PDA

View Full Version : N-Arbitrary Rotations -> Euler angle shortcut?



paradoxresolved
11-08-2013, 12:51 AM
Hello all,

I've tried looking through the posts that have already been made regarding the topic of Euler angles, but I'm not sure if Euler angles are the route to take for my current problem. My project has stalled for about two weeks, so I decided to consult the experts here...

I have an object that will be rotated an arbitrary number of times around the three principals axes, X, Y and Z, in no particular order. What I need is to extract the outcome from the resulting matrix and apply the transformation, preferably using glRotatef. (I have a somewhat older version of OpenGL, v. 2.0 I believe).

First off, I found Eberly's function for retrieving the Euler angles, which I'll list here:




GLfloat x = 0;
GLfloat y = 0;
GLfloat z = 0;
y = asin(m_matrix[2][0]);
if(y < PI/2)
{
if(y > -PI/2)
{
x = atan2(-(float)m_matrix[2][1],(float)m_matrix[2][2]);
z = atan2(-(float)m_matrix[1][0],(float)m_matrix[0][0]);
}
else
{
// not a unique solution
x = -atan2((float)m_matrix[0][1],(float)m_matrix[1][1]);
z = 0;
}
}
else
{
// not a unique solution
x = atan2((float)m_matrix[0][1],(float)m_matrix[1][1]);
z = 0;
}
x = x*180/PI;
y = y*180/PI;
z = z*180/PI;


The matrix is:
|[0][0] [0][1] [0][2] [0][3]|
|[1][0] [1][1] [1][2] [1][3]|
|[2][0] [2][1] [2][2] [2][3]|
|[3][0] [3][1] [3][2] [3][3]|

They are all GLfloat values.

As far as I know, the angles that are being extracted using this function are the correct angles. I tested it by making single axis rotations, one at a time. At least as far as those tests go, the angles are correct.

In either case, once I have the Euler angles, I implement the transformation of the object using:



glPushMatrix();
glRotatef(x,1,0,0);
glRotatef(y,0,1,0);
glRotatef(z,0,0,1);

// ... draw object
glPopMatrix();


For as long as my series of arbitrary rotations are restricted to one axis (for instance, a bunch of rotations around the z-axis, say), this Euler angle approach works. As soon as I start adding rotations around the other axis, the object rotates incorrectly.

The first question I'd like to ask is a conceptual one: Is this the reasonable route to take to achieve the goal? The goal, to (hopefully) be clear, is: perform n-number of arbitrary X,Y,Z rotations, pull the Euler angles from the final matrix, and then use the Euler's angles to achieve the net result of the n-number of arbitrary rotations.

Your help will be greatly appreciated! :)

GClements
11-09-2013, 03:21 AM
For as long as my series of arbitrary rotations are restricted to one axis (for instance, a bunch of rotations around the z-axis, say), this Euler angle approach works. As soon as I start adding rotations around the other axis, the object rotates incorrectly.
Where is the matrix coming from? Your code is correct for a matrix in row-major order, but OpenGL uses column-major order.


The first question I'd like to ask is a conceptual one: Is this the reasonable route to take to achieve the goal? The goal, to (hopefully) be clear, is: perform n-number of arbitrary X,Y,Z rotations, pull the Euler angles from the final matrix, and then use the Euler's angles to achieve the net result of the n-number of arbitrary rotations.
Why do you want to use Euler angles? If you're just trying to "compress" an orthonormal matrix into three parameters, the axis-and-angle form used by glRotate() can be reduced to 3 parameters by scaling the axis by the angle. Converting this representation back to a matrix is less work than generating three separate matrices then multiplying them.

paradoxresolved
11-09-2013, 04:49 PM
The matrix is generated separate from OpenGL. For a variety of reasons, I keep a history of the transformations separate from OpenGL, for now anyway.

I have decided to switch to quaternions in order to try to solve this problem. Unfortunately, I'm getting the exact same result. Rotating along one axis is fine, but as soon as I start rotating around a separate axis, things get screwy. I'm going to need to put some more research into this.

Dark Photon
11-12-2013, 05:55 PM
paradoxresolved, either of these is possible (decompose to euler rot or decompose to quaternion). You just have to have a working "matrixToEuler()" or "matrixToQuat()" function.

Here are some links for the quat case:

* http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
* http://www.geometrictools.com/LibMathematics/Algebra/Wm5Quaternion.inl

Main thing is you need an alg that's resilient in the face of the basis vectors getting either slightly denormalized and/or slightly out of orthogonal w.r.t. each other.

Note that an even better solution is to just composite the rotation using quaternions and not even mess with matrices. More efficient that way too.