2009-10-12 22 views

Respuesta

27

El siguiente código se basa en un cuaternión (QW, qx, qy, QZ), donde el orden se basa en los cuaterniones Boost:

boost::math::quaternion<float> quaternion; 
float qw = quaternion.R_component_1(); 
float qx = quaternion.R_component_2(); 
float qy = quaternion.R_component_3(); 
float qz = quaternion.R_component_4(); 

primer lugar hay que normalizar el cuaternión:

const float n = 1.0f/sqrt(qx*qx+qy*qy+qz*qz+qw*qw); 
qx *= n; 
qy *= n; 
qz *= n; 
qw *= n; 

continuación, puede crear y nuestra matriz:

Matrix<float, 4>(
    1.0f - 2.0f*qy*qy - 2.0f*qz*qz, 2.0f*qx*qy - 2.0f*qz*qw, 2.0f*qx*qz + 2.0f*qy*qw, 0.0f, 
    2.0f*qx*qy + 2.0f*qz*qw, 1.0f - 2.0f*qx*qx - 2.0f*qz*qz, 2.0f*qy*qz - 2.0f*qx*qw, 0.0f, 
    2.0f*qx*qz - 2.0f*qy*qw, 2.0f*qy*qz + 2.0f*qx*qw, 1.0f - 2.0f*qx*qx - 2.0f*qy*qy, 0.0f, 
    0.0f, 0.0f, 0.0f, 1.0f); 

Dependiendo de su clase de matriz, es posible que tenga que transponerla antes de pasarla a OpenGL.

+0

fyi this parece una interpretación de fila mayor, para cualquiera que mire esto. Debería funcionar, como sucede al pasar a OpenGL, ya que los resultados column-major y row-major generan la misma matriz lineal. Sin embargo, si utiliza esto con una biblioteca column-major para multiplicar con otra matriz, podría tener problemas dependiendo de cómo funciona su biblioteca. – johnbakers

+0

Agradable. Así que el impulso puede hacer prácticamente todo lo que estoy buscando. –

+0

Vea también: http://stackoverflow.com/questions/1274936/flipping-a-quaternion-from-right-to-left-handed-coordianates que menciona que los cuaterniones NO tienen lateralidad, sino que las matrices HACEN. Así que puede que tenga que modificar 6 celdas de la transformación anterior, conjugarlas por orden. Celdas 21,31,32,12,13,23. (Aparte de eso, acabo de pegar este código y cambié ligeramente para mi biblioteca en particular, y funcionó muy bien. ¡Gracias!) –

9

Una forma de hacerlo, lo cual es bastante fácil de visualizar, es aplicar la rotación especificada por su cuaternión a los vectores de base (1,0,0), (0,1,0) y (0,0,1). Los valores girados dan los vectores de base en el sistema girado en relación con el sistema original. Utilice estos vectores para formar las filas de la matriz de rotación. La matriz resultante, y su transposición, representan las transformaciones directa e inversa entre el sistema original y el sistema rotado .

no estoy familiarizado con las convenciones utilizadas por OpenGL, por lo que tal vez alguien más puede responder que parte de su pregunta ...

+0

Sí me olvidó que podía hacer esto ... Voy a darle una oportunidad – Polaris878

+0

matemáticamente correcto, pero computacionalmente más caro hacerlo así. – teodron

+0

Lo probaría, porque esta versión usa instrucciones que podrían ser específicas para algunos hardware (estoy pensando específicamente en sombreadores de GPU), así que aunque es probable, no estaría tan seguro de que sea más costoso computacionalmente ... –

3

Puede que no tenga que ocuparse de una matriz de rotación. Aquí está una manera que parece ser más rápido que la conversión a una matriz y la multiplicación de un vector con él:

// move vector to camera position co (before or after rotation depending on the goal) 
    v -= co; 

    // rotate vector v by quaternion q; see info [1] 
    vec3 t = 2 * cross(q.xyz, v); 
    v = v + q.w * t + cross(q.xyz, t); 

[1] http://mollyrocket.com/forums/viewtopic.php?t=833&sid=3a84e00a70ccb046cfc87ac39881a3d0

+0

El enlace está muerto. – Dan

0

usando GLM, sólo tiene que utilizar un operador de fundición. así convertir de un matrix4 a cuaternión, sólo tiene que escribir

GLM :: mat4_cast (quaternion_name)

Cuestiones relacionadas