A partir da descrição do seu problema, parece que o cerne da questão pode ser que sua representação esteja perdendo dados no momento. Um osso não é simplesmente o vetor de uma articulação para a próxima - é uma matriz de transformação completa que representa a orientação da estrutura local, seja com relação ao espaço do mundo ou com relação à estrutura local do próximo osso 'na cadeia' . Por exemplo, imagine um personagem com uma cicatriz no antebraço; ter o vetor do cotovelo do personagem até o pulso indica onde a mão será posicionada, mas não contém informações suficientes para que você saiba onde estaria a cicatriz - por exemplo, se está apontando para cima ou para baixo. Essas informações de orientação devem fazer parte do seu esqueleto de origem.
Depois de ter as coisas representadas em termos de quadros de orientação local completos e não simplesmente vetores direcionais, o restante das informações deve cair facilmente; exatamente como você sugeriu em seu post, você usaria inversos de matriz para 'descolar' as camadas de suas transformações e chegar à matriz suculenta M no meio. Por exemplo, se você tiver childAbs = childRel * M * selfRel * parentAbs, multiplique por childRel -1 à esquerda de ambos os lados e parentAbs -1 * selfRel -1 à direita de ambos os lados para obter M = childRel - 1 * childAbs * parentAbs -1 * selfRel -1. Observe que a inversão de um produto de matrizes altera a ordem em que seus inversos são multiplicados, de modo que a ordem é importante aqui - (A * B) -1 não é (em geral) igual a A -1 * B -1 , mas sim a B -1 * A -1 .
Depois de obter sua matriz M, deve haver muita informação na Web sobre como convertê-la em um quaternion; se você estiver procurando por ajuda com essa etapa específica, avise-me e eu posso detalhar isso com alguns links, mas parece que existem vários outros problemas que você precisará resolver agora mesmo antes de precisar considere isso.
Edição: Depois de alguns dias para pensar sobre isso, escrevi essa descrição aproximada do processo de passar do espaço mundial para as informações locais; espero que isso ajude a esclarecer um pouco mais.
Vou trabalhar em termos de um esquema dissociado em que cada osso consiste em uma matriz de rotação e um deslocamento; a matriz de rotação é aplicada na raiz do osso e o deslocamento é dado nas coordenadas locais do osso. Isso faz duas coisas importantes:
- Ele permite que vários ossos sejam anexados ao mesmo encaixe, facilitando um pouco a árvore esquelética - por exemplo, as clavículas podem ser facilmente presas a um ponto central entre as omoplatas ou os ossos dos dedos a um ponto central do pulso.
- Isso significa que a maioria das animações de um osso pode ser feita apenas alterando a rotação associada a esse osso; por exemplo, um bíceps pode ser movido alterando sua orientação, fazendo com que a localização do cotovelo seja deslocada. De fato, os ossos geralmente terão um deslocamento de (0, 0, L), onde L é o comprimento do osso - a extremidade mais distante do osso está diretamente ao longo do eixo Z local a partir do ponto de fixação do osso.
Essa não é necessariamente a abordagem que eu recomendaria para a implementação, mas é a mais direta para falar sobre como fazê-lo; Embora os resultados precisos não sejam diretamente aplicáveis à sua situação, o IMHO é realmente o melhor: oferece melhores chances de entender como a derivação funciona e como derivar as fórmulas precisas que serão aplicadas à sua própria versão do problema.
Algumas definições rápidas das quantidades com as quais estamos trabalhando: Um sobrescrito de 'w' designa um valor do espaço no mundo, enquanto 'l' indica um valor local. Usaremos P para posição e R para rotação; por exemplo, a P w osso seria a posição alvo espaço de mundo de um osso, (em oposição à sua posição de base, que, naturalmente, é a posição do alvo da sua mãe), enquanto que R l osso seria a orientação local do osso - que é como é girado em relação ao quadro de seu pai.
Agora, considerando isso, podemos derivar a posição de destino e a orientação de qualquer articulação - como alguns dos comentários sugerem, o relacionamento é recursivo. Em particular, temos
R w filho = R w pai * R l filho
e
P w filho = P w pai + R w filho * P l filho
(Eles dizem, respectivamente, 'A orientação mundial da criança é sua orientação local composta pela orientação mundial de seus pais' e 'A posição mundial da criança é a posição mundial de seus pais compensada por seu deslocamento local (conforme traduzido no apropriado coordenadas do worldspace) '.)
Diante disso, podemos agora resolver estas equações para encontrar os parâmetros do osso - ou seja, R l e P l - em termos dos dados WorldSpace que nos são dadas. Isso também dá outra razão pela qual precisamos não apenas da posição, mas também da orientação do espaço mundial de todas as juntas; é um componente essencial para a solução.
Encontrar a orientação local é simples; podemos apenas multiplicar ambos os lados da nossa equação de orientação pelo inverso da orientação do espaço no mundo dos pais, obtendo
R l filho = R w pai -1 * R w filho
O deslocamento local também é relativamente fácil de entender, já que sabemos o deslocamento no espaço mundial e a matriz de transformação para ir do espaço local para o espaço mundial (o que significa que sabemos que a matriz deve seguir o outro caminho):
P l filho = R w filho -1 * (P w filho - P w pai )
Observe uma coisa também: nenhuma dessas equações depende da posição ou orientação local do osso parental, apenas dos valores do espaço mundial para o pai e o filho - portanto, enquanto eles se sentem recursivos (e o cálculo para encontrar os valores do espaço mundial para os ossos) precisa ir da raiz do esqueleto até as folhas devido às dependências dos resultados) eles podem realmente ser feitos em qualquer ordem.
Espero que isso lhe dê uma idéia melhor do que está acontecendo - é fácil ficar atolado em todas as transformações que estão por aí. Avise-me se isso ajudar!