::Euler Rotations and Matrices::

October 6th, 2010 by hamish download the zooToolBox

For the most part dealing with positions is fairly easy. You hardly need to learn matrices to to complex manipulations of positions. The hard part about 3d transforms is rotations. It took me a long time to really get rotations – and I would hardly describe my understanding of them as mastery, so there is still a long way to go, but what I do understand has been super useful in my everyday work.

Hopefully I’ll be able to convey my understanding of rotations and you’ll also find yourself more useful in your day to day work.

Rotations are hard to work with unless you know how they work together with matrices.  Have you ever tried to use a rotation channel as a driver for an SDK?  Doesn’t work so hot does it?  Sure sometimes it can work, it depends on the specifics of what you’re trying to do.  But in general they’re functionally useless.

Now bear with me – this gets kinda convoluted – and I’ll let you know now that most of this (converting to/from euler/matrix) is actually covered for you already in the Matrix class in vectors.

Again using the maya docs (although this is I believe again fairly universal) we find that a 3d rotation is the result of multiplying three different matrices together – one for X, one for Y and one for Z.  The order in which these matrices are multiplied together is the rotation order.  So each axis has its own matrix, which look like this:

RX = |  1   0    0    0 |   RY = |  cy  0  -sy   0 |   RZ = |  cz   sz  0   0 |
     |  0   cx   sx   0 |        |  0   1    0   0 |        | -sz   cz  0   0 |
     |  0  -sx   cx   0 |        |  sy  0   cy   0 |        |  0    0   1   0 |
     |  0   0    0    1 |        |  0   0    0   1 |        |  0    0   0   1 |

where:
cx = cos( x )
sx = sin( x )
etc...

So these are the individual matrices for the X rotation, the Y rotation and the Z rotation.  To get the rotation matrix for a transform with XYZ rotation order, you multiply these matrices together in that order.  Similarly for other rotation orders etc…

Now when you multiply these three matrices together, you get a big giant mess.  But the big giant mess of a matrix can be used to turn euler angles into a rotation matrix, or can be used to figure out how to convert a rotation matrix back to euler angles.  How?  Well, lets figure out what the matrix for XYZ looks like.  Doing the matrix multiplication is arduous – so I won’t do it here (in fact I was so lazy I wrote some code to do the multiplication for me.  On a side note, does anyone know of any way to do algebraic matrix multiplication without having to buy matlab or some sort of crazy piece of software?).  Anyhoo if you do it yourself, you’ll find the rotation matrix for an XYZ euler rotation looks like this:

XYZ = | cz*cy,   sz*cx + cz*sy*sx,  sz*sx - cz*sy*cx |
      | -sz*cy,  cz*cx - sz*sy*sx,  cz*sx + sz*sy*cx |
      | sy,     -cy*sx,             cy*cx            |

Kinda ugly looking huh?  But clearly this makes it super easy to get the matrix for an XYZ euler rotation.  Simply calculate the cos and sin for the x, y and z angles and plug em into the equations here.  Bam.  You’re done.  Like a ram.  Or something…  In fact if you look at the FromEulerXYZ method on the Matrix class, thats exactly what it does.  So constructing a matrix from euler angles is a no brainer.

Converting from the matrix to the euler angles however is a little tricker.  Figuring this out boils down to the fact that one of the matrix entries in this case is sy.  Which means we can find the Y rotation easily by doing asin( XYZ[2][0] ).  Now using this, we can use the cx*cy and cz*cy entries to figure out rotation values for X and Z.  Its not quite this simple, but its not far from it.  As it turns out, all the other rotation orders have an entry we can use to figure out the rest.  And again, if you check out the ToEulerXYZ on the Matrix class, the code is already written, I just figured it was useful to break down what is happening in there.  Incidentally there is a more formal paper here which describes how this works in more detail.  I learnt a bunch from it – although its not directly applicable to maya for a few reasons.  But its still helpful.

Kinda shortish post I know.  Originally this was going to be post number 4, but a few of you suggested that I do a post with some actual code, so I figured a walk through of the rotation mirroring node would do the job.  Anyway, I’m not sure if folks are interested in me taking this topic any further.  I was thinking of walking through an aim constraint (which I haven’t done yet – it’d be a fun exercise).  Anyone have any thoughts?

This is post 5 in the matrix series.

Share

This post is public domain

This entry was posted on Wednesday, October 6th, 2010 at 21:07 and is filed under main, tutorials. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

  • Dave

    Hey Hamish,

    A BIG BIG thanks for these articles on Matrices and rotations.

    I’ve struggled with this side of being a tech artist for a fair while.

    I’ve also always tried to go through your code and understand whats going on, even when you change it all in a submission, I sit there and try and work out why you changed it.

    I’m trying to find the time to embark on a floppyCST adventure again this time in python and these articles and you new code should make it easier (and me smarter :))

    Dave

  • Dave

    Oh and a walk through of the mirror code would be cool, i’ve been looking over that one a little since it went up last weekish.

    Dave

  • hamish

    You want another walk through? did you see this one: http://www.macaronikazoo.com/?p=451

    I didn’t get any comments on it – perhaps because it was way to dense, or perhaps because it was super clear, I don’t know (although I doubt the latter!). But that was my shot at walking through the code.

  • floppyDJ

    Urgh my bad Hamish, I missed that one.

    I read your site through google reader and it got lost in my list!

    I will endeavour to get to it soon!

  • Josh

    Hamish,

    Thanks for the explanation of rotations. As a young, eager, tech artist, it’s been great reading

    through some of your articles (and challenging for areas I can’t yet wrap my head around). I’ve been

    reading bits here and there of David Gould’s “Complete Maya Programming” book. Great

    explanations in there! I would like to see how the math in an aim constraint works if you don’t mind

    breaking it down. Thanks again for all the time you put in to teaching us!

  • hamish

    thanks Josh! yes, I still plan to do the aim constraint. Things have just been a bit busy this last week, but I’ll hopefully get to it next week!

  • phage

    Hammish, much appreciated! Perfectly weighted detail for me. I’m also very interested in your implementation of an aim constraint.

    Thanks, props!

  • tm

    Thanks for these excellent notes. However I still can’t figure out how to add two euler rotations together- can you offer any advice?
    Reference:
    http://www.akeric.com/blog/?p=1067
    http://www.isner.com/tutorials/quatSpells/quaternion_spells_14.htm#7) Adding 2 Quaternions
    I’d like to convert this into a scripted python node with two rotate inputs and one output rotate:

    file -f -new;
    group -em;
    setAttr “null1.rotateZ” 400;
    setAttr “null1.rotateX” 400;
    setAttr “null1.rotateY” 400;
    rotate -r -os -rotateXYZ 400 400 400 null1;//add RELATIVE rotation
    getAttr “null1.rotateZ”;
    // Result: 826.940102 //
    getAttr “null1.rotateX”;
    // Result: 826.940102 //
    getAttr “null1.rotateY”;
    // Result: 750.793468 //

  • Ryan Gordon

    There are MATLAB alternative like octave and scipy, but MATLAB can support euler angles more directly.