Original Post
I want to make a 3d freelook game so I''m doing it with quaternions.Before I did know about Gimbal lock I used glulookat() and everything was working.Now with quaternions rotations are ok but only if I''m not moving then strange things happen - objects are moving in wrong ways and so on.What could cause such problems ?
Code:
void CalculateNewPos(float time)
{
float x_velocity;
float xz_velocity;
float y_velocity;
float z_velocity;
QUATERNION Qx;
QUATERNION Qy;
QUATERNION Qz;
QUATERNION Qxy;
y_velocity=(float)sin((double)my_position.rot_x)*my_position.velocity;
xz_velocity=(float)cos((double)my_position.rot_x)*my_position.velocity;
z_velocity=-1.0f*(float)cos((double)my_position.rot_y)*xz_velocity;
x_velocity=(float)sin((double)my_position.rot_y)*xz_velocity;
my_position.x+=x_velocity*time;
my_position.y+=y_velocity*time;
my_position.z+=z_velocity*time;
Qx.w=(float)cos(my_position.rot_x/2.0f);
Qx.x=(float)sin(my_position.rot_x/2.0f);
Qx.y=0;
Qx.z=0;
NormalizeQuaternion(&Qx);
Qy.w=(float)cos(my_position.rot_y/2.0f);
Qy.x=0;
Qy.y=(float)sin(my_position.rot_y/2.0f);
Qy.z=0;
NormalizeQuaternion(&Qy);
Qz.w=(float)cos(0);
Qz.x=0;
Qz.y=0;
Qz.z=(float)sin(0);
NormalizeQuaternion(&Qz);
Qxy=MultiplyQuaternion(Qx,Qy);
NormalizeQuaternion(&Qxy);
MY_VIEW.Qxyz=MultiplyQuaternion(Qxy,Qz);
NormalizeQuaternion(&MY_VIEW.Qxyz);
QuatToMatrix(MY_VIEW.Qxyz,&MY_VIEW.matrix[0]);
}
void CalculateTranspose()
{
MY_VIEW.transpose_matrix[0]=MY_VIEW.matrix[0];
MY_VIEW.transpose_matrix[1]=MY_VIEW.matrix[4];
MY_VIEW.transpose_matrix[2]=MY_VIEW.matrix[8];
MY_VIEW.transpose_matrix[3]=MY_VIEW.matrix[12];
MY_VIEW.transpose_matrix[4]=MY_VIEW.matrix[1];
MY_VIEW.transpose_matrix[5]=MY_VIEW.matrix[5];
MY_VIEW.transpose_matrix[6]=MY_VIEW.matrix[9];
MY_VIEW.transpose_matrix[7]=MY_VIEW.matrix[13];
MY_VIEW.transpose_matrix[8]=MY_VIEW.matrix[2];
MY_VIEW.transpose_matrix[9]=MY_VIEW.matrix[6];
MY_VIEW.transpose_matrix[10]=MY_VIEW.matrix[10];
MY_VIEW.transpose_matrix[11]=MY_VIEW.matrix[14];
MY_VIEW.transpose_matrix[12]=MY_VIEW.matrix[3];
MY_VIEW.transpose_matrix[13]=MY_VIEW.matrix[7];
MY_VIEW.transpose_matrix[14]=MY_VIEW.matrix[11];
MY_VIEW.transpose_matrix[15]=MY_VIEW.matrix[15];
}
void DrawGLScene()
{
double deltat;
deltat=GetTime();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
CalculateNewPos((float)deltat);
CalculateTranspose();
glMultMatrixf((const float*)&MY_VIEW.transpose_matrix[0]);
glTranslatef(-1.0f*my_position.x,-1.0f*my_position.y,-1.0f*my_position.z);
DrawSkybox();
glPushMatrix();
glTranslatef(EARTH->x,EARTH->y,EARTH->z);
ShowObject(EARTH->model);
glPopMatrix();
glPushMatrix();
glDisable(GL_CULL_FACE);
glTranslatef(0.0f,0.0f,5.0f);
glBegin(GL_TRIANGLES);
glVertex3f(-2.0f,-2.0f,0.0f);
glVertex3f(2.0f,-2.0f,0.0f);
glVertex3f(0.0f,2.0f,0.0f);
glEnd();
glEnable(GL_CULL_FACE);
glPopMatrix();
}
and some of quaternions functions:
QUATERNION MultiplyQuaternion(QUATERNION Q1,QUATERNION Q2)
{
QUATERNION final;
final.w=Q1.w*Q2.w-Q1.x*Q2.x-Q1.y*Q2.y-Q1.z*Q2.z;
final.x=Q1.w*Q2.x+Q1.x*Q2.w+Q1.y*Q2.z-Q1.z*Q2.y;
final.y=Q1.w*Q2.y+Q1.y*Q2.w+Q1.z*Q2.x-Q1.x*Q2.z;
final.z=Q1.w*Q2.z+Q1.z*Q2.w+Q1.x*Q2.y-Q1.y*Q2.x;
return final;
}
void NormalizeQuaternion(QUATERNION* Q)
{
float normal;
normal=(float)sqrt(Q->w*Q->w+Q->x*Q->x+Q->y*Q->y+Q->z*Q->z);
Q->w/=normal;
Q->x/=normal;
Q->y/=normal;
Q->z/=normal;
}
void QuatToMatrix(QUATERNION Q,float* matrix)
{
int i=0;
*matrix=1.0f-2.0f*Q.y*Q.y-2.0f*Q.z*Q.z;
*(matrix+1)=2.0f*Q.x*Q.y-2.0f*Q.w*Q.z;
*(matrix+2)=2.0f*Q.x*Q.z+2.0f*Q.w*Q.y;
*(matrix+3)=0.0f;
*(matrix+4)=2.0f*Q.x*Q.y+2.0f*Q.w*Q.z;
*(matrix+5)=1.0f-2.0f*Q.x*Q.x-2.0f*Q.z*Q.z;
*(matrix+6)=2.0f*Q.y*Q.z-2.0f*Q.w*Q.x;
*(matrix+7)=0.0f;
*(matrix+8)=2.0f*Q.x*Q.z-2.0f*Q.w*Q.y;
*(matrix+9)=2.0f*Q.y*Q.z+2.0f*Q.w*Q.x;
*(matrix+10)=1.0f-2.0f*Q.x*Q.x-2.0f*Q.y*Q.y;
*(matrix+11)=0.0f;
*(matrix+12)=0.0f;
*(matrix+13)=0.0f;
*(matrix+14)=0.0f;
*(matrix+15)=1.0f;
for(i=0;i<16;i++)
{
if((*(matrix+i)<0.00001f) && *(matrix+i)>-0.00001f)
*(matrix+i)=0;
}
}