world to local rotations

Started by
16 comments, last by AlessandroMastronardi 12 years, 6 months ago
In opengl I rotate objects in world space:

glRotatef(myObject.zRot, 0, 0, 1);
glRotatef(myObject.xRot, 1, 0, 0);
glRotatef(myObject.yRot, 0, 1, 0);


There is a way to find the object local angles of rotation?
Advertisement

In opengl I rotate objects in world space:

glRotatef(myObject.zRot, 0, 0, 1);
glRotatef(myObject.xRot, 1, 0, 0);
glRotatef(myObject.yRot, 0, 1, 0);


There is a way to find the object local angles of rotation?


Look into quaternions. You can use that rotation matrix to extract a quat and then get eular angles (xyz).
There is a quaternion lib in my library.
There is also a function for extracting angles directly from a rotation matrix.
Sig: http://glhlib.sourceforge.net
an open source GLU replacement library. Much more modern than GLU.
float matrix[16], inverse_matrix[16];
glhLoadIdentityf2(matrix);
glhTranslatef2(matrix, 0.0, 0.0, 5.0);
glhRotateAboutXf2(matrix, angleInRadians);
glhScalef2(matrix, 1.0, 1.0, -1.0);
glhQuickInvertMatrixf2(matrix, inverse_matrix);
glUniformMatrix4fv(uniformLocation1, 1, FALSE, matrix);
glUniformMatrix4fv(uniformLocation2, 1, FALSE, inverse_matrix);

In opengl I rotate objects in world space:

glRotatef(myObject.zRot, 0, 0, 1);
glRotatef(myObject.xRot, 1, 0, 0);
glRotatef(myObject.yRot, 0, 1, 0);


OpenGL does not work in world space. IF your modelview was still identity, the very first rotation will happen to in world space, but only because local and global are still the same. Every rotation after that is using the local coordinate system resulting from your previous transformations. If you want to use global coordinates, you have to change the order of the matrix multiplication (ie. do it manually, because OpenGL will always do modelview = rotationMatrix * modelview, when what you want is modelview = modelview * rotationMatrix; ).
f@dzhttp://festini.device-zero.de

[quote name='Alessandro' timestamp='1318032168' post='4870317']
In opengl I rotate objects in world space:

glRotatef(myObject.zRot, 0, 0, 1);
glRotatef(myObject.xRot, 1, 0, 0);
glRotatef(myObject.yRot, 0, 1, 0);


OpenGL does not work in world space. IF your modelview was still identity, the very first rotation will happen to in world space, but only because local and global are still the same. Every rotation after that is using the local coordinate system resulting from your previous transformations. If you want to use global coordinates, you have to change the order of the matrix multiplication (ie. do it manually, because OpenGL will always do modelview = rotationMatrix * modelview, when what you want is modelview = modelview * rotationMatrix; ).
[/quote]

Sorry for the confusion. Yes opengl works in local space. I do have a quaternion library but I don't know the math of how would I go from local angles to world space, using matrices. Any chance to have some pseudo-code?
Here is the code I came up with. I'm still not sure I'm extracting angles correctly from the final step.<br><br>



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

// build rotateX matrix
matX= new float[16];
matX[5] = cosf(xRot);
matX[6] = -sinf(xRot);
matX[9] = -matX[6];
matX[10] = matX[5];

// build rotateY matrix
matY= new float[16];
matY[0] = cosf(yRot);
matY[2] = sinf(yRot);
matY[8] = -matY[2];
matY[10] = matY[0];

// build rotateZ matrix
matZ= new float[16];
matZ[0] = cosf(zRot);
matZ[1] = sinf(zRot);
matZ[4] = -matZ[1];
matZ[5] = matZ[0];

matXY=new float[16];
matXYZ=new float[16];

matXY= matrixMultiply(matX, matY);
matXYZ=matrixMultiply(matXY, matZ); //calculate final rotation matrix matXYZ

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 ) ;
}




Forgot to show the matrixMultiply function:


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;
}
If you understand the dot product and know how to use it to find angles between vectors:

After you do those 3 global rotations you get a matrix that shows the new x,y,z vectors for your object. So by drawing your object with the identity matrix it is probably aligned with the global vectors (right = x, y = top, forward = z or negative z). Those 3 vectors now equal the 3 columns in your matrix after doing global rotations. In otherwords, The identity matrix gives you x,y,z axis, what do they map to now: column0,1,2 of your matrix. So do a dot product between the old x and new x, old y and new y, old z and new z. And you can figure out that but.

I assume that is what you want, but you should be knowing the local rotations (yaw,pitch,roll). I do what you do, I align all models on the z axis, that way I can do z rotation first, and then the x,y rotations are the ones the figure out the heading direction of the object. I think I just dont understand your problem though.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

Sorry, instead of writing code perhaps I had to explain more in detail what I'm trying 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...
You should be able to use the local xyz rotations to compute what the object would draw like relative to its own Identity/Local space, Then apply the transform that makes the object be a certain way globally. Should be able to just multiply both matrices. That would give you the final matrix it should look like to draw with given the vertex data in local space. With that matrix, you could just dot product all vectors in that matrix (column0,1,2) with the regular world space vectors (1,0,0 0,1,0, 0,0,1) with their new representations column0,1,2 and that would give you the angle that the object is drawing at relative to the regular world axis.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

Thanks dpadam450, so the pseudo-code would look like this:

1) build the object local space matrix
2) get the current MODELVIEW matrix from OpenGL
3) build final matrix multiplying the MODELVIEW by the local space matrix (and I think I arrived at this point in previous code I posted)
4) dot product the vectors defined by columns 0,1,2 of the final matrix, by the corresponding regular world space vectors (1,0,0 0,1,0, 0,0,1)
5) extract euler angles from this last resulting matrix.

Would that work? Any comments also from others?

This topic is closed to new replies.

Advertisement