Skip to main content
GameDev.net gamedev.net
🔒 Locked

Quaternion problem

Started by vlasko Apr 27, 2004 at 4:28 PM 4 replies 600+ views
Original Post
vlasko
vlasko
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; } }
Charles B
Charles B
I can''t see anything wrong reading the code. What you do is using intermediate quats for a typical Euler to Matrix conversion.

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 ?

I don''t understand this sentence. Is iot going weird when you move or when you don''t ? Whern you move I suppose.

A common mistake is using unconsistant referentials between the displacements and the view. I suppose it''s due to the transposition stuff or when you compute the x_velocity. Basically a question of sign error on the angles.

Try to remove the y rotation first and see what happens, branching things again one by one step by step. Else use an asserted Euler to Matrix code found somewhere on the www.
"Coding math tricks in asm is more fun than Java"
jvsquare
jvsquare
It looks like you''re transposing the view-to-world matrix, instead of inverting it. If you have a translation, i.e. you move around, that would give some odd results like you''re reporting.
vlasko
vlasko
To Charles B:
I think it''s the y rotation when I removed it it was ok-but I don''t actually understand what you wrote before(hmm probably my english)
To jvsquare:
Yes I''m transposing matrix to get inverted rotation matrix and then translating - I don''t see anything wrong there
vlasko
vlasko
To Charles B:
I think it''s the y rotation when I removed it it was ok-but I don''t actually understand what you wrote before(hmm probably my english)
To jvsquare:
Yes I''m transposing matrix to get inverted rotation matrix and then translating - I don''t see anything wrong there
vlasko
vlasko
It works now it was just signs problem(not even quaternion related)Shame on me :-) Thanks everyone

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.