Lately, I've noticed fellow Maya riggers creating more and more good resources on the subject of transform matrices. Some more classic ones I've referenced are over at MacaroniKazoo and KimonMatara, and the most recent addition is from Vasil Shotarov's blog. Refreshing my knowledge of matrices has been a rewarding thing to work on over the past several months, as matrix nodes enable and reward stubborn determination through their flexibility to create niche and persnickety control setups, all while remaining fast and stable. The resources mostly fall between the very academic and very specific, so I thought I would contribute by striking a middle ground. So, this is an overview of all of Maya's native matrix nodes and broad-strokes examples of how they can be used.
HoldMatrix
I'll start off with the simplest one. The hold matrix node does literally nothing to its matrix input; it's basically the node equivalent of the Matrix data type. If you have a completely static matrix which you want to have saved in your setup to pipe into another node, this is the cheapest way to do that.
PassMatrix
Pass matrix simply multiplies every element of its input matrix by a connectable scaling factor. It's important to remember that uniformly scaling a matrix in this way does not change its orientation (eulers when decomposed). If you want to scale down a matrix's orientation, you could do that by averaging it with the identity matrix (I).
ComposeMatrix
This node takes standard transform node plugs and converts them into a matrix. Useful for isolating different aspects of an object's matrix, e.g. finding something's rotation matrix by inputting only its Euler/Quaternion values.
DecomposeMatrix
All of the matrix math in the world doesn't help much if we can't turn them into connectable attributes - the matrix plugs on transform nodes are read-only. The decompose matrix node takes its input matrix and spits out translate, rotate, scale, and shear - any of which can be connected independently. This means that you can technically have a shear matrix - that is, a matrix whose three axes are not orthogonal - but if you ignore the outputShear channel on the decompose node, you don't have to worry about it. Currently, rotation can only be output in XYZ-order - if this is fixed, it's likely that a shear matrix would result in different orientations for different output rotate orders. But we can ignore that for now.
InverseMatrix
Practically speaking, every transformation matrix A has an inverse B, and its inverse is defined such that AB = I. What this means in Maya terms is that the transforms of B "undo" the transforms of A. In the above image, locator2's translation and rotation nullify locator1's - so when I parent locator2 to locator1, it stays at the origin aligned to the world axes, no matter what I do to its parent. Practically speaking, uses for the inverse matrix node are few and far between, since transform nodes have built-in inverse plugs for each of their matrix attributes.
TransposeMatrix
A transposed matrix is created by writing the columns of the original as the rows of the transpose. For any non-sheared rotation matrix, it is identical to the inverse matrix. However, standard transformation matrices are 4x4, not 3x3 as a rotation matrix is; so avoid using them as such. One interesting note is that transposing any object's matrix will result in an empty translation channel, since the fourth column of any transform node is empty, and doesn't decompose into anything - it does, however, still factor into multiplication. One possible avenue for using this node would be creating a system that generates rotations by translating a control then transposing and multiplying its matrix. Honestly, though, I haven't found any practical rigging use for this node. Please let me know if you have found one!
FourByFourMatrix
The 4x4 matrix node provides the most control available in Maya towards making a custom matrix data plug. You can set or connect every (float) element, exposed as .in00-.in03, .in10-.in13, etc. Vasil's article linked above shows a great potential use for a 4x4 matrix node - creating a custom orientation from the vector data provided by a PointOnSurfaceInfo node. The PoSI node outputs normal and tangent U/V vectors, which can be considered axis vectors for our custom matrix. We simply connect the components (normalX, normalY, normalZ) to our fourByFour.in00, .in01, .in02, thereby creating a matrix which decomposes into a simpler, slightly cheaper follicle-style transform. In Vasil's example, each axis vector of the 4x4 is considered - but this isn't strictly necessary. If we connect only the X-axis (.in00-.in02) and leave the other two as the (default) standard basis vectors, we get Eulers which align the X-axis to the surface normal but leave the other two axes as close to local default as possible. It's rather like a normal constraint with an easy, default "Local Up" Y-Vector - only cheaper, simpler, and with more control over the surface parameters. It's a technique I've used on the controls for a surface-based rig, as I think the surface U/V directions are rather unintuitive things to align your animation axes to.
AddMatrix
Now for the math-y ones! As far as matrix operations go, addition is simple as heck. This node just adds the pair of values from the same element of each matrix. That's it. Therefore, adding and decomposing the matrices of two objects will result transforms that have added their translations, averaged their orientations, and likely scaled things oddly as well. Likely only one of these would be desirable at a time, and there are simpler ways to achieve any of those on their own. So, on it's own, the add matrix node doesn't seem very useful, until...
WtAddMatrix
This is where the concept gets super useful. The weighted add matrix node could be called "blend matrix", because those are the results that it's capable of giving you. While it doesn't have "true" blend functionality (a simple 0-1 input), it makes up for this in its ability to work on as may input matrices as you want, to any combination of float value weights. It's essentially a self-contained network of PassMatrix nodes feeding into an AddMatrix. DIY multi-target parent constraint? Check, with a couple possible bonuses: it outputs a matrix rather than transform channels, its inputs are simpler and more PyMel-friendly, and the output can actually exceed 100% of any of the targets. Add, average, or anything in between.
MultMatrix
The multiply matrix node is the undisputed champ of rigging utility. Use it to put any object into or take any object out of any parent space (as all spaces are just matrices), or even make a control affect a rig joint in ways not achievable by mere mortal means. The classic is, of course, to chain together object matrices to make parent-style constraints - multiplying matrix A by matrix B, in plain English, says "give me A's transforms in B's space". Similarly, multiplying an B's inverse matrix by matrix A says, "give me A's transforms out of B's space". Make sense?
Let's wade a little deeper. Let the following setup give you a headache:
Inverse parent matrix times matrix times parent matrix? Essentially, "give me locator1's rotations taken out of its parent's space, then put back in its parent's space." It sounds as though it may give you the same thing as locator1's matrix, or perhaps worldMatrix - but since matrix multiplication is non-commutative (order matters), that's not the case. What this setup says is, "treat locator1's rotations as though they were not in this parent space, even though they are still affected by it". In other words, locator1 can be rotated to intuitively animate locator3, and any changes to its parent affect the matrix product only in how they affect locator1's orientation. This may not sound very useful at first, but it's the matrix (read: more accurate) equivalent of an orientConstraint with a dynamic offset of (target space - parent space). The real power of this technique (I call it "bookending") lies in the fact that you can chain as many other matrices into the multMatrix node as you want - in this case, we could precede the bookends with an auto-rotation matrix, or even another control, or both. And each input would affect the target as intended. Pretty powerful stuff.
PointMatrixMult
Finally, we come to the point matrix multiply node. This one only has a single matrix input, plus an additional vector input, and spits out a vector. It essentially asks the question, "where is the given point in the given space?" There's also an attribute "Vector Multiply", which controls whether the output is world position relative to the input matrix. It's best illustrated visually:
As an aside, the results with Vector Multiply On/Off are the same as the results from a VectorProduct node set to "Vector Matrix Product" and "Point Matrix Product", respectively. The first method (relative) is a handy technique to isolate a particular axis from an input matrix. Simply set .inPoint or .input1 to (1, 0, 0) to get the vector representing any space's X-axis. The other mode accomplishes nothing more than a transform node under the space in question, while being more opaque. However, if the input matrix is from one of these other matrix nodes rather than a DAG object, I could see its utility in saving some nodes.
And that's all of them! If I could wish more native matrix nodes into existence, I would likely start with one that extracts just the rotation or translation matrix from its input, followed by perhaps a "true" blend matrix node. There's nothing stopping me from making these, but custom nodes can diminish the portability of any project. In any case, I can safely say that my rigging game has improved from a familiarity with these nodes. And as I mentioned, they reward determination and willingness to experiment - traits riggers tend to have. If you have discovered cool uses that I didn't mention for any of these nodes, leave a comment! Until next time.