PDA

View Full Version : Real rotations.



MatthewL
06-22-2004, 04:48 PM
Hi!

Woops, I have a nasty problem!
See, I have a few 3D objects in memory,
each having a position, axis and pivot point stored with them.

What I'm trying to do obviously is rotate those objects around an X,Y,Z pivot point first, and then position them in the scene, rotated, to a given point.
So I can rotate limbs of a character around a pivot point for example, and still have the limb located at a given position (ie. an arm is located beneath a shoulder).

I'm having trouble pulling this off :(

Could anyone explain how to go about doing this please?

Thanks in advance!

endash
06-22-2004, 05:44 PM
(This belongs in the beginner forum)

Think carefully about the order of translation and rotation operations. If I have my head screwed on the right way around, you want to translate the origin to your character, then draw it. As part of drawing it, you'll translate to each major joint, like the hip, then draw the leg, translating down the leg, and rotating for the knee, etc.

MatthewL
06-22-2004, 07:30 PM
Thanks for the reply!

(I placed this post in the Beginner's section, but quickly deleted it and reposted here because I thought it was in the wrong place. ;) )

I'm having trouble figuring out the order of glTranslate/glRotate calls to be able to rotate around a pivot point, while at the same time position the object to be rotated in the scene.

I tried everything :(

What I'm doing now is;


/* Draw an object */
glLoadIdentity();
// Rotate coordinate system
glRotatef(object.angle,object.axis[x],object.axis[y],object.axis[z]);
// Translate origin to pivot point
glTranslatef(object.pivot[x],object.pivot[y],object.pivot[z]);
// Position object in scene
glTranslate(object.pos[x],object.pos[y],object.pos[z]);
draw_object();
// Flip screen...This obviously doesn't work :(
I just want the object to rotate around a point, and then position it somewhere. It sounds easy, I know, but it's harder than I thought :confused:

CrazyButcher
06-23-2004, 12:26 AM
to rotate around point in affine space you'd do:

1. move your "pivot" to center (ie translate with inverse of pivot position

2. rotate

3. move your pivot back to its original pos

the matrix you get now will rotate around the pivot point

I think in GL you can achieve this with pushing & popping the matrix

ie move to pivot, push matrix, rotate, push, move again (the coords using for move now should be relative to the pivot point) pop, pop

Jared
06-23-2004, 12:59 AM
first of: you save yourself a lot of trouble if you model each object around its pivot. then you wont have to do anything but translate into place and rotate into position.

just keep in mind, that youre working on the objects local coordinate system and this system is changing WITH the object. so the way you try to move it into position AFTER rotating will have a hard time working, because rotating changes the axes and as your position is most likely stored in world coordinates they just became more or less useless.

so in short: instead of storing a pivot for every object just move the vertices so the pivot is the origin.

MatthewL
06-23-2004, 10:06 AM
Ok, I tried doing what was suggested and negated the pivot point, then translated the coord system to it, rotated, and then restored the pivot and translated again. Then I translate to the object's pivot-relative position. But it doesn't do what it's supposed to :(

Here's my code;

/* Draw an object */
glLoadIdentity();
/* Negate pivot point. */
object.pivot[x] = -object.pivot[x];
object.pivot[y] = -object.pivot[y];
object.pivot[z] = -object.pivot[z];
/* Move to inverse pivot */
glTranslatef(object.pivot[x],object.pivot[y],object.pivot[z]);
/* Rotate coordinate system */
glRotatef(object.angle,object.axis[x],object.axis[y],object.axis[z]);
/* Undo changes to pivot point */
object.pivot[x] = -object.pivot[x];
object.pivot[y] = -object.pivot[y];
object.pivot[z] = -object.pivot[z];
/* Move to regular pivot point */
glTranslatef(object.pivot[x],object.pivot[y],object.pivot[z]);
/* Get pivot-relative position coordinates */
temp[x] = object.pivot[x] - object.pos[x];
temp[y] = object.pivot[y] - object.pos[y];
temp[z] = object.pivot[z] - object.pos[z];
/* Position rotated object */
glTranslatef(temp[x],temp[y],temp[z]);
draw_object();Note that:
object.pivot = {5.0, 0.0, 100.0}
object.pos = {0.0, 0.0, 100.0}

So pivot - pos = {5.0, 0.0, 0.0}, which is where I position the object at so its position is relative to the pivot point.

However, the object appears at position {5.0, 0.0, 0.0} :(

I want it to be positioned at {0.0, 0.0, 100.0}, then rotate around {5.0, 0.0, 100.0}.

I can't translate the vertices of objects relative to a pivot point before transformation, because the pivot point is to be dynamic in my program. (for physics) It would just be very slow looping through all the vertices in the scene and applying a translation to them every time the pivot point is changed, which is probably every frame. T&L does a better job.

MatthewL
06-23-2004, 11:20 AM
I tried something trivial, but even that doesn't work:

glLoadIdentity();
glTranslatef(5.0, 0.0, 0.0); // Origin at 5,0,0?
glRotatef(angle,xr,yr,zr); // Rotate around 5,0,0
glTranslatef(0.0 ,0.0 ,100.0 ); // translate to 0,0,100
draw_object();I don't get it, isn't it rotating around a new origin (5,0,0) and then positioning the object at 0,0,100?
what this code does instead is position the object at 0,0,100, and then rotate it around 5,0,0 :eek: :confused:

ZbuffeR
06-23-2004, 11:38 AM
Don't worry, I think it is a common problem.

As the transformations are computed as matric multiplications, you end up with reversed order compared to what would be natural.

In fact each transformation is multiplied this way :
PresentMatrix = NewTransformation . PresentMatrix

so with :

TransA
RotB
TransC

You end up with TransC.RotB.TransA.I

At thi s web page (http://www.sgi.com/software/opengl/advanced97/notes/node15.html) it is said : "Since the matrix order is the reverse of the order of operations".

So just reverse the order, and it will work !

endash
06-23-2004, 11:47 AM
You should look at the discussion of this in the Red Book.

Describing this stuff with words like "...and then..." can be confusing. In that notation, what the code you give does is place the object at (5,0,100) and then rotate it about (5,0,0).

In English, this could be rephrased to match how OpenGL thinks: "Draw an object at (0,0,100), rotate it about the origin, move the origin to (5,0,0)."

Matrix operations are very stack-like, hence glPushMatrix() and glPopMatrix().

MatthewL
06-23-2004, 12:01 PM
Well, thank you all for your help!

What ZbuffeR suggested helped!
The working code turned out to be;


/* Draw an object */
glLoadIdentity();

glTranslatef(object.pivot[x],object.pivot[y],object.pivot[z]);
glRotatef(object.axis[x],object.axis[y],object.axis[z]);

tmp[0] = object.pivot[x] - object.pos[x];
tmp[1] = object.pivot[y] - object.pos[y];
tmp[2] = object.pivot[z] - object.pos[z];
glTranslatef(tmp[x],tmp[y],tmp[z]);
draw_object();Woohoo!! :)