How to Get Local Transformations ?

Hello all,
I am pretty new to OpenGL, and I was wondering how could I get my little program
to work.

Let’s say I want to draw a robot’s ARM, at which end FOREARM is attached. On the end of the FOREARM we have a FINGER. On my way to draw a FINGER I am using many glTranslatef() and glRotatef(), but these operations will
be constant - the only variable element will be the FINGER itself.

Here’s the pseudo-code, later I’ll try to
explain what I want to achieve.

// – CODE BEGIN –
glGetDoublev(GL_MODELVIEW_MATRIX,m_modelview_matrix) // Save the current matrix
// Star Drawing Robot’s ARM
gluCylinder(…) // Draw an Arm
glTranslatef(…) // Move to the ‘end’ of the arm
glRotatef(…) // Rotate the ‘end’ of the arm
// Start Drawing Robot’s FOREARM
gluCylinder(…) // Draw a Forearm
glTranslatef(…) // Move to the end of the forearm
glRotatef(…) // Rotate the ‘end’
// Start Drawing Robot’s FINGER
gluCylinder(…) // Draw a Finger
// – CODE END –

I want to be able to get the coordinates (the angles of rotation are not so important)
of the FINGER according to the begining of the ARM, so I could simply draw the ARM and FOREARM from a CallList, then start drawing the fingers ‘manually’

// Draw the Robot’s ARM and FOREARM using stored Call List
glCallList(Stored_Call_List_For_ARM_FOREARM);
glLoadMatrixd(m_modelview_matrix);
glTranslatef(Calculated_X,Calculated_Y, Calculated_Z);
// Draw Robot’s Fingers
gluCylinder(…) // Draw a Finger

I don’t know how to get the ‘local’ values
of transformation between one point and another. I tried subtracting values of current matrix M[12], M[13], M[14] from the one stored on the beginning of the ARM, but it only works when I don’t rotate the beginning of the ARM.

Then I tried to follow the transformations
made from the beginning of the ARM until the
FINGER (to get the local coordinates in the Beginning-Of-The-ARM-is-a-(0,0,0)-point of the FINGER), but it didn’t work either.
Maybe I just made a mistake somewhere,
or maybe there’s a simplier, better way to
do what I want to achieve.

sighs I hope I’ve explained my problem well … I’m on the end of the rope …

Here is how I understand world to local coordinate transformations. When you send coords down the pipeline, they are initially in what is known as model space. They are then multiplied by the model matrix. The resulting coords are in world space. These coords are multiplied by the view matrix, and the resulting coords are in eye space. Then more stuff happens, but that’s not important right now.

Note that OpenGL combines the model and view matrices into the modelview matrix for efficiency. Coords go directly from model space to eye space.

Think of whatever you do to set up your camera as defining the view matrix. Think of whatever you do afterwards to place objects as defining the model matrix. Now, I’ll assume you didn’t perform any transformations before you got to the beginning of the arm. Then you know that the coords for the beginning of the arm are the same in model space and in world space because the model matrix is just the identity matrix at this point; you haven’t done anything to it yet.

Now you must find the model coords that will give you the same world coords as the start of the arm after a whole bunch of transformations. In equation form,

world_coord = transformation_matrix * model_coord

You know the world_coord already: it’s the start of the arm. You also know the transformation_matrix. You must solve for model_coord.

model_coord = (transformation_matrix)^(-1) * world_coord

You must pre-multiply the coords for the start of the arm with the inverse of the transformation matrix that you use to get you to the location that you’re interested in. Just in case you don’t have the routines or knowledge yet, here is how you can find the appropriate inverse in OpenGL. Say the entire transformation you wanted consisted of

glTranslatefv(some_vector)
glRotatef(some_angle, some_axis)

You could find the inverse by doing something like

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glRotatef(-some_angle, some_axis);
glTranslatefv(-some_vector);

get the modelview matrix
glPopMatrix();

Note that the angle and the vector are negated and the order in which the calls are made must be reversed.

edit::
The process I outlined can be used to find the coord of the beginning of the arm with respect to the fingers. Getting the coord of the finger with respect to the beginning of the arm should be even easier. You just have to mimic the matrix math that the pipline is doing for you:

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

do all your transformations
get the modelviewmatrix

glPopMatrix();

finger_coord_rel_arm_beginning = transformation_matrix * whatever_finger_coord_was

Since you know what finger coord you would have used when drawing stuff after all the transformations, you can get the position relative to the beginning of the arm.

[This message has been edited by UnIcron (edited 10-05-2003).]

The easy way would be to use variables and push/pop matrix.

See my clock demo on my website: www.angelfire.com/linux/nexusone/

I would treat the Robot as its own world space.

You have first the world space in which the robot is moving around in.

//draw routine
void display(void)
{
// Setup the projection matrix

… here projection stuff …

// setup our point of view of the world.

… glulookat or transforms to set our camera view …

// Draw our object aka Robot

glPushMatrix(); // Start of our Robot’s world space
glTranslate // Location of Robot in our world
glRotate // Rotation of Robot in our world.
// Note that all the robots body parts are drawn relative to the robots world space.
// By doing this we don’t have to worry about where the part are in respect to world space, only to the robot.
// Draw main body
DrawBody();
// Draw head
glPushMatrix() // here we save the current robot’s world space so that the transforms for the next body parts dont’ effect other parts.
glTranslate // Location of head relative to body
glRotate // We would stick some variables here so that we could make our robot move his head by changing them.
drawHead();
glPopMatrix(); // Restore Matrix to Robots space origin

// Draw Left Arm
glPushMatrix();
glTranslate // Location of arm on body
glRotate // rotation of body another place to use a variable for arm movement
drawArm();
// Left arm Elbow junction
glPushMatrix() // Since the Elbow moves in conjunction with the main arm we now save the matrix based the main arm.
glTranslate // Move next section of left arm
glRotate // Here would be rotation of elbow varaible
drawArm(); this would be the next section
// We could add a hand by adding another Push matrix, but hope you see the patern here.

glPopMatrix(); // End elbow

glPopMatrix(); // End arm

// You would repeat above for next arm, legs etc.