Estoy tratando de escribir código para transferir animaciones que fueron diseñadas para que un esqueleto se vea correcto en otro esqueleto. Las animaciones de origen consisten solo en rotaciones, excepto las traducciones en la raíz (son las animaciones mocap de la base de datos de captura de movimiento de CMU ). Muchas aplicaciones 3D (por ejemplo, Maya) tienen esta facilidad incorporada, pero estoy tratando de escribir una versión (muy simple) para mi juego.
He trabajado un poco en el mapeo óseo, y debido a que los esqueletos son jerárquicamente similares (bípedos), puedo hacer un mapeo óseo 1: 1 para todo menos la columna vertebral (puede trabajar en eso más adelante). El problema, sin embargo, es que las posturas del esqueleto base / unión son diferentes, y los huesos son escalas diferentes (más cortas / más largas), por lo que si copio la rotación directamente, parece muy extraño.
He intentado una serie de cosas similares a la solución de lorancou a continuación en vano (es decir, multiplicando cada cuadro en la animación por un multiplicador específico de hueso). Si alguien tiene recursos sobre cosas como esta (documentos, código fuente, etc.), eso sería realmente útil.
fuente
Respuestas:
El problema era uno de estabilidad numérica. Aproximadamente 30 horas de trabajo en esto en el transcurso de 2 meses, solo para descubrir que lo estaba haciendo desde el principio. Cuando orto-normalicé las matrices de rotación antes de conectarlas al código de retarget, la solución simple de multiplicar fuente * inversa (objetivo) funcionó perfectamente. Por supuesto, hay mucho más para reorientar que eso (en particular, teniendo en cuenta las diferentes formas del esqueleto, es decir, el ancho de los hombros, etc.). Aquí está el código que estoy usando para el enfoque simple, ingenuo, si alguien tiene curiosidad:
fuente
Creo que su opción más fácil es simplemente hacer coincidir la postura de enlace original con su nuevo esqueleto si tiene la posibilidad (si su nuevo esqueleto aún no está desollado).
Si no puedes hacer eso, aquí hay algo que puedes probar. Esto es solo intuición, probablemente estoy pasando por alto muchas cosas, pero podría ayudarte a encontrar la luz. Para cada hueso:
En su "viejo" pose se unen, usted tiene un cuaternión que describe la relación de rotación de este hueso en comparación con su matriz ósea. Aquí hay una pista sobre cómo encontrarlo. Digamos que es
q_old
.Ibídem. para su "nueva" postura de enlace, llamémosla
q_new
.Puede encontrar la rotación relativa de la pose de enlace "nueva" a la pose de bin "antigua", como se describe aquí . Eso es
q_new_to_old = inverse(q_new) * q_old
.Luego, en una clave de animación, tienes tu quaternion que transforma ese hueso de la pose de enlace "antigua" a una pose animada. Llamemos a este
q_anim
.En lugar de usar
q_anim
directamente, intente usarq_new_to_old * q_anim
. Esto debería "cancelar" las diferencias de orientación entre las posturas de enlace, antes de aplicar la animación.Podría hacer el truco.
EDITAR
Su código anterior parece seguir la lógica que describo aquí, pero algo está invertido. En lugar de hacer esto:
Podrías probar eso:
Creo que debe transformarse de su destino a su fuente antes de aplicar la animación de origen, para obtener la misma orientación final.
fuente