Quaternions

I’m using quaternions for 3d look but i found strange thing - when rotating around x axis and turned to negative z axis i move look up and down as i want but when I turn to positive z axis and then rotatine around x axis I get reversed look(when it should turn up it turns down) and if I turn 90 degrees on y axis then moving up or down it twists view(probably rotation on z axis) Where can the bug be ?


…when rotating around x axis and turned to negative z axis i move look up and down as i want but when I turn to positive z axis and then rotatine around x axis I get reversed look…

Vlasko,

Which freedom does your quat axis constrain, the left-right or up-down? How are you determining the up vector for left-right rotation? How are you rotating around the other axis, and how are you combining this rotation with your quaternion? Your description is a tad on the sparse side. :slight_smile:

I think your problem is that you’re rotating around the axis of the absolute opengl coordinate frame rather than your current coordinate frame.
If you’re turned toward the positive Z-axis, the X-axis of the camera-coordinate frame will be the opposite of the X-axis from the absolute opengl coordinate frame.
This explains why turning up-down is reversed when rotating 180 degrees.

Try doing a premultiplication of your modelviewmatrix instead of the standard OpenGL postmultiplication.

So change:

glMatrixMode(GL_MODELVIEW);
glRotatef(90.,1.0,0.,0.);

into:

GLfloat matrix;

glMatrixMode(GL_MODELVIEW);
glGetFloatv(GL_MODELVIEW_MATRIX,matrix);
glLoadIdentity();
glRotatef(90.,1.0,0.,0.);
glMultMatrixf(matrix);

Hope this fixes your problem

N.

Multiplication solved problem with rotations but created new one with position calculation

I better post some of my code to get clear

 
void CalculateNewPos(float time)
{
	float x_velocity;
	float xz_velocity;
	float y_velocity;
	float z_velocity;
	float rad_x;
	float rad_y;
	QUATERNION Qx;
	QUATERNION Qy;
	QUATERNION Qz;
	QUATERNION Qxy;
	rad_x=(float)my_position.rot_x/180.0f*PI;
	rad_y=(float)my_position.rot_y/180.0f*PI;
	y_velocity=-1.0f*(float)sin((double)rad_x)*my_position.velocity;	
	xz_velocity=(float)cos((double)rad_x)*my_position.velocity;
	z_velocity=-1.0f*(float)cos((double)rad_y)*xz_velocity;
	x_velocity=(float)sin((double)rad_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(rad_x/2.0f);
	Qx.x=-(float)sin(rad_x/2.0f);
	Qx.y=0;
	Qx.z=0;
	NormalizeQuaternion(&Qx);
	Qy.w=(float)cos(rad_y/2.0f);
	Qy.x=0;
	Qy.y=-(float)sin(rad_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 DrawGLScene()
{
	float matrix[16]; 
	double deltat;
	deltat=GetTime();
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	//glGetFloatv(GL_MODELVIEW_MATRIX,&matrix[0]);
	glLoadIdentity();
	CalculateNewPos((float)deltat);
	glLoadMatrixf(&MY_VIEW.matrix[0]);
	glTranslatef(-1.0f*my_position.x,-1.0f*my_position.y,-1.0f*my_position.z);
	//glMultMatrixf(&matrix[0]);
	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();
}

 

Commented is premultiplication

In this part of your code

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
CalculateNewPos((float)deltat);
glLoadMatrixf(&MY_VIEW.matrix[0]);
glTranslatef(-1.0f*my_position.x,-1.0f*my_position.y,-1.0f*my_position.z);

the translation is defined relative to the absolute openGL coordinate frame due to postmultiplication.
When you put it in premultiplication, the translation is defined relative to the camera coordinate frame and not relative to the frame in which the vertices of your objects were defined.

In this case, change your code to

glMatrixMode(GL_MODELVIEW);
glGetFloatv(GL_MODELVIEW_MATRIX,&matrix[0]);
glLoadIdentity();
CalculateNewPos((float)deltat);
glLoadMatrixf(&MY_VIEW.matrix[0]);
glMultMatrixf(&matrix[0]);
glTranslatef(-1.0f*my_position.x,-1.0f*my_position.y,-1.0f*my_position.z) 

Hmm shouldn’t then the calculations of rotation angles be relative to last frame insted of relative to origin(as I’m using now)?

Have a look at

http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=10

It’s tutorial about moving in a 3d world. This is one of many ways to do it.

N.