Eu tenho uma realização simples do mecanismo de jogo entidade / componente.
O componente Transform possui métodos para definir a posição local, rotação local, posição global e rotação global.
Se a transformação está sendo definida como nova posição global, a posição local também muda, para atualizar a posição local. Nesse caso, estou apenas aplicando a matriz local de transformação atual à matriz mundial de transformação dos pais.
Até então, não tenho problemas, posso obter a matriz de transformação local atualizada.
Mas estou lutando para atualizar a posição local e o valor de rotação na transformação. A única solução que tenho em mente é extrair os valores de conversão e rotação do localMatrix de transform.
Para tradução, é bem fácil - eu apenas uso os valores da quarta coluna. mas e a rotação?
Como extrair ângulos de Euler da matriz de transformação?
Essa solução está correta ?:
Para encontrar a rotação em torno do eixo Z, podemos encontrar diferença entre o vetor do eixo X do localTransform e o vetor do eixo X do pai.localTransform e armazenar o resultado no Delta, então: localRotation.z = atan2 (Delta.y, Delta .x);
O mesmo para rotação em torno de X e Y, basta trocar de eixo.
Há um ótimo artigo sobre esse processo de Mike Day: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf
Agora também está implementado no glm, a partir da versão 0.9.7.0, 02/08/2015. Confira a implementação .
Para entender a matemática, você deve examinar os valores que estão na sua matriz de rotação. Além disso, você precisa saber a ordem em que as rotações foram aplicadas para criar sua matriz para extrair adequadamente os valores.
Uma matriz de rotação dos ângulos de Euler é formada pela combinação de rotações em torno dos eixos x, y e z. Por exemplo, girar θ graus em torno de Z pode ser feito com a matriz
Existem matrizes semelhantes para girar sobre os eixos X e Y:
Podemos multiplicar essas matrizes para criar uma matriz que é o resultado de todas as três rotações. É importante observar que a ordem em que essas matrizes são multiplicadas é importante, porque a multiplicação da matriz não é comutativa . Isso significa isso
Rx*Ry*Rz ≠ Rz*Ry*Rx
. Vamos considerar uma ordem de rotação possível, zyx. Quando as três matrizes são combinadas, resulta em uma matriz que se parece com isso:onde
Cx
é o cosseno dox
ângulo de rotação,Sx
é o seno dox
ângulo de rotação, etc.Agora, o desafio é extrair o original
x
,y
ez
os valores que entraram na matriz.Vamos primeiro entender o
x
ângulo. Se conhecemos osin(x)
ecos(x)
, podemos usar a função inversa da tangenteatan2
para nos devolver o ângulo. Infelizmente, esses valores não aparecem sozinhos em nossa matriz. Mas, se dermos uma olhada mais atenta nos elementosM[1][2]
eM[2][2]
, podemos ver que sabemos-sin(x)*cos(y)
tambémcos(x)*cos(y)
. Como a função tangente é a razão entre os lados oposto e adjacente de um triângulo, escalar os dois valores na mesma quantidade (nesse casocos(y)
) produzirá o mesmo resultado. Portanto,Agora vamos tentar obter
y
. Nós sabemossin(y)
deM[0][2]
. Se tivéssemos cos (y), poderíamos usaratan2
novamente, mas não temos esse valor em nossa matriz. No entanto, devido à identidade pitagórica , sabemos que:Então, podemos calcular
y
:Por último, precisamos calcular
z
. É aqui que a abordagem de Mike Day difere da resposta anterior. Como neste momento sabemos a quantidadex
e ay
rotação, podemos construir uma matriz de rotação XY e encontrar a quantidade dez
rotação necessária para corresponder à matriz de destino. ARxRy
matriz fica assim:Como sabemos que
RxRy
*Rz
é igual à nossa matriz de entradaM
, podemos usar essa matriz para retornar aRz
:O inverso de uma matriz de rotação é sua transposição , para que possamos expandir isso para:
Agora podemos resolver
sinZ
ecosZ
realizar a multiplicação da matriz. Nós só precisamos calcular os elementos[1][0]
e[1][1]
.Aqui está uma implementação completa para referência:
fonte
M[1][3]
comM[1][2]
eM[2][3]
comM[2][2]
.