Tengo un Vector3 que tiene un ángulo de Euler para cada eje.
Por lo general, cuando quiero crear una matriz de rotación, usaré funciones como D3DXMatrixRotationX que pasa el ángulo respectivo desde mi vector de rotación anterior y multiplico las matrices (ZXY) para crear la matriz de rotación general que se usa para formar la matriz de transformación de objetos completa.
Sin embargo, este método producirá un conjunto de rotaciones en el espacio del objeto. Es decir, pasar un vector de (90, 0, 90) a mi método creará efectivamente una rotación en el espacio mundial de (90, 90, 0).
¿Hay alguna manera de garantizar siempre que cada componente de mi vector de rotación dé como resultado una rotación alrededor de los respectivos ejes alineados con el espacio mundial?
EDITAR:
Esta es una animación de lo que está sucediendo actualmente: quiero una forma de rotar alrededor de los ejes azules, no los rojos.
EDITAR 2:
Solo para tener en cuenta que no estoy buscando una solución que implique los ángulos de Euler, sino simplemente una forma en que pueda representar una transformación de múltiples rotaciones alrededor de los ejes del mundo.
fuente
Respuestas:
Según sus comentarios, parece que está almacenando la orientación del objeto como un conjunto de ángulos de Euler y disminuyendo / disminuyendo los ángulos cuando el jugador gira el objeto. Es decir, tienes algo como este pseudocódigo:
Como señala Charles Beattie , debido a que las rotaciones no conmutan, esto no funcionará como se espera a menos que el jugador rote el objeto en el mismo orden en que
eulerAnglesToMatrix()
aplica las rotaciones.En particular, considere la siguiente secuencia de rotaciones:
En la ingenua representación de ángulo de Euler, como se implementa en el pseudocódigo anterior, estas rotaciones se cancelarán y el objeto volverá a su orientación original. En el mundo real, esto no sucede: si no me crees, toma un dado de seis lados o un cubo de Rubik, deja que x = y = 90 °, ¡y pruébalo tú mismo!
La solución, como notas en tu propia respuesta , es almacenar la orientación del objeto como una matriz de rotación (o un cuaternión) y actualizar esa matriz en función de las aportaciones del usuario. Es decir, en lugar del pseudocódigo anterior, haría algo como esto:
(Técnicamente, dado que cualquier matriz de rotación o cuaternión se puede representar como un conjunto de ángulos de Euler, es posible usarlos para almacenar la orientación del objeto. Pero la regla físicamente correcta para combinar dos rotaciones secuenciales, cada una representada como ángulos de Euler, en una sola rotación es bastante complicado, y esencialmente equivale a convertir las rotaciones en matrices / cuaterniones, multiplicarlas y luego convertir el resultado nuevamente en ángulos de Euler).
fuente
El problema con las rotaciones es que la mayoría de las personas piensan en términos de ángulos de Euler, ya que son fáciles de entender.
Sin embargo, la mayoría de la gente olvida el punto de que Euler se inclina son tres ángulos secuenciales . Esto significa que la rotación alrededor del primer eje hará que la siguiente rotación sea relativa a la primera rotación original, por lo tanto, no puede rotar independientemente un vector alrededor de cada uno de los 3 ejes usando ángulos de Euler.
Esto se traduce directamente en matrices cuando multiplica dos matrices, puede pensar que esta multiplicación transforma una matriz en el espacio de la otra matriz.
Esto debe suceder con 3 rotaciones secuenciales, incluso cuando se usan cuaterniones.
Quiero enfatizar el hecho de que los cuaterniones no son una solución para el bloqueo de gimble. En realidad, el bloqueo de gimble siempre sucederá si representó ángulos de Euler usando cuaterniones. El problema no es la representación, el problema es la 3 pasos secuenciales.
¿La solución?
La solución para rotar un vector alrededor de 3 ejes independientemente es combinarlo en un solo eje y un solo ángulo, de esta manera puede deshacerse del paso en el que tiene que hacer una multiplicación secuencial. Esto se traducirá efectivamente en:
Mi matriz de rotación representa el resultado de la rotación alrededor de X e Y y Z.
en lugar de la interpretación de Euler de
Mi matriz de rotación representa la rotación alrededor de X, luego Y y luego Z.
Para aclarar esto, citaré del teorema de rotación de Euler de Wikipedia:
Tenga en cuenta que multiplicar 3 matrices siempre representará 3 rotaciones secuenciales.
Ahora para combinar rotaciones alrededor de 3 ejes, debe obtener un solo eje y ángulos únicos que representen la rotación alrededor de X, Y, Z. En otras palabras, debe usar una representación de eje / ángulo o cuaternión para deshacerse de las rotaciones secuenciales.
Esto generalmente se hace, comenzando con una orientación inicial (la orientación puede considerarse como un ángulo de eje), generalmente representada como un cuaternión o un ángulo de eje, y luego modificando esa orientación para representar su orientación de destino. Por ejemplo, comienza con el quaterion de identidad y luego gira por la diferencia para llegar a la orientación de destino. De esta manera no pierdes ningún grado de libertad.
fuente
Cambiar una combinación de rotaciones del espacio de objetos al espacio mundial es trivial: solo tiene que invertir el orden en que se aplican las rotaciones.
En su caso, en lugar de multiplicar matrices
Z × X × Y
, solo necesita calcularY × X × Z
.Se puede encontrar una razón para esto en Wikipedia: conversión entre rotaciones intrínsecas y extrínsecas .
fuente
Z
(espacio del objeto), luego 50 grados alrededorX
(espacio del objeto), luego 45 grados alrededorY
(espacio del objeto). Esto es exactamente lo mismo que una rotación de 45 grados alrededorY
( espacio mundial ), luego 50 grados alrededorX
( espacio mundial ), luego 50 grados alrededorZ
( espacio mundial ).Proporcionaré mi solución como respuesta hasta que alguien pueda explicar por qué funciona.
Cada render estaba reconstruyendo mi quaternion usando los ángulos almacenados en mi vector de rotación y luego aplicando el quaternion a mi transformación final.
Sin embargo, para mantenerlo alrededor de los ejes mundiales, tuve que retener el cuaternión en todos los cuadros y solo rotar objetos usando una diferencia de ángulo, es decir ...
(Detallado para readiblity)
Creo que dsilva.vinicius estaba tratando de llegar a este punto.
fuente
Deberá almacenar el orden de las rotaciones.
Almacene su matriz de rotación actual y premultiply cada rotación como vienen.
fuente
Además de la respuesta @ concept3d, puede usar 3 matrices de rotación extrínsecas para rotar alrededor del eje en coordenadas mundiales. Citando de Wikipedia :
Entonces, lo que necesita es invertir el orden de las rotaciones en relación con lo que haría utilizando rotaciones intrínsecas (o espacio local). @Syntac solicitó una rotación zxy, por lo que deberíamos hacer una rotación extrínseca yxz para lograr el mismo resultado. El código está abajo:
Explicación de los valores de la matriz aquí .
Este código es didáctico, no óptimo, ya que podría reutilizar varias matrices D3DXMATRIX.
fuente