Simple world space rotation?

Started by
22 comments, last by VanKurt 19 years, 7 months ago
The problem is pretty simple and its a common one. Because the rotations that opengl uses are cumulative by rotating on the x-axis you also change the direction of the z-axis. This means that simulating rolling is tricky. You can get the rotation around one axis perfectly, but the other axis ends up pointing in some awkward direction so that your rotation looks weird.
The commonly offered solution is to use quaternions or use matrices. These are both potential solutions to the problem. However, as I explain above you have to use them correctly. The way you are currently using quaternions is equivalent to an Euler representation, that is you store a quaternion for the x rotation and a quaternion for the z rotation. This suffers from the exact same limitations as before because at some point you still call
glMultMatrix(x rotation stuff)
glMultMatrix(z rotation stuff)
and this is identical to what you had before. The solution is to realize that quaternions don't just represent an angle, they represent an angle around an axis. Thus it is possible to code the entire rotation of the ball into a single quaternion ie
quaternion BallRot;
then you simple call
glMultMatrix(BallRot.Matrix());
or the equivalent commands.
In order to change this rotation you need to calculate a quaternion containing the change in the balls rotation. For example if the ball rolls right, thus rolling about the z axis you have something like
quaternion Rot(angle, 0,0,1);
then you concatenate that rotation with the existing rotation of the ball - something like
BallRot*=Rot;
this won't work exactly because I don't know how you quaternion class is set up - you may have to do something like
BallRot = Rot*BallRot*Rot'
and even then it may be backwards since quaternion multiplication is commutative.
In short, the calculations here are not exactly correct and will not work as I have typed them. However, they express the basic idea of what you need to do. If I have a chance I may be able to write out some working functional code, but at the moment I am a bit short on time.

I hope this helps.
Advertisement
Just for a sanity check,I wrote this small piece of code following my suggestion(minor change:I used z-axis for spinning) and it worked fine.Left/right change orientation and UP moves the ball.

float orient=0.0;float spin=0.0;double ox=0;double oy=0;double oz=0;double eyex=0;double eyey=8;double eyez=0;GLUquadricObj *sphere;void RenderScene(){glClearColor(1,0,0,0);glClearDepth(1.0);glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glViewport(0,0,RES_X,RES_Y);GL_SetFrustum(fov,0.1,100);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glRotatef(90.0,1,0,0);glTranslatef(-eyex,-eyey,-eyez);gluQuadricTexture(sphere,1);glPushMatrix();glTranslatef(ox,oy,oz);glRotatef(orient,0,1,0);glRotatef(spin,0,0,1);gluSphere(sphere,0.5,10,10);glPopMatrix();if (GetAsyncKeyState(VK_RIGHT)<0) orient=orient-2.0;if (GetAsyncKeyState(VK_LEFT)<0) orient=orient+2.0;if (GetAsyncKeyState(VK_UP)<0){ox=ox+0.05*cos(degtorad(orient));oz=oz-0.05*sin(degtorad(orient));spin=spin-1;}}


Hope that helps.
But you are taking advantage of the behavior that is causing the problem. You have the lines
glRotatef(orient,0,1,0);glRotatef(spin,0,0,1);

which rely on the fact that the spin rotation depends on the orient rotation. It does indeed avoid the problem but doesn't solve it.
I think what VanKurt wants to do (and if I'm wrong forgive me, its been a long day) is to to use the right, left, up and down arrows to move the ball in the appropriate direction. In this case you need independent rotations around the world X and Z axis, and the best way I know of to do this is not to use Euler angles to store the ball's rotation.

edit - its [ source ] not
Yep, that's right! And now it works!!!! :-D
Thanks soooo much, guys! You're great!!!

Having one quat per ball and changing this from frame to frame (not generating a new one every time) did the job.

Man, that feels so good ;-)

This topic is closed to new replies.

Advertisement