Matrices, Transforms, and JME3

As a personal project for my own education and development, I’m writing a COLLADA importer/translator for visualization with JME3. Though, I’m having trouble wrapping my head around the matrix information included in the specification.Please correct me if I’m wrong on the following point: Matrix multiplication is non-commutative, ergo you can’t have a meaningful transform matrix if you don’t know the order in which the various transformations were multiplied.

I’m not so much asking for help reading the COLLADA spec, I just want to make sure the theory is correct in my head, and who better to ask than game developers :slight_smile: So the big question is. If you encountered an arbitrary transform matrix, how should it be interpreted? In my own little world. It seems like the translation info would be pretty straightforward to extract, but if there is any rotation information involved at all, the whole matrix becomes a mess and translation, scaling, and rotation then requires more information.

I apologize if this is the wrong venue, the COLLADA forums seem terrible, and I don’t really want to fight with reddit users and their comments, so please forgive me for a slightly unrelated post.

best regards,

1 Like

A matrix is the result of every accumulated transformation. The order of those operations is important to where you end up but if you are already there then they don’t matter anymore.

A simple thought experiment can show you how they are not commutative. Imagine turning your head to the left 90 degrees and then leaning it down (ear down) 45 degrees. This would be a 90 degree rotation about the y axis and then a 45 degree rotation about the z axis (in JME terms). You should not be looking at the wall to your left… sideways.

If you reverse the order of those operations then you end up looking at the floor.

Non-commutative.

In either case, the resulting transform is enough to describe your current orientation… regardless of how you got there.

2 Likes

Got it, awesome!

This page: The Mathematics of the 3D Rotation Matrix seems to suggest that it is relatively easy to get each piece of information from the matrix in this specific order:

  1. Get 3x3 rotation matrix from 4x4 transformation matrix. Record rotation information.
  2. Invert a copy of the 3x3 rotation matrix and multiply it by the original 4x4 matrix. This will leave you with the translation information. Record the translation information.
  3. Scaling information: ?

Is this correct? What does one do if scaling information is included?

I promise I’m not trying to be thick-headed here, I’m just wanting to understand in order to properly convey the ideas to others in the future.

The 3x3 rotation matrix is an orthogonal set of vectors representing a rotated set of coordinate axes (x,y,z). For scale 1, they are length 1. For other scales, their lengths will be different. Scaling can be non-uniform in x,y,z.

Matrix multiplication is applied in reverse order. So the transformation happens in the local space at that current time in the matrix stack of multiplication.

For instance, if I have 2 matrices: 1 which has a rotation component of 30 degrees in the Z axis, and another matrix with a translation component of (0, 10, 0). Then R * T, would result in a translation of 10 units in the world Y, and then a rotation around the local space. Now if I do T * R, then I first rotate, then translate in the local space, which moves me in the new local Y axis. As shown below (sorry for shitty drawing). Left shows the 2 matrices, right shows the results of multiplying them together.

1 Like

@wezrule thanks for the diagrams! VERY helpful!

What if you don’t know the order in which the matrices were multiplied?

@jagwire said: @wezrule thanks for the diagrams! VERY helpful!

What if you don’t know the order in which the matrices were multiplied?

Why would you care?

If you just have a 4x4 matrix, then the stuff pspeed said will help you extract the info from that. You’ll have a translation column/row (depending what format you use), and a 3x3 matrix with rotation and scaling in it.

@pspeed said: Why would you care?

@pspeed I thought caring was a prerequisite. In the diagrams @wezrule provided, it looks like the order very much results in where your object being transformed ends up. For example, in the two right-most diagrams, the right-most position lies on the y-axis (or so it seems) and the the next-to-right-most diagram the position looks like a bit to the left of the y-axis. Thus, it looks like the location of my object will be a bit more to the left if I rotate first and then translate, instead of the other way around.

@jagwire said: @pspeed I thought caring was a prerequisite. In the diagrams @wezrule provided, it looks like the order very much results in where your object being transformed ends up. For example, in the two right-most diagrams, the right-most position lies on the y-axis (or so it seems) and the the next-to-right-most diagram the position looks like a bit to the left of the y-axis. Thus, it looks like the location of my object will be a bit more to the left if I rotate first and then translate, instead of the other way around.

What do you have? Do you have a transformation or do you have a handful of random transformations?

