GLM: Euler Angles to Quaternion

12

Espero que sepas GL Mathematics ( GLM ) porque tengo un problema, no puedo romper:

Tengo un conjunto de ángulos de Euler y necesito realizar una interpolación suave entre ellos. La mejor manera es convertirlos a Quaternions y aplicar el alrogirthm SLERP.

El problema que tengo es cómo inicializar glm :: quaternion con Euler Angles, ¿por favor?

Leí una y otra vez la documentación de GLM , pero no encuentro la adecuada Quaternion constructor signature, eso requeriría tres ángulos de Euler. La más cercana que encontré es la función angleAxis () , que toma el valor del ángulo y un eje para ese ángulo. Tenga en cuenta, por favor, lo que estoy buscando de alguna manera, cómo analizar RotX, RotY, RotZ.


Para su información, esta es la firma de la función angleAxis () mencionada anteriormente :

detail::tquat< valType > angleAxis (valType const &angle, valType const &x, valType const &y, valType const &z)
Bunkai.Satori
fuente

Respuestas:

13

No estoy familiarizado con GLM, pero en ausencia de una función para convertir directamente los ángulos de Euler en cuaterniones, puede utilizar las funciones de "rotación alrededor de un eje" (como "angleAxis").

Aquí se explica cómo (pseudocódigo):

Quaternion QuatAroundX = Quaternion( Vector3(1.0,0.0,0.0), EulerAngle.x );
Quaternion QuatAroundY = Quaternion( Vector3(0.0,1.0,0.0), EulerAngle.y );
Quaternion QuatAroundZ = Quaternion( Vector3(0.0,0.0,1.0), EulerAngle.z );
Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ;

(O puede que necesite cambiar esas multiplicaciones de cuaterniones, dependiendo del orden en el que se pretende aplicar las rotaciones de ángulo de Euler)

Alternativamente, al mirar a través de la documentación de GLM, parece que puede convertir los ángulos de Euler -> matrix3 -> quaternion de esta manera:

toQuat( orient3( EulerAngles ) )
Trevor Powell
fuente
buena respuesta porque es menos ambiguo sobre el orden de aplicación.
Richard Fabian
@Trevor: +1, Hola Trevor, gracias por tu buena respuesta. Esta parece ser la solución más práctica aquí. Puedo cambiar fácilmente entre el orden de multiplicación de rotación. Posiblemente, el número de combinaciones es la razón, por qué la conversión de ángulo de Euler a Quaterion no está disponible en GLM.
Bunkai.Satori
Aunque todas las respuestas son buenas y valiosas, en mi opinión, esta es la más práctica. Me gustaría marcarlo como la respuesta aceptada .
Bunkai.Satori
@Trevor: En Quaternion finalOrientation = QuatAroundX * QuatAroundY * QuatAroundZ ;, ¿qué tipo de multiplicación has querido decir? Me sorprende que GLM no se sobrecargue operator *para la multiplicación de Quaternion, por lo que posiblemente tendré que realizar la multiplicación manualmente .
Bunkai.Satori
3
@Bunkai, el concepto de multiplicación de cuaterniones es similar a la multiplicación de matrices, no es ni punto ni producto cruzado. Si desea comprender el uso de los cuaterniones, entonces acostúmbrese a las matrices y entienda los ángulos de los ejes, su concepto básico es bastante similar a los cuaterniones, las matemáticas son un poco más avanzadas, pero una vez que comprende los ángulos de los ejes, los cuaterniones no son lejos ya.
Maik Semder
16
glm::quat myquaternion = glm::quat(glm::vec3(angle.x, angle.y, angle.z));

Donde anglehay un tono queglm::vec3 contiene , guiñada, rodar respectivamente.

PD. En caso de duda, solo ve a los encabezados y mira. La definición se puede encontrar en glm / gtc / quaternion.hpp:

