PDA

View Full Version : Rotation in 2 axes

Rav89
09-09-2009, 04:31 PM
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;

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

_x57_
09-10-2009, 02:04 AM
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 M*R1*R2. When a vertex is transformed the result is M*R1*R2*x = 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.

MaxH
09-10-2009, 10:38 AM
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.