2012-03-25 32 views
8

Estoy creando un proyecto muy simple en OpenGL y estoy atascado con las rotaciones. Intento rotar un objeto indepentientemente en los 3 ejes: X, Y y Z. He tenido noches de insomnio debido al problema de "bloqueo del cardán" después de haber rotado alrededor de un eje. Luego aprendí que los cuaterniones resolverían mi problema. Investigué sobre cuaterniones y lo implementé, pero no he podido convertir mis rotaciones en cuaterniones. Por ejemplo, si quiero rotar alrededor del eje Z 90 grados, simplemente creo el vector {0,0,1} para mi cuaternión y lo giro alrededor de ese eje 90 grados usando el código aquí:Cómo encontrar el vector para el cuaternión de X Y Z rotaciones

http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-7_04.html (el más matriz complicada hacia la parte inferior)

Eso está bien para un vector, pero, por ejemplo, primero quiero rotar 90 grados alrededor de Z, luego 90 grados alrededor de X (solo como ejemplo). ¿Qué vector debo pasar? ¿Cómo puedo calcular ese vector? No soy bueno con las matrices y la trigonometría (conozco los conceptos básicos y las reglas generales, pero no soy un genio) pero necesito terminar esto. Hay MUCHOS tutoriales sobre cuaterniones, pero parece que no entiendo ninguno (o no responden a mi pregunta). Solo necesito aprender a construir el vector para rotaciones alrededor de más de un eje combinado.

ACTUALIZACIÓN: he encontrado esta página bueno de cuaterniones y decidió ponerlas en práctica esta manera: http://www.cprogramming.com/tutorial/3d/quaternions.html

Aquí está mi código para la multiplicación de cuaterniones:

void cube::quatmul(float* q1, float* q2, float* resultRef){ 
float w = q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3]; 
float x = q1[0]*q2[1] + q1[1]*q2[0] + q1[2]*q2[3] - q1[3]*q2[2]; 
float y = q1[0]*q2[2] - q1[1]*q2[3] + q1[2]*q2[0] + q1[3]*q2[1]; 
float z = q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1] + q1[3]*q2[0]; 

resultRef[0] = w; 
resultRef[1] = x; 
resultRef[2] = y; 
resultRef[3] = z; 
} 

Aquí está mi código de aplicando un quaternion a mi matriz de vista de modelo (tengo una variable tmodelview que es mi matriz de vista de modelo objetivo):

void cube::applyquat(){ 
float& x = quaternion[1]; 
float& y = quaternion[2]; 
float& z = quaternion[3]; 
float& w = quaternion[0]; 
float magnitude = sqrtf(w * w + x * x + y * y + z * z); 
if(magnitude == 0){ 
    x = 1; 
    w = y = z = 0; 
}else 
if(magnitude != 1){ 
    x /= magnitude; 
    y /= magnitude; 
    z /= magnitude; 
    w /= magnitude; 
    } 

tmodelview[0] = 1 - (2 * y * y) - (2 * z * z); 
tmodelview[1] = 2 * x * y + 2 * w * z; 
tmodelview[2] = 2 * x * z - 2 * w * y; 
tmodelview[3] = 0; 

tmodelview[4] = 2 * x * y - 2 * w * z; 
tmodelview[5] = 1 - (2 * x * x) - (2 * z * z); 
tmodelview[6] = 2 * y * z - 2 * w * x; 
tmodelview[7] = 0; 

tmodelview[8] = 2 * x * z + 2 * w * y; 
tmodelview[9] = 2 * y * z + 2 * w * x; 
tmodelview[10] = 1 - (2 * x * x) - (2 * y * y); 
tmodelview[11] = 0; 

glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadMatrixf(tmodelview); 
glMultMatrixf(modelview); 
glGetFloatv(GL_MODELVIEW_MATRIX, tmodelview); 
glPopMatrix(); 
} 

Y mi código para la rotación (que llamo desde el exterior), donde quaternion es una variable de clase del cubo:

void cube::rotatex(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = sinf(ang/2); 
quat[2] = 0; 
quat[3] = 0; 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

void cube::rotatey(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = 0; 
quat[2] = sinf(ang/2); 
quat[3] = 0; 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

void cube::rotatez(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = 0; 
quat[2] = 0; 
quat[3] = sinf(ang/2); 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

que llamo, dicen rotatex, por 10-11 veces para girar solamente 1 grado, pero mi el cubo se gira casi 90 grados después de 10-11 veces de 1 grado, lo cual no tiene sentido. Además, después de llamar funciones de rotación en diferentes ejes, mi cubo se sesga, se vuelve bidimensional y desaparece (una columna en la matriz de vista de modelo se convierte en ceros) irreversiblemente, lo que obviamente no debería ocurrir con una implementación correcta de los cuaterniones.

+0

¿Desea ayuda con los cuaterniones o con la rotación de un objeto? – Beta

+0

Bueno, me he ido con la ruta de los cuaterniones y escribí el código, por lo que sería útil si tienes una solución que involucre cuaterniones para la rotación. lo que simplemente necesito implementar es poder rotar un objeto con 3 grados de libertad en el espacio 3D –

+0

Quizás el libro "Quaternions and Rotations Sequences" de Jack Kuipers pueda ayudarte. Hay mucho que decir acerca de las rotaciones X-Y-Z (también conocidas como ángulos de Euler). Por ejemplo, ¿está girando alrededor del antiguo eje X o el nuevo (el eje "unido" al objeto que está girando)? – ascobol

Respuesta

7

Te estás acercando de esta manera incorrecta. Si tiene tres rotaciones de ángulo de Euler para los ejes X, Y y Z, convertirlas en un cuaternión y luego en una matriz no lo ayudará. El bloqueo cardánico se produce debido a la representación de la rotación deseada. Si almacena la rotación que desea como ángulos de Euler X-Y-Z, obtendrá el bloqueo de Gimbal.

Necesita almacenar su orientación deseada como cuaternión para obtener las ventajas. Es decir, es posible tomar una orientación actual como un cuaternión y luego hacer la pregunta "¿cómo rotar eso alrededor del eje Z en 90 grados y usar eso como mi nueva orientación?", Pero no es útil preguntar "mi actual la orientación está definida por estos ángulos XYZ Euler, ¿cómo puedo convertir eso en un cuaternión? ".

Un tratamiento completo de las partes relevantes de los cuaterniones sería bastante largo. This site may help you out. Vale la pena señalar que el sitio al que se vinculó parece estar hablando realmente de rotaciones de ángulo de eje, no de cuaterniones.

Editar: El código que envió es correcto, excepto que las señales para tmodelview[6] y tmodelview[9] están equivocados.

+0

gracias. Entiendo que necesito guardar mi orientación (por lo tanto, un cuaternión), y olvidarme de los ángulos en esa. su enlace es bastante útil, pero una cosa que todavía no entiendo es la pregunta de la que está hablando: "¿cómo giro eso alrededor del eje Z en 90 grados y lo uso como mi nueva orientación?" –

+3

Multiplicación de Quaternion. Si tiene un cuaternión 'q' que se refiere a su orientación actual, y un cuaternión' r' que es una rotación alrededor del eje Z en 90 grados, entonces el cuaternión 'r * q' es su nueva orientación. Un paralelo exacto a la multiplicación de la matriz, realmente. –

+0

estaré investigando –

Cuestiones relacionadas