explicit tquat(tvec3<T> const & eulerAngles) {
        tvec3<T> c = glm::cos(eulerAngle * value_type(0.5));
    tvec3<T> s = glm::sin(eulerAngle * value_type(0.5));

    this->w = c.x * c.y * c.z + s.x * s.y * s.z;
    this->x = s.x * c.y * c.z - c.x * s.y * s.z;
    this->y = c.x * s.y * c.z + s.x * c.y * s.z;
    this->z = c.x * c.y * s.z - s.x * s.y * c.z;    
}

¿Para dónde quates un tipo flotante tquat?

caviar desacelerado
fuente
Eso es bastante ambiguo, ¿en qué orden se aplicarían? Los Eulers son rotaciones ordenadas y al constructor de quaternion aquí no parece importarle eso.
Richard Fabian
La definición de la función es exactamente la misma que la suya; Lo publiqué en mi respuesta si importaba.
deceleratedcaviar
no el orden de los argumentos, el orden de aplicación de la rotación. Mi respuesta contiene el pedido XYZ, tomado del artículo de Wikipedia, sin embargo, utilizamos el pedido ZYX de la aplicación en mi empresa anterior, y YZX en la actual. el ángulo x sigue siendo el primer valor en la lista de vectores / argumentos en todos los casos, pero la transformación resultante real no es la misma.
Richard Fabian
Arreglé mi respuesta para la rotación Qat, para que pueda ver cómo podría cambiar fácilmente el orden. Por defecto acepta XYZ, pero puede cambiarlo fácilmente.
deceleratedcaviar
2
-1 por no mencionar el orden de rotación, que es muy importante para la pregunta
Maik Semder
7

La solución está en wikipedia: http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles

usando eso:

sx = sin(x/2); sy = sin(y/2); sz = sin(z/2);
cx = cos(x/2); cy = cos(y/2); cz = cos(z/2);

q( cx*cy*cz + sx*sy*sz,
   sx*cy*cz - cx*sy*sz,
   cx*sy*cz + sx*cy*sz,
   cx*cy*sz - sx*sy*cz ) // for XYZ application order

q( cx*cy*cz - sx*sy*sz,
   sx*cy*cz + cx*sy*sz,
   cx*sy*cz - sx*cy*sz,
   cx*cy*sz + sx*sy*cz ) // for ZYX application order

Constructores para un cuaternión, dado un Euler (donde la aplicación de rotación es XYZ o ZYX). Sin embargo, son solo dos de las seis combinaciones posibles de ángulos de Euler. Realmente necesita averiguar en qué orden se construyen los ángulos de Euler al convertir a matriz de transformación. Solo entonces se puede definir la solución.

En la antigua empresa en la que trabajaba, teníamos Z como reenvío (como la mayoría de las tarjetas gráficas), por lo que el orden de la aplicación era ZYX, y en mi compañía actual el eje Y está hacia adelante y Z está arriba, por lo que nuestro orden de aplicación es YZX. Este orden es el orden en el que multiplicas tus cuaterniones para generar tu transformación final, y el orden de las rotaciones es que las multiplicaciones no son conmutativas.

Richard Fabian
fuente
1
+1, hola y gracias por una excelente respuesta. Cuando uso OpenGL , el valor Z sale de la pantalla. En mi aplicación realizo el orden de multiplicación ZYX . Originalmente, pensé que GLM tiene esta funcionalidad disponible, pero veo que aún no la han implementado, por lo que una alternativa es crear la conversión manualmente , como me recomiendan.
Bunkai.Satori
Esta es la mejor respuesta aquí.
plasmacel
1
vec3 myEuler (fAngle[0],fAngle[1],fAngle[2]);
glm::quat myQuat (myEuler);

¡El ángulo debe estar en radianes!

Carlos
fuente
2
¿Era esto una broma? ¿O simplemente no leíste las otras respuestas (especialmente las de Daniel)?
Chris dice reinstalar a Mónica el