Tengo una comprensión simple del motor de juego de entidad / componente.
El componente de transformación tiene métodos para establecer la posición local, la rotación local, la posición global y la rotación global.
Si transform se establece en una nueva posición global, entonces la posición local también cambia, para actualizar la posición local en ese caso, solo estoy aplicando la matriz local de transformación actual a la matriz mundial de transformación de los padres.
Hasta entonces no tengo problemas, puedo obtener una matriz de transformación local actualizada.
Pero estoy luchando sobre cómo actualizar la posición local y el valor de rotación en la transformación. La única solución que tengo en mente es extraer los valores de traducción y rotación de la Matriz local de transformación.
Para la traducción es bastante fácil: solo tomo los valores de la cuarta columna. ¿Pero qué hay de la rotación?
¿Cómo extraer los ángulos de Euler de la matriz de transformación?
¿Es correcta esta solución ?:
Para encontrar la rotación alrededor del eje Z, podemos encontrar la diferencia entre el vector del eje X de localTransform y el vector del eje X de parent.localTransform y almacenar el resultado en Delta, luego: localRotation.z = atan2 (Delta.y, Delta .X);
Lo mismo para la rotación alrededor de X e Y, solo necesita cambiar el eje.
Hay un gran comentario sobre este proceso por Mike Day: https://d3cw3dd2w32x2b.cloudfront.net/wp-content/uploads/2012/07/euler-angles1.pdf
Ahora también se implementa en glm, a partir de la versión 0.9.7.0, 08/02/2015. Echa un vistazo a la implementación .
Para comprender las matemáticas, debe mirar los valores que están en su matriz de rotación. Además, debe conocer el orden en el que se aplicaron las rotaciones para crear su matriz y extraer los valores correctamente.
Se forma una matriz de rotación desde los ángulos de Euler combinando rotaciones alrededor de los ejes x, y y z. Por ejemplo, la rotación de θ grados alrededor de Z se puede hacer con la matriz
Existen matrices similares para rotar alrededor de los ejes X e Y:
Podemos multiplicar estas matrices para crear una matriz que sea el resultado de las tres rotaciones. Es importante tener en cuenta que el orden en que estas matrices se multiplican juntas es importante, porque la multiplicación de matrices no es conmutativa . Esto significa que
Rx*Ry*Rz ≠ Rz*Ry*Rx
. Consideremos un posible orden de rotación, zyx. Cuando se combinan las tres matrices, se obtiene una matriz similar a esta:donde
Cx
está el coseno delx
ángulo de rotación,Sx
es el seno delx
ángulo de rotación, etc.Ahora, el reto consiste en extraer el original
x
,y
yz
los valores que entraron en la matriz.Primero saquemos el
x
ángulo. Si conocemos elsin(x)
ycos(x)
, podemos usar la función de tangente inversaatan2
para devolvernos nuestro ángulo. Desafortunadamente, esos valores no aparecen por sí mismos en nuestra matriz. Pero, si miramos más de cerca los elementosM[1][2]
yM[2][2]
, podemos ver que sabemos-sin(x)*cos(y)
tan bien comocos(x)*cos(y)
. Dado que la función tangente es la razón de los lados opuestos y adyacentes de un triángulo, al escalar ambos valores en la misma cantidad (en este casocos(y)
) se obtendrá el mismo resultado. Así,Ahora intentemos llegar
y
. Lo sabemossin(y)
porM[0][2]
. Si tuviéramos cos (y), podríamos usarloatan2
nuevamente, pero no tenemos ese valor en nuestra matriz. Sin embargo, debido a la identidad pitagórica , sabemos que:Entonces, podemos calcular
y
:Por último, necesitamos calcular
z
. Aquí es donde el enfoque de Mike Day difiere de la respuesta anterior. Como en este punto sabemos la cantidadx
y lay
rotación, podemos construir una matriz de rotación XY y encontrar la cantidad dez
rotación necesaria para que coincida con la matriz objetivo. LaRxRy
matriz se ve así:Como sabemos que
RxRy
*Rz
es igual a nuestra matriz de entradaM
, podemos usar esta matriz para volver aRz
:La inversa de una matriz de rotación es su transposición , por lo que podemos expandir esto a:
Ahora podemos resolver
sinZ
ycosZ
realizar la multiplicación de matrices. Solo necesitamos calcular los elementos[1][0]
y[1][1]
.Aquí hay una implementación completa para referencia:
fuente
M[1][3]
conM[1][2]
yM[2][3]
conM[2][2]
.