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.
¿Desea ayuda con los cuaterniones o con la rotación de un objeto? – Beta
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 –
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