Skip to main content
GameDev.net gamedev.net
🔒 Locked

Direction Vector From Rotation Matrix

Started by Code-R May 12, 2005 at 9:58 PM 8 replies 22.4k views
Original Post
Code-R
Code-R
apparently, this code makes the results "break" at a certain point, it doesn't go thru the entire 360, but 0 ->180 then JUMPS to 270 and continues! any thoughts?

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

			/* return only positive angles in [0,360] */
			if (angle_x < 0) angle_x += 6.28318;
			if (angle_y < 0) angle_y += 6.28318;
			if (angle_z < 0) angle_z += 6.28318;
			vec3 Res = vec3(0,0,-1) - vec3(cos(angle_x),cos(angle_y),cos(angle_z));
			Res.Normalize();
			return Res;
As you can see, this was ripped off the matrix and quat. faq ;)
Zakwayda
Zakwayda
Euler angles suffer from aliasing, that is, the same rotation can be represented with multiple Euler angle combinations. When you extract Euler angles from a matrix, you get one of the many possible combinations that describe that rotation; however, it may not be the one you want.

I didn't look at the code this time, but I recall helping someone with this particular implementation before. IIRC the 'y' rotation is found first using asin(), which means it will always be in the range [-pi/2,pi/2]. That may not be the y rotation you used to construct the matrix, but if so the x and z rotations will also adopt different values to 'take up the slack', so to speak. In the end, the Euler angles that you extract may be different than the ones you put in, but they will describe the same rotation.

There are other issues, such as differing orders of application for Euler angles, row/column conventions, and coordinate system and rotation handedness, which may lead to unexpected results.
John Schultz
John Schultz
The view direction vector is either the z column or z row (depending on row/column orientation), and if using a right-handed coordinate system (e.g. OpenGL), the resulting vector is negated.

Vec3 viewDir(m[2][0],m[2][1],m[2][2]); // Left-handed column oriented: get z row.

or

Vec3 viewDir(m[0][2],m[1][2],m[2][2]); // Left-handed row oriented: get z column.

or

Vec3 viewDir(-m[2][0],-m[2][1],-m[2][2]); // OpenGL style matrix (right-handed, column oriented), get the -z row.

or

Vec3 viewDir(-m[0][2],-m[1][2],-m[2][2]); // Right-handed row oriented: get -z column.
Code-R
Code-R
Quote:
Original post by John Schultz
The view direction vector is either the z column or z row (depending on row/column orientation), and if using a right-handed coordinate system (e.g. OpenGL), the resulting vector is negated.

Vec3 viewDir(m[2][0],m[2][1],m[2][2]); // Left-handed column oriented: get z row.

or

Vec3 viewDir(m[0][2],m[1][2],m[2][2]); // Left-handed row oriented: get z column.

or

Vec3 viewDir(-m[2][0],-m[2][1],-m[2][2]); // OpenGL style matrix (right-handed, column oriented), get the -z row.

or

Vec3 viewDir(-m[0][2],-m[1][2],-m[2][2]); // Right-handed row oriented: get -z column.


Thanks, that's more like what i was trying to achieve. But I'm not trying to find the view vector I'm trying to get the direction of an object whose orientation is represented by a 4x4 matrix, will this still work??

Zakwayda
Zakwayda
Quote:
Thanks, that's more like what i was trying to achieve. But I'm not trying to find the view vector I'm trying to get the direction of an object whose orientation is represented by a 4x4 matrix, will this still work??
If your matrix is an object transform rather than a view transform, then I think you probably just want the transpose of what John posted. Also, you may not need to negate the z axis in this case.
John Schultz
John Schultz
Quote:
Original post by Code-R
Quote:
Original post by John Schultz
The view direction vector is either the z column or z row (depending on row/column orientation), and if using a right-handed coordinate system (e.g. OpenGL), the resulting vector is negated.

Vec3 viewDir(m[2][0],m[2][1],m[2][2]); // Left-handed column oriented: get z row.

or

Vec3 viewDir(m[0][2],m[1][2],m[2][2]); // Left-handed row oriented: get z column.

or

Vec3 viewDir(-m[2][0],-m[2][1],-m[2][2]); // OpenGL style matrix (right-handed, column oriented), get the -z row.

or

Vec3 viewDir(-m[0][2],-m[1][2],-m[2][2]); // Right-handed row oriented: get -z column.


Thanks, that's more like what i was trying to achieve. But I'm not trying to find the view vector I'm trying to get the direction of an object whose orientation is represented by a 4x4 matrix, will this still work??


Yes, it will work, as long as the z-axis is the reference direction (forward) for the object. The same technique can be used for the x and y directions. For an arbitrary reference direction: define a normal vector in the object's local coordinates, then transform said normal to world coordinates using the 3x3 submatrix of the 4x4 matrix (or set translation to zero, etc.).
Genjix
Genjix
i'm lost... why can he not just apply the matrix to an axis aligned vector?
John Schultz
John Schultz
Quote:
Original post by Genjix
i'm lost... why can he not just apply the matrix to an axis aligned vector?


A rotation matrix contains 3 "axis aligned"* unit vectors, ready to use as is: just extract the appropriate rows or columns. Thus, it's faster and easier to extract the information that already exists (3 copies verses 9 multiplies and 6 adds with additional intermediate/copy overhead).

My matrix system is right-handed and row oriented (matrix -> vector transforms are computed as 3 dot products (fast memory access)). To get an object to trivially move forward:

(xCol(), yCol() and zCol() return the appropriate column of the row oriented rotation matrix).

struct Object {
Mat3 rotation;
Vec3 pos;
float speed;
};

...

pos += rotation.zCol()*(-speed)*deltaTime // scalar speed negated to flip z sign.

To move up:

pos += rotation.yCol()*(speed)*deltaTime

To move right:

pos += rotation.xCol()*(speed)*deltaTime

Thus, it's faster and easier to use this method than to (redundantly) transform an axis-aligned vector. Transforming a direction (normal vector) makes sense for non-axis aligned (local frame) movement.

In the case of a rotation matrix inverted/transposed to be used as a view transform matrix, the row/column rules are swapped. Right-handed systems must always negate z (consider the identity matrix: I = transpose(I)).

In the case one does not know if the system is row or column oriented, left or right handed, it's easy to figure out: it's either the row or the column (x,y,z), and +/- the extracted z direction vector.

A rotation matrix can also be interpreted as 3 unit vectors, orthogonal to each other, creating an orthonormal basis (vectors) and an orthogonal matrix (the term orthonormal matrix also makes sense (since a matrix can be composed of orthogonal but not unit length vectors), and is sometimes used in the computer graphics literature, but traditional linear algebra literature prefers the term orthogonal matrix, even though the description underscribes the system).

*Axis aligned in local coordinates, before rotation to world coordinates.
chad_420
chad_420
SUCCESS!!!
Genjix
Genjix
oh yeah... duh. thanks.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.