Как найти вектор для кватерниона из вращений X Y Z

Я создаю очень простой проект на OpenGL. и я застрял с вращениями. Я пытаюсь вращать объект независимо друг от друга по всем 3 осям:X, Y и Z. У меня были бессонные ночи из-за проблемы с «карданным замком» после вращения вокруг одной оси. Затем я узнал, что кватернионы решат мою проблему. Я исследовал кватернионы и реализовал их, но не смог преобразовать свои вращения в кватернионы. Например, если я хочу повернуть вокруг оси Z на 90 градусов, я просто создаю вектор {0,0,1} для моего кватерниона и поворачиваю его вокруг этой оси на 90 градусов, используя код здесь:

http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-7_04.html(самая сложная матрица в направлении снизу)

Это нормально для одного вектора, но, скажем, я сначала хочу повернуть на 90 градусов вокруг Z, а затем на 90 градусов вокруг X (просто для примера). Какой вектор мне нужно передать? Как вычислить этот вектор. Я плохо разбираюсь в матрицах и тригонометрии (Я знаю основы и общие правила, но я просто не гений), но мне нужно это сделать. Существует МНОГО руководств по кватернионам, но я, кажется, ни в одном не разбираюсь (или они не отвечают на мой вопрос). Мне просто нужно научиться строить вектор для вращения вокруг более чем одной оси вместе взятых.

ОБНОВЛЕНИЕ:Я нашел эту замечательную страницу о кватернионах и решил реализовать их таким образом:http://www.cprogramming.com/tutorial/3d/quaternions.html

Вот мой код для умножения кватернионов:

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;
}

Вот мой код для применения кватерниона к моей матрице представления модели (У меня есть tmodelviewпеременная, которая является моей целевой матрицей представления модели):

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();
}

И мой код для вращения (, который я вызываю извне), где quaternion— переменная класса куба :

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();
}

, которую я вызываю, скажем rotatex, для 10-11 раз для поворота только на 1 градус,но мой куб поворачивается почти на 90 градусов после 10-11 раз по 1 градусу, что не имеет смысла. Кроме того, после вызова функций вращения по разным осям, Мой куб искажается, становится двумерным и исчезает (столбец в матрице представления модели необратимо становится полностью нулевым), чего, очевидно, не должно происходить при правильной реализации кватернионы.

8
задан Can Poyrazoğlu 27 March 2012 в 18:43
поделиться