Estou tentando escrever código para transferir animações que foram projetadas para um esqueleto parecer correto em outro esqueleto. As animações de origem consistem apenas em rotações, exceto as traduções na raiz (são as animações mocap do banco de dados de captura de movimento da CMU ). Muitos aplicativos 3D (por exemplo, o Maya) possuem esse recurso embutido, mas estou tentando escrever uma versão (muito simples) dele para o meu jogo.
Eu fiz algum trabalho no mapeamento ósseo e, como os esqueletos são hierarquicamente semelhantes (bípedes), eu posso fazer o mapeamento ósseo 1: 1 para tudo, exceto a coluna vertebral (pode trabalhar nisso posteriormente). O problema, no entanto, é que as posições base do esqueleto / atadura são diferentes e os ossos têm escalas diferentes (mais curtas / mais longas), por isso, se eu apenas copiar a rotação diretamente, parecerá muito estranho.
Tentei várias coisas semelhantes à solução de lorancou abaixo sem sucesso (ou seja, multiplicar cada quadro na animação por um multiplicador específico de osso). Se alguém tiver algum recurso em coisas como esta (documentos, código fonte, etc), isso seria realmente útil.
fonte
Respostas:
O problema era de estabilidade numérica. Aproximadamente 30 horas de trabalho nisso ao longo de 2 meses, apenas para descobrir que eu estava fazendo isso desde o início. Quando orto-normalizei as matrizes de rotação antes de conectá-las ao código de retarget, a solução simples de multiplicar a origem * inversa (destino) funcionou perfeitamente. Obviamente, há muito mais para redirecionar do que isso (em particular, levando em consideração as diferentes formas do esqueleto, como largura dos ombros, etc.). Aqui está o código que estou usando para a abordagem simples e ingênua, se alguém estiver curioso:
fonte
Acredito que a sua opção mais fácil é simplesmente combinar a pose de ligação original com o seu novo esqueleto, se você tiver a possibilidade (se o seu novo esqueleto ainda não estiver esfolado).
Se você não pode fazer isso, aqui está algo que você pode tentar. Isso é apenas intuição, provavelmente estou ignorando muitas coisas, mas isso pode ajudá-lo a encontrar a luz. Para cada osso:
Em seu "velho" pose bind, você tem um quaternion que descreve a relação de rotação deste osso em comparação com seu pai osso. Aqui está uma dica de como encontrá-lo. Vamos chamá-lo
q_old
.Ibid. para a sua "nova" pose de ligação, vamos chamá-la
q_new
.Você pode encontrar a rotação relativa da "nova" pose de ligação à "velha" posição de posição, conforme descrito aqui . É isso
q_new_to_old = inverse(q_new) * q_old
.Então, em uma chave de animação, você tem seu único quaternion que transforma esse osso da pose de ligação "antiga" em uma pose animada. Vamos chamar este aqui
q_anim
.Em vez de usar
q_anim
diretamente, tente usarq_new_to_old * q_anim
. Isso deve "cancelar" as diferenças de orientação entre as poses de ligação, antes de aplicar a animação.Pode fazer o truque.
EDITAR
Seu código acima parece seguir a lógica que estou descrevendo aqui, mas algo está invertido. Em vez de fazer isso:
Você pode tentar isso:
Eu acho que você precisa transformar do seu destino na sua fonte antes de aplicar a animação de origem, para obter a mesma orientação final.
fonte