rotation

from what i understand about rotation in opengl, the only option is to rotate around an axis. if you want to create a free floating object, such as a spaceship, then adjust the yaw n degrees, you can not adjust the pitch because your rotation will go around the original x axis, not the new axis. the only realistic solution i found was to convert the angles to a quaternion. although this works, it appears to be a lot of work on the processor when using multiple objects.
the first time i realized what was happening, i tried to do a glpushmatrix, assuming it would reset the x,y,z angles to 0 in the new space, which would all still be angled, therefore allowing me to angle in another direction.
glrotatef(45,1,0,0)
glpushmatrix
glrotatef(45,0,1,0)
glpushmatrix
glrotatef(40,0,0,1)
draw the object
glpopmatrix
glpopmatrix
…etc
i tried many other methods and calculations to adjust for the angle change but had no luck. i still do not understand why the pushmatrix doesn’t work. also, how hard would it be to make another rotate function that does the quaternions built in to opengl?

The only way for the glPushMatrix() method to work is if the object is centered around (0,0,0). So before you do any rotations, make sure that the object is centered around (0,0,0) and then translate to its real position. Even if you did not call glTranslate*() before glRotate*(), the center of rotation is not necessarilly (0,0,0).

Go to the program that drew the spaceship or whatever object you’re using and find the coordinates of the center of the object. The following code should work, assuming x,y, and z hold the coordinates of your object:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-x,-y,-z);
glRotatef(xrot,1,0,0);
glRotatef(yrot,0,1,0);
glRotatef(zrot,0,0,1);
/* draw object */

If you don’t want to load the identity matrix, you must find the current coordinates of the object’s center of rotation, say tx,ty, and tz.
Then you do this instead:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-x-tx,-y-ty,-z-tz);
glRotatef(xrot,1,0,0);
glRotatef(yrot,0,1,0);
glRotatef(zrot,0,0,1);
/* draw object */

I hope this helps.

glPushMatrix only pushes the matrix upon the matrix stack, but doesn’t change it. to reset it, you have to use glLoadIdentify(). and before that, one normally uses glpushmatrix to prevent the current matrix from getting lost.

the original problem was not pushing the matrix stack, i just thought that might be a simple answer to a more complex problem. the problem is rotating an object freely opun it’s OWN axis, i also saw this referred to as “local rotation” by someone else. the glrotatef function only rotates around the set x,y,z axis, not depending on the previous rotation.
glrotatef(45,1,0,0) rotates around x axis
glrotatef(45,0,0,1) rotates around z axis
what i want is
MYrotate(45,1,0,0) rotates around x-axis
MYrotate(45,0,0,1) rotates around the NEW axis created by the previous x-rotation
(this allows pitching nose up instead of unpredictibly twisting and turning around the old z-axis)
or any other simpler method.
i’ve seen a lot of message boards and webpages about this problem that all come to the solution of using quaternions. my question is is there a simpler mathematical way, or a way using opengl functions, and if not, why isn’t it implemented into opengl?

i had a misconception of exactly what the conversion from euler angles to quaternions did, i finally got the functions working on my program and i did not get the result i anticipated. now i am totally baffled on how to freely rotate an object. i notice that if you do it one axis at a time, the last one you put is independent, the second is dependent on the last, and the first causes major problems.

thanks fork and jan for helping my understanding of glpushmatrix and loadidentity, i implemented that into my code and for some reason it still would not rotate around the new axis.

i believe the problem is because the glrotatef function was made to set a perspective on the scene, and not to do free-rotation on an object.

…time passes…

i tried a new search for more information and still can not find how to do this, many looked like they might do it, but i couldn’t find a working sample.

this has to be a fairly common problem, it seems that the solution would be readily available, i don’t understand why i’m having so much trouble here.

[This message has been edited by adams_antics (edited 08-15-2003).]

http://www.gametutorials.com/Tutorials/opengl/OpenGL_Pg4.htm

Check out the ‘Quaternions’ tutorial, I think it might be what you’re looking for (not quite sure).

You should look up the chapter on matrices in the red book. It explains in there a number of things. The order of your glRotate, glScale, and glTranslates makes a huge difference. To rotate an object about it’s own origin, you simply do something like…

glTranslate(object position);
glRotate(object orientation);

If for some reason the origin of your model isn’t actually the point you want to rotate about, you need to do something like…

glTranslate(offset from object origin);
glRotate(object orientation);
glTranslate(negative offset from object origin);

