Rotation in 2 axes

At the beginning I want to apologize for my english.

I’m making my first own game. I’ve got a virtual world and a sphere that can be moved along x-axis and z-axis in this world. I want the sphere to rotate while it’s moving so I added to it’s class float variables “RotateX” and “RotateZ” that are the angles I want the sphere to be rotated as effect of moving along the x-axis (rotate about the z-axis) or along the z-axis (rotate about the x-axis).

This is how I count them:


Vec3f posDiff = position - oldPos;
rotateX -= posDiff[0]/(2*PI*radius) * 360;
rotateZ += posDiff[2]/(2*PI*radius) * 360;

while (rotateX < 0) rotateX+=360;
while (rotateZ < 0) rotateZ+=360;

while (rotateX > 360) rotateX-=360;
while (rotateZ > 360) rotateZ-=360;

At the beginning both rotateX and rotateZ are 0.0f.
Vec3f is a class type - a vector of 3 float variables - that I downloaded from http://www.videotutorialsrock.com/opengl_tutorial/vec3f/video.php

Before drawing the sphere I firstly used this lines to rotate the sphere:

glRotatef(rotateX, 0.0f, 0.0f, 1.0f);
glRotatef(rotateZ, 1.0f, 0.0f, 0.0f);

But of course it didn’t work as I wanted it to - and I think I know why. That’s because after the first glRotatef the x-axis rotated and the second glRotatef rotated the object along the new x-axis (whereas I wanted it to rotate along the “original” x-axis).

Then I hit on idea - I tried to do the second rotation about the “original” x-axis by giving as arguments the coordinates of vector I got after rotating it by rotateX degrees - but in the opposite direction.

This is why I used this lines:


glRotatef(rotateX, 0.0f, 0.0f, 1.0f);
Vec3f aux = rotate(Vec3f(1.0f, 0.0f, 0.0f), Vec3f(0.0f, 0.0f, 1.0f), rotateX);
glRotatef(rotateZ, aux[0], aux[1], aux[2]);

where rotate function is:


//Rotates the vector by the indicated number of degrees about the specified axis
Vec3f rotate(Vec3f v, Vec3f axis, float degrees)
{
	axis = axis.normalize();
	float radians = degrees * PI / 180;
	float s = sin(radians);
	float c = cos(radians);
	return v * c + axis * axis.dot(v) * (1 - c) + v.cross(axis) * s;
}

I draw it on the paper and it looked right.
And…rotating about the x-axis was working right this time…but rotating about the z-axis stopped working right instead and I don’t know why.

I googled about my problem and I found a few topics about similiar problems on discussion boards but without a solution.

How can I make the rotation working as I want it to?

I did not re-check everything, but i think in general your idea of doing the second rotation about another axis is good.

But what you are doing here


glRotatef(rotateX, 0.0f, 0.0f, 1.0f);
Vec3f aux = rotate(Vec3f(1.0f, 0.0f, 0.0f), Vec3f(0.0f, 0.0f, 1.0f), rotateX);
glRotatef(rotateZ, aux[0], aux[1], aux[2]);

rotates “rotateZ” degrees about aux FIRST and AFTER THAT it rotates “rotateX” debrees about (0,0,1). This is because the glRotate call creates a Rotation Matrix R and multiplies it from the RIGHT to the current Matrix M. Thus, if you start with a matrix M on the modelview stack the sequence

glRotate(R1)
glRotate(R2)

creates the overall transformation MR1R2. When a vertex is transformed the result is MR1R2x = M(R1*(R2*x)) and you see that the second rotate call is applied to x first. This holds for all transformation calls in opengl.

So what you mean is probably more like:

//find old z axis by undoing the first x transform
Vec3f aux = rotate(Vec3f(0.0f, 0.0f, 1.0f), Vec3f(1.0f, 0.0f, 0.0f), -1.0*rotateX);

glRotatef(rotateZ, aux[0], aux[1], aux[2]); //second rotate about new z axis
glRotatef(rotateX, 1.0f, 0.0f, 0.0f); //first rotate about x

As i said i did no double checking, so be careful with my proposal… but i think this should point in the right direction.

There have been other threads similar to this one recently. I posted a demo program (C and glut) that shows how to do what you are asking (if I understand you correctly). Look at the thread below.

MaxH Rotations Demo

Thank you very much :slight_smile:
The main problem was I thaught the order of rotations about the “global” axes is not important - and I was wrong. When I discovered it, by rotating the ping-pong ball in my hand, I understood I have to change my algorithm absolutely. I implemented a new way to rotate the ball and it still didn’t work.

But thanks to your demo I discovered that I only have to change the order of glRotatef and glMultMatrixf. I did it and now it’s working :slight_smile: So thank you very much again!