Originally posted by JiauFoo:

[b]Hi all.

I’m having some trouble modeling the rotational human shoulder joint.

The shoulder (or rather, arm) can rotate in the x, y and z axes. However, after each rotation, the axes are rotated too. Meaning that it’s very hard to tell which direction the next rotation is going to occur in.

How do I make the shoulder/arm rotate about a fixed x, y and z axis, regardless of it’s current orientation?

Thanks for any help. Need it badly.[/b]

I think the problem you are having is called the gimball effect. The problem is with how the OpenGL pipeline works. As you should know, a call to glRotate*() doesn’t really rotate the object, it simply post-multiplies the current modelview matrix by a rotation matrix:

[current_model_view_matrix]=[current_model_view_matrix] * [R]

so what happens here that the effect is that some axis gets rotated. In order to avoid this, now you have think whether you want to rotate the object about its own coordinates or about the world coordinates.

How do you implement it?

let’s say you have a rotation_matrix which has some value (perhaps it came from a trackball rotation, or its the joint’s previous orientation). In the following, MV stands for ModelView matrix and CT is the actual current transformation

glPushMatrix();

glLoadIdentity(); //MV=I

glMultMatrixf(rotation_matrix); //MV=rotation_matrix

glRotatef(angle,xaxis,yaxis,xaxis); //MV=MV*R => MV=rotation_matrix*R

glGetFloatv(GL_MODELVIEW_MATRIX,rotation_matrix);

glPopMatrix();

glMultMatrixf(rotation_matrix);

so what happens when you do another rotation?

- MV=I*R1 => MV=R1
- MV=MV
*R2 => MV=R1*R2
- MV=MV
*R3 => MV=R1*R2*R3

now remember matrices work from right to left, so when we say pre-multiply, we mean multiply on right. You should easily come up with the post-multiply implementation for a world-centred rotation (but in you case I don’t think you need it)

Hope this helps,

Reza

Ps. I think I’m totally confused about this pre/post multiply business myself. The above is correct in the order I’ve put things, but the notation may be wrong. In particular,

MV = MV * R is a post-multiply

MV = R * MV would be a pre-multiply

(can somebody verify this please?)

In addition, the above is for a body centred rotation and you need world centred rotation, here is the world centred one:

glPushMatrix();

glLoadIdentity; //MV = I

glRotatef(angle,xaxis,yaxis,zaxis); //MV=R

glGetFloatv(GL_MODELVIEW_MATRIX,rotation_matrix); //rotation_matrix = R

glPopMatrix();

glMultMatrixf(rotation_matrix);

By now you should be well confused.

Reza

[This message has been edited by Rizo (edited 04-10-2001).]