views:

311

answers:

1

Hello!

My problem is the following:

I have nested object in my opengl scene, and i only know their relative position and orientation.

How do I get the absolute position and orientation of the inner object? I' thinking of calculating the modelview matrix of the inner object, and after that i have the current matrix, but how do i convert it to position and orientation? In other words, to two float vector, so I can call the following code:

glTranslatef(position.x,position.y,position.z);

glRotatef(alignment.x,1.0f,0.0f,0.0f);
glRotatef(alignment.y,0.0f,1.0f,0.0f);
glRotatef(alignment.z,0.0f,0.0f,1.0f);

Thanks in advance!

+2  A: 

If you have the modelview matrix of the object you can extract the position with the following code:

// ... Some rotations/translations has been applied
GLfloat matrix[16]; 
glGetFloatv (GL_MODELVIEW_MATRIX, matrix);
const float position_x = matrix[12];
const float position_y = matrix[13];
const float position_z = matrix[14];

The rotation is a little bit more complex, look at: euler angles. The rotation matrix we want is the transpose of the zyx-one =>

//c1 = cos(alignment_x)
//c2 = cos(alignment_y)
//c3 = cos(alignment_z)
//s1 = sin(alignment_x)
//s2 = sin(alignment_y)
//s3 = sin(alignment_z)
//matrix[0] = c1 * c2
//matrix[1] = -c2 * s1
//matrix[2] = s2
//matrix[4] = c3 * s1 + c1 * s2 * s3
//matrix[5] = c1 * c3 - s1 * s2 * s3
//matrix[6] = -c2 * s3
//matrix[8] = s1 * s3 - c1 * c3 * s2
//matrix[9] = c3 * s1 * s2 + c1 * s3
//matrix[10] = c2 * c3

Extracting the actual angles from this is rather messy because there are a couple of singularities, if we ignore these we get:

// Assumes c2 != 0, you'll need more code to handle the special cases
if (matrix[0] != 0.0f || matrix[1] != 0.0f) {
    const float alignment_x = atanf(-matrix[1], matrix[0]);
    float c2;
    if (0 != cosf(alignment_x)) {
        c2 = matrix(0) / cosf(alignment_x);
    } else {
        c2 = matrix(1) / -sinf(alignment_x);
    }
    const float alignment_y = atanf(matrix[2], c2);
    const float alignment_z = atanf(-matrix[6], matrix[10]);
} else {
    alignment_y = atanf(matrix[2], 0);
    //Too tired to deduce alignment_x and alignment_z, someone else?
}

All the above code assumes you're only using rotations/translations and no scalings or skewings.

Let me just finish by saying euler angles are evil, if I were you I would look for an alternative solution to whatever problem it is you're trying to solve ;)

/A.B.

Andreas Brinck
hi, i would be really thankful if you could provide the rest of the code, because i think this is exactly what i need at the moment. i too have the modelview matrix and want to extract the 3 angles to do stuff like glRotatef(x,1,0,0);glRotatef(y,0,1,0);glRotatef(z,0,0,1);on my own. in my case i definitely know, that there are no translations done with the matrix, but i think this isn't relevant for the calculation of the rotation (?)will the resulting values be in value range from 0 to 360 or -PI to PI or ranges like that?
Sponge
in which way is this here: http://www.songho.ca/opengl/gl_anglestoaxes.html#anglestoaxes related to your code? are you just extraction the angles for all possible matrices?
Sponge
Yes and no, Song Ho's page shows you how to calculate a rotation matrix for one of 6 possible combinations of euler angles. What you're asking for is the inverse of this: how do I calculate a particular set of euler angles given a rotation matrix? As I said in my original answer this is rather finicky to do since there are singularties which make the calculation not well defined. The code I've supplied above will give all angles in radians.
Andreas Brinck