Naming Convention for Matrix Math
27/Jul 2017
There’s a fairly common naming convention for matrix math which makes most of the matrix math used in games as simple as slotting together Legos. This is by far the biggest bang-for-buck coding convention I know of. Ever randomly inverted a matrix or swapped the order of a matrix multiply until things look right? Yeah no, you never have to do that again. This really should be taught in graphics programming 101 because it pretty much eliminates all matrix transform headaches.
I make no claims to having invented this. I’ve seen many people use it, but can’t find description anywhere so I’ll put something here.
First, let’s assume we’re using D3D style matrix math convention (I’ll show a variant for the other one later), where vectors are rows, and operations flow from left to right. E.g to transform a point you multiply it “from the left” with the matrix.
|
|
And to transform a point first by M
and then by A
you’d do:
|
|
So the basic naming convention is that every transform matrix is named something like foo_to_bar
, where foo
and bar
are two coordinate spaces. For example world_to_view
or view_to_projection
. This is already pretty useful, now instead of looking at some cryptic matrix called transform_matrix
and wondering what the hell that means, it’ll be spelled out what it actually does (e.g. perhaps you really meant local_to_parent
or object_to_world
).
However, this really begins to shine once you start multiplying matrices together. E.g.
|
|
Two things to pay attention to here. First note that the coordinate space listed on each side of the *
above is world
. That means the multiplication is valid. The rule to remember here is that for a multiplication of two matrices to produce sensible results, the words on either side of a *
have to be the same. If they’re not, you’re doing something wrong.
The second thing to note is that the name for this combined transform is formed by looking at the leftmost and rightmost word of the multiplication chain (in this case object
and view
). This generalizes to arbitrary length multiplication chains:
|
|
And you can also pull out named sub-expressions and things still match up nicely:
|
|
One more rule: when inverting a matrix, you flip the names of the spaces of the original matrix:
|
|
If you follow this convention, transforming points from one coordinate space to the next is just a matter of finding the right sequence of matrices and slotting them together left to right such that the words on either side of all the multiplications match.
For example, let’s say you’re doing a VR game and want to know how to transform a point on an object to the space of the right hand controller. So you look around at what kind of matrices you have available, use inverses where necessary and slot them together until you get what you need. You know the name of the matrix should be object_to_right_hand
so now you just need find a sequence of matrices to multiply together that make that happen. You might end up with something like:
|
|
There’s really no thinking involved here. Just slotting together matrices until the start and end of the multiplication chain have the correct spaces and you’re done.
OpenGL style matrix convention
Yeah I get it, in math textbooks vectors are columns and transforms flow right-to-left so the D3D convention is an abomination etc. etc.
Unfortunately things aren’t quite as nice when using the more traditional column vector notation (which is actually why I’m a recent convert to the D3D style row vector convention). Basically, you now name things like foo_from_bar
instead, and that way you can still just slot things together and make the names on either side of the *
signs match up. E.g.
|
|
It doesn’t read quite as nicely to me, but it’s still has that nice property that it’s trivial to figure out how to transform between two spaces if you can find a chain of matrices that get you there.
That’s it! Start using this and never struggle with transforms again!
Update: naming for points and vectors
Once your transforms are correct, it’s also useful to make sure your points and other vectors have the space in their name. For D3D you want the space at the end so I’d use e.g. point_in_world
, and for the OpenGL style you want the space on the left so something like world_point
. Then things still match up when you multiply points with your matrices.