Local to World rotation angles.

I’m developing a plugin for an application called Daz Studio (more info here, if you are curious: INFINITO plugin), using QT and OpenGL.

In the plugin glWidget, my object rotates using the local coordinate system. I need to convert those angles into world coordinate system (because the main application opengl viewport expect objects to work that way).

Matrices, math in general is my pet hate, any help greatly appreciated.

Well, a rotation in a local system won’t be (in general) also only a single rotation in the global system. But it will generally be a rotation (with different axis and different angle) plus a translation.

Let’s say M is the matrix that makes the transformation from the global system to the local system you want.

If you apply a rotation R (as a 4*4 matrix) in the local system, the results of this rotation of a point P in the local system will be:
P’ = R * P.

If you want it in the global system, it will then be
P" = M * R * P

From these results, you can then deduce the 3 axis (3 column-vectors, let’s say v1,v2,v3) and the translation (last column-vector). [note: use the matrix M*R for this]

I think you can then check the angles between v1 and i (1,0,0), v2 and j (0,1,0) and v3 and k (0,0,1). You then have the 3 angles around the 3 axis expressed in the global system, plus the required translation.

It should be doable but I never did that before…

Thank you very much, will try this…

Here is the code I came up with. It still doesn’t work, because the world rotation angles do not produce the same rotation as the local ones.


float xRot=45.0*DEG_TO_RAD;
float yRot=30.0*DEG_TO_RAD;
float zRot=22.0*DEG_TO_RAD;

 // build rotation matrix
    float A       = cos(xRot);
    float B       = sin(xRot);
    float C       = cos(yRot);
    float D       = sin(yRot);
    float E       = cos(zRot);
    float F       = sin(zRot);
    float AD      =   A * D;
    float BD      =   B * D;
	
    matXYZ[0]  =   C * E;
    matXYZ[1]  =  -C * F;
    matXYZ[2]  =  -D;
    matXYZ[4]  = -BD * E + A * F;
    matXYZ[5]  =  BD * F + A * E;
    matXYZ[6]  =  -B * C;
    matXYZ[8]  =  AD * E + B * F;
    matXYZ[9]  = -AD * F + B * E;
    matXYZ[10] =   A * C;
    matXYZ[3]  =  matXYZ[7] = matXYZ[11] = matXYZ[12] = matXYZ[13] = matXYZ[14] = 0;   matXYZ[15] =  1;

  
 float *modelview;
 modelview= new float[16];
 glGetFloatv( GL_MODELVIEW_MATRIX, modelview );  // Get the current MODELVIEW matrix from OpenGL 
 
 float *worldRotMatrix;
 worldRotMatrix=new float[16];
 worldRotMatrix=matrixMultiply(modelview,matXYZ); // this should be the final rotation matrix, in world space

 angle_y = -asin( worldRotMatrix[2]); /* Calculate Y-axis angle */ 
float C = cos( angle_y );  
if ( fabs( C ) > 0.005 ) /* Gimball lock? */ 
{ 
        tr_x = worldRotMatrix[10] / C; /* No, so get X-axis angle */  
        tr_y = -worldRotMatrix[6] / C;  
        angle_x = atan2( tr_y, tr_x ) ;  
        tr_x = worldRotMatrix[0] / C; /* Get Z-axis angle */  
        tr_y = -worldRotMatrix[1] / C;  
        angle_z = atan2( tr_y, tr_x ) ; 
} 
else /* Gimball lock has occurred */ 
{  
     angle_x = 0; /* Set X-axis angle to zero */  
     tr_x = worldRotMatrix[5]; /* And calculate Z-axis angle */ 
     tr_y = worldRotMatrix[4];   
     angle_z = atan2( tr_y, tr_x ) ; 
}