Just think about it this way… due to the way the matrices are multiplied, the last matrix operation you perform, is actually the one that occurs first.

[This message has been edited by Deiussum (edited 08-15-2003).]

Re-read your post and my explanation probably isn’t quite what you’re looking for. There’s a couple of ways to do what you want. One of them involves quaternions, which I am ashamed to admit, I know little about. I think you basically can use them to help determine the rotation about an arbitrary axis. So in this case, you would have a single glRotate with the angle and axis to rotate about.

The method I generally use is to keep a rotation matrix. Then for each new rotation applied, I PRE-multiply the new rotation matrix to my current rotation matrix. Then instead of using glRotate to apply the rotation, I just use glMultMatrix.

Function EtoQRotate(x As GLfloat, y As GLfloat, z As GLfloat)

Dim q As tQuaternion
Dim aa As tQuaternion 'axisangle
EulerToQuaternion x, y, z, q
QuatToAxisAngle q, aa
glRotatef aa.w, aa.x, aa.y, aa.z

End Function

this function appears to work fine.
then during my rendering, i draw one using the normal x,y,z rotations, then another one using the quaternion rotation, both draw the jet at the same angle.

  glPushMatrix
    glTranslatef -20, 0, 0
    glRotatef .aRoll, 0, 0, 1
    glRotatef .aYaw, 0, 1, 0
    glRotatef .aPitch, 1, 0, 0
    DrawWalls 30, True, False
    DrawJet
  glPopMatrix
  
  glPushMatrix
    glTranslatef 20, 0, 0
    EtoQRotate .aPitch, .aYaw, .aRoll
    DrawJet
    DrawWalls 30, True, False
  glPopMatrix

the drawwalls function is something i made to draw either axes or a grid-wall at a given radius, it is irrelevant here.
i put a screenshot of the output at http://www.neotheism.org/images/rotation.jpg
the translation was just to seperate the images and has no effect on the rotation, they do the same thing with no translation

Should you not get different results?

I think that the problem with Euler angles is that a rotation will go around the new axis and not the original axis. A link with a explanation and solution. http://www.sjbaker.org/steve/omniv/eulers_are_evil.html

Some comments about the page and the keep a rotation matrix solution:

  • Steve Baker talks about inverting the matrix but that should only be done if you are changing the view, the camera. Dont invert if youre rotating an object.
  • He mentions that you need to check the scale because of accumulated rounding errors. You also need to make sure that its orthogonal, this can be done with the crossproduct function.
  • The recommendation to check the matrix for rounding errors is in my opinion too strict. If the check is done for every 1000 matrix should that be enough.

Like Deiussum and many others do I prefer this method over quaternions.

It sounds a lot like you’re trying to write a flight model, where the aircraft orientation is updated incrementally each frame. I’ve got a flight model that stores the aircraft orientation as a quaternion called “rot_quat.” It get’s updated each frame like this:

// Update aircraft rotation
tfwQuat temp_quat;
// p (rotation about aircraft’s x axis)
temp_quat.make(dt * p, 1.0, 0.0, 0.0);
rot_quat.preMult(temp_quat);
// q (rotation about aircraft’s y axis)
temp_quat.make(dt * q, 0.0, 1.0, 0.0);
rot_quat.preMult(temp_quat);
// r (rotation about aircraft’s z axis)
temp_quat.make(dt * r, 0.0, 0.0, 1.0);
rot_quat.preMult(temp_quat);

Then you can convert rot_quat to a matrix or euler angles if you need them. Of course, you’ll need some quaternion math routines for this, but it sound like you might already have some…

could you send me some sample code? preferrably vb6 or vc6. the way i have mine set up right now is
left/right arrow adjust yaw
a,z adjust pitch
s,x adjust roll
up and down arrows are forward and back, that is another problem i run into, but i have to solve the rotation problem first.

ok mogumbo, i didn’t get to read your post until now. i am not at home so i can’t try that, but i think my mistake was keeping up with the angles as euler then converting them every time, which obviously would just give the same output, but i was not sure what to expect. i’ll try fixing it when i get home.

I browsed the web and found some pages that can be interesting:

A general guide to set the ModelView matrix with VB
A Monkey’s Guide to Matrices http://is6.pacific.net.hk/~edx/matrices.htm

C Code samples http://www.uku.fi/~tronkko/g5-examples.html
showing how to fix the matrix from rounding errors http://www.uku.fi/~tronkko/rebuild.c

Steve Baker has a library with useful functions http://plib.sourceforge.net/sg/