Left-Handed Euler Rotation Matrices

Started by
5 comments, last by L. Spiro 10 years, 10 months ago
I am trying to emulate the FBX system of determining an object’s local transform (described here).
For simplification, I only need to worry about the local Euler rotations of the object—the scale, pivots, pre-rotate, post-rotate, etc., are all “identity” and do not contribute to the result for my test work.

That means I only have to take an X-rotation matrix, Y-rotation matrix, and Z-rotation matrix and combine them in that order (because I am using row-major matrices whereas they are using column-major matrices).

When I actually construct these 3 matrices and combine them in that order, it works fine. Code for the way I construct them (only upper 3×3 shown):
MatrixRotationX( _tType _tAngle ) {
    LSREAL fS;
    LSREAL fC;
    CMathLib::SinCos( static_cast<LSREAL>(_tAngle), fS, fC );
    _11 = 1.0;
    _12 = 0.0;
    _13 = 0.0;
 
    _21 = 0.0;
    _22 = fC;
    _23 = fS;
 
    _31 = 0.0;
    _32 = -fS;
    _33 = fC;
}
MatrixRotationY( _tType _tAngle ) {
    LSREAL fS;
    LSREAL fC;
    CMathLib::SinCos( static_cast<LSREAL>(_tAngle), fS, fC );
    _11 = fC;
    _12 = 0.0;
    _13 = -fS;
    
    _21 = 0.0;
    _22 = 1.0;
    _23 = 0.0;
    
    _31 = fS;
    _32 = 0.0;
    _33 = fC;
}
MatrixRotationZ( _tType _tAngle ) {
    LSREAL fS;
    LSREAL fC;
    CMathLib::SinCos( static_cast<LSREAL>(_tAngle), fS, fC );
    _11 = fC;
    _12 = fS;
    _13 = 0.0;
    
    _21 = -fS;
    _22 = fC;
    _23 = 0.0;
    
    _31 = 0.0;
    _32 = 0.0;
    _33 = 1.0;
}
According to this, this is a left-handed system that has been transposed for my row-major matrices (theirs are column-major). My assignments are grouped by rows, and my row [_11, _12, _13] matches their first column except that the sign of the sine’s are reversed, making it left-handed (I guess?).

In any case, if I use these to manually combine the XYZ Euler rotations from the FBX data the result is correct.
But I don’t want to construct 3 matrices and multiply them together when I know there is a way to get the result directly.

So I checked here to get some direct conversions.
My code for their Tait-Bryan XYZ set follows (exactly the same but transposed into row-major):
MatrixRotationXYZ( _tType _tX, _tType _tY, _tType _tZ ) {
    LSREAL fS1, fC1;
    CMathLib::SinCos( static_cast<LSREAL>(_tX), fS1, fC1 );

    LSREAL fS2, fC2;
    CMathLib::SinCos( static_cast<LSREAL>(_tY), fS2, fC2 );

    LSREAL fS3, fC3;
    CMathLib::SinCos( static_cast<LSREAL>(_tZ), fS3, fC3 );

    _11 = fC2 * fC3;
    _12 = fC1 * fS3 + fC3 * fS1 * fS2;
    _13 = fS1 * fS3 - fC1 * fC3 * fS2;

    _21 = -fC2 * fS3;
    _22 = fC1 * fC3 - fS1 * fS2 * fS3;
    _23 = fC3 * fS1 + fC1 * fS2 * fS3;

    _31 = fS2;
    _32 = -fC2 * fS1;
    _33 = fC1 * fC2;
}
Obviously, this is not going to work, as it is right-handed and transposing is not enough.
How do I make this left-handed? I need at least this one, but best would be a table of all combinations (YZX, XZY, ZYX, etc., as on Wikipedia).


Thank you,
L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Advertisement

M' = ScaleMatrix(1, 1, -1) * M * ScaleMatrix(1, 1, -1)

I tried it; the model vanishes completely. Besides I am specifically trying to avoid any matrix multiplication.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I did the multiplication and got

_11 = c2c3

_12 = c2s3

_13 = -s2

_21 = s1s2c3 - c1s3

_22 = s1s2s3 + c1c3

_23 = s1c2

_31 = c1s2c3 + s1s3

_32 = c1s2s3 - s1c3

_33 = c1c2

I may have made a mistake though. Just multiply the matrices together...

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley
Doing the math by hand is my plan for the rest of them too. I’m planning to make some temporary code that will print the whole multiplication process for each matrix to make it easy and accurate.

But first I will try yours and get back.


L. Spiro


[EDIT]
Yours works.
I will do the rest by myself and post the results later for anyone who needs them all.
[/EDIT]

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

You might want to remember that when dealing with products of transposed matrices, the following formula applies:

(AB)T = BT * AT

EDIT: Proof here: http://www.proofwiki.org/wiki/Transpose_of_Matrix_Product

And for multiple products of transposes

(A1A2...An-1An)T = AnT * An-1T * ... * A2T * A1T

Which is very similar to the product of inverses formula too (replace AT with A-1). The inverse formula is trivial to prove.

EDIT2: So, since your X, Y, Z rotation matrices are transposed, you should find that XTYTZT = (ZYX)T

i.e. your XYZ rotation matrix will be the other library's ZYX rotation matrix, transposed.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

I didn’t think of it that way.

I hadn’t had time to get around to my method of printing them out and simplifying due to health issues, so this will definitely save me some time. Thank you.

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

This topic is closed to new replies.

Advertisement