float* matrixMultiply(float* m1, float* m2)
{
    float *finalMat;
    finalMat=new float[16];
    matrixIdentity(finalMat);
    
    // Fisrt Column
    finalMat[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
    finalMat[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
    finalMat[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
    finalMat[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
	
    // Second Column
    finalMat[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
    finalMat[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
    finalMat[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
    finalMat[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
	
    // Third Column
    finalMat[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
    finalMat[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
    finalMat[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
    finalMat[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
	
    // Fourth Column
    finalMat[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
    finalMat[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
    finalMat[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
    finalMat[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
	
    return finalMat;
}

Maybe I should have given more info about what I’m trying to accomplish, I’ve the feeling I’ve created a chaotic thread and instead of posting/asking code I should have explained more in detail what I need to do.

I have a simple opengl application where I load and display .obj files. The application allows also to position, scale and rotate those models using the mouse. All those transformations happen in local space.
The application allows to export the above data in a .txt file, with the following scheme:

obj file | xRot | yRot | zRot | xPos | yPos | zPos

Later on, in a separate, commercial application, I read this .txt file and I recreate the scene, loading sequentually the obj’s files and applying the transformation values read from the .txt file.
Problem is, that the commercial application perform rotations in world space, while the angles that I “exported” are in local space.

So, what I’m trying to do is to convert those angles from local to world space so that the objects are properly rotated in the commercial application.

I hope I could explain myself better…

Arts, when you write M, you mean I should do the following?

float *M;
M= new float[16];
glGetFloatv( GL_MODELVIEW_MATRIX, M ); 	// Get the current MODELVIEW matrix from OpenGL 

Thanks

It was just mathematics. Don’t forget that when you set your view with gluLookAt or with other means, this transforms the modelview matrix too.

I’m totally confused.
What drives me crazy is that I’m so dumb to figure out what it seems to be such an easy problem.
I mean, let’s forget opengl for a moment.

I have an object rotated in local space as follows:

pitch=45, yaw=30, roll=15

Given that world axis are [1,0,0] [0,1,0] [0,0,1]

Now, let’s calculate world angles out of it… what is the math beyond it?

If M is the matrix that transforms from world space to your local space (translation + rotation + scaling for example), and you have the matrix R that does your rotation in this local space, then the matrix M*R makes the both transformations at once. Let’s call this matrix A.

A is then in the form:


a0  a1  a2  a3
a4  a5  a6  a7
a8  a9  a10 a11
0   0   0   1

Generally, the last line is (0,0,0,1).

Then, the vectors v0 (a0, a4, a8), v1 (a1, a5, a9) and v2 (a2, a6 and a10) are the eigenvectors of this matrix, which means they represent the 3 axis vectors of the local system.

It then seems to be possible to extract the angles (see http://www.codeguru.com/forum/archive/index.php/t-329530.html for example). It’s different from what I guessed however.

Thinking a bit about your topic, I’d like to add: if the rotation center in the local space is the same than the object’s space center, then you don’t need math at all. In this way, what you have to do is simply use the ‘local-space’ angles as world-space angles and rotate objects before translating them into their position.

That’s all what I can say about this.

What do you mean with “local space”?
To do a local space transformation (ex. rotation), you need to have three arbitrary orthonormal axes, and you must build a rotation matrix relative to these axes (instead of the world’s space axes x(1,0,0), y(0,1,0), z(0,0,1)).
If you didn’t specify these axes, the rotation is expressed in world space, not local space.

The “real” local-space is expressed by your vertices in the .obj file. Every vertex of the model is in fact a vector relative to the same (local) origin (0,0,0). It’s called “local”, because you want to translate and rotate every vertex of the model in a scene without effectively modify and store the transformed vertices (the transformation is performed on the fly and so the values stored will remain always the same).

The angles are relative to the world’s axes x, y, z.
And the position is obviously in world space.
As arts said, no math is required.

If the rotation between two different applications is not the same, the problem can be related to other factors. Make sure the two applications use the same conventions (ex. pitch-yaw-roll rotations need to be applied in the same order) and make sure the camera position and orientation is the same of your application.