I assumed that an object had a single transformation. You don’t need to know where it came from because it is THE transformation. It incorporates the order already.

@pspeed said: What do you have? Do you have a transformation or do you have a handful of random transformations?

I assumed that an object had a single transformation. You don’t need to know where it came from because it is THE transformation. It incorporates the order already.

@pspeed one such example is the following:

                0.9238795 -0.3826834 0.0000000 -318.7583909
                                0.3826834 0.9238795 0.0000000 -769.5508305
                               -0.0000000 0.0000000 1.0000000 0.0000000
                                0.0000000 0.0000000 0.0000000 1.0000000

This matrix “looks” like it has both rotation and translation information incorporated in it. But was it T * R or R * T?..it sounds like you’re saying it doesn’t matter…which would be awesome, but I thought @wezrule just said it did matter?

As an aside, thanks for all the patience!

Just a sidenode, if your actual target is not to create a dae importer, but just to get your assets ingame, you can import them into blender and then save, jme can load the .blend file directly.

It does not matter in your case.

It matters only if you build a matrix from a chain of transforms.

You still have World-Coordinates = Transform-Matrix * Local-Coordinates.
You don’t mind if you rotate it then translate or the opposite. Both are possible, but the result will be the same (the individual transforms won’t…)

@jagwire said: 0.9238795 -0.3826834 0.0000000 -318.7583909 0.3826834 0.9238795 0.0000000 -769.5508305 -0.0000000 0.0000000 1.0000000 0.0000000 0.0000000 0.0000000 0.0000000 1.0000000

You won’t always be able to get the exact transformation matrix order back that was used to create it, as there’s potentially an infinite number of ways to arrive at a final transformation (e.g R * T * T1 * R1 * R2).

You only know the overall transformation (translation, rotation, scale), and for that transform matrix:

Translation is (-318.758, -769.55, 0). And from the topLeft 3x3 matrix, rotation can be found to be 22.5 degrees around the Z axis (the bottom matrix in the image is for Z rotation) with scale as 1:

Just had to do acos (0.9238795) = 0.39 radians.

@jagwire said: @pspeed one such example is the following:
                0.9238795 -0.3826834 0.0000000 -318.7583909
                                0.3826834 0.9238795 0.0000000 -769.5508305
                               -0.0000000 0.0000000 1.0000000 0.0000000
                                0.0000000 0.0000000 0.0000000 1.0000000

This matrix “looks” like it has both rotation and translation information incorporated in it. But was it T * R or R * T?..it sounds like you’re saying it doesn’t matter…which would be awesome, but I thought @wezrule just said it did matter?

As an aside, thanks for all the patience!

As Wezrule points out, order is irrelevant at this point because the matrix multiplication is explicit.

I like your matrix because it is a good example. If you know what the values mean you can even look at it and visualize exactly what it’s doing.
[java]
0.9238795 -0.3826834 0.0000000 -318.7583909
0.3826834 0.9238795 0.0000000 -769.5508305
-0.0000000 0.0000000 1.0000000 0.0000000
0.0000000 0.0000000 0.0000000 1.0000000
[/java]

Even Wezrule’s post implies it’s a little more complicated than it looks. For example, I can just look at the numbers and know what this matrix is doing.

If anyone is interested, I can explain how you can easily visualize what a matrix is doing. Then it will never be confusing again. It’s the one thing I miss using Quaternions (they are just magic)… well, the only thing I miss.

@pspeed said: As Wezrule points out, order is irrelevant at this point because the matrix multiplication is explicit.

I like your matrix because it is a good example. If you know what the values mean you can even look at it and visualize exactly what it’s doing.
[java]
0.9238795 -0.3826834 0.0000000 -318.7583909
0.3826834 0.9238795 0.0000000 -769.5508305
-0.0000000 0.0000000 1.0000000 0.0000000
0.0000000 0.0000000 0.0000000 1.0000000
[/java]

Even Wezrule’s post implies it’s a little more complicated than it looks. For example, I can just look at the numbers and know what this matrix is doing.

If anyone is interested, I can explain how you can easily visualize what a matrix is doing. Then it will never be confusing again. It’s the one thing I miss using Quaternions (they are just magic)… well, the only thing I miss.

I’d greatly appreciate an explanation on easily visualizing what a matrix is doing.

i am also interested.
i want to see the matrix.

Working on it… making some pics to go with it. :slight_smile:

First let me sweep Quaternions under the rug. They are magic. They are wonderful. They are inscrutable.

So let’s forget about them.

The beauty of the transformation matrix is that you can look at it and see what is going on. I will show you how… but first I will digress a little. I’m going to try to explain why so that maybe it’s easier to remember and confirm.

Sorry if any of this is review.

Vector Projection

A unit vector represents direction. We say that because it is easy to plot things in that “direction”.

If we are at some location and we want to travel one unit in that direction then we just add it.
me + v = me there

If we want to travel 5 units in that direction then we add it 5 times. Or add v * 5.
me + v * 5 = me there farther

So let’s say we had two vectors representing an orthogonal set of axes. A rotation in space. One points down a new x-axis and the other points down a new y-axis.

If we want to figure out what x=4, y=5 in this new space is in our regular space we could travel xv 4 times and then yv 5 times.
me + x * xv + y * yv = me at 4,5 in rotated into regular space

This works in 3D also but you’ll have to trust me because I can’t draw in 3D.

But in 3D you would need three of these direction vectors. One to represent the x axis, one for the y axis, and one for the z axis. With these, given and x,y,z location we could figure out what x,y,z in this new space means in our regular space. Just like the 2D version above.

Put that aside for a second while I talk about matrix multiplication.

Matrix Multiplication

You will often see this explained a different way. For example, this site: http://www.facstaff.bucknell.edu/mastascu/elessonsHTML/Circuit/MatVecMultiply.htm

…has a nice animation showing it backwards for my purposes. So I will explain it myself… :slight_smile:

Given some matrix:

And some Vector: Vx, Vy, Vz

Step 1: Multiply the vector components by the columns.

Step 2: Add the column vectors together.

Rx,Ry,Rz is the result.

If the matrix was a rotation matrix then we get a rotated point as the result. But why?

If you’ve been following along then maybe it’s starting to become clearer why I did the multiply then the add.

The Rotation Matrix
In a rotation matrix, the 3x3 matrix is actually 3 vectors. The vectors represent the axes of rotation.

So in this matrix, we have three vectors…

Each of them is length 1 and they are 90 degrees from each other, ie: orthogonal. You can picture this in your head.

The Z axis is pointing straight up. The X and Y axes are rotated slightly because X in the X-axis vector is almost 1 and Y in the Y-axis vector is almost one.

Kind of like this: (I’m just drawing the x,y)

You can remember this by understanding how the matrix is actually doing it’s job. We can put together the things I talked about above. Matrix multiplication and vector projections.

If we want to project a x,y,z coordinate into this space then we’d project X down X-axis, add the projection of Y down the y-axis, and so on.

And well… isn’t that exactly what the matrix multiplication is doing? It multiples the x,y,z by each column and then adds those columns (ie: vectors) together.

Tada… now you should be able to visualize what a rotation matrix is doing. You might even be able to draw it on paper if you can’t graph in your head.

Transformation Matrix
The full up transformation matrix is an interesting beast in its simplicity. It almost feels like magic.

But wait… won’t the translation thing screw up our nice picture? No, in fact, here is the other reason I broke it down as multiplication then vector addition.

When you multiply a 3 component vector by a 4x4 matrix, you actually have to add a fourth component: 1
x, y, z, 1

So you’ll end up with four vectors and then add them together. From this it should be clear what order things happen in. (rotation then translation)

It is interesting to note that the bottom row of a column-major 4x4 matrix is basically useless in a regular transformation matrix. Many graphics-oriented math packages will just leave it out. (It is useful for a projection matrix but let’s pretend those are magic for now.)

So, what about scale?

Well, what do you think happens if you were to make those axis vectors non-unit? What if x-axis, y-axis, and z-axis were actually length 0.5 instead of length 1?

I’ll leave that as an exercise for the reader since I’ve already hand-drawn on imgur images too many times in this post.

11 Likes

@pspeed this is fantastic! With your permission, I’d like to use this in development of some instructional materials for co-workers. I’d also encourage this be saved/published in the JME3 mathematics documentation…even if just for background information.

To continue the discussion one step further, we have this transform matrix, and JME3 spatials have a Transform object including a vector3f for translation, a quaternion for rotation, and a vector3f for scale.

How do we convert from one to the other?

Is there a utility class to interpret a transform matrix into a Transform object and vice-versa?