If you ever work in 3D, you need to understand the mysterious modelMatrix.

That’s what this post is about. It’s actually not very hard to understand.

### What is modelMatrix?

modelMatrix is a 4×4 matrix that holds all the translations, scaling and rotations you make when you draw.

What makes it amazing is that when you multiply this matrix by any position vector, it will translate, scale and rotate it to exactly the right place. So it doesn’t just store translations and rotations, but it does it in a very useful way!

Let me show you how it works. There will not be any difficult math.

This is how modelMatrix looks before you translate or rotate anything. To see it, print(modelMatrix())  – don’t forget to put the brackets after modelMatrix!

```(1    0    0    0)
(0    1    0    0)
(0    0    1    0)
(0    0    0    1)
```

Let’s see what happens when we multiply it by a 3D position vector, say x=1, y=2, z=3, and our vector is vec4(1,2,3,1). Note that a position vector uses a vec4, and the last number is always 1. You’ll see why, soon.

```(1    0    0    0)    x   (1   2   3    1)
(0    1    0    0)
(0    0    1    0)
(0    0    0    1)
```

You put the vector on the right, and now we apply the first column of the matrix to the vector to get the new value of that item = 1×1 + 0x2 +  0x3 + 0x1 = 1, ie unchanged.

We apply the second column of the matrix to the second item in the vector = 0x1 + 1×2 +  0x3 + 0x1 = 2, ie unchanged.

If you do this for all four items in the vector, you will get (1  2  3  1), ie unchanged. This is as it should be, because we haven’t translated or rotated yet.

### Translating

Let’s translate to x=10, y=15, z = 20, with the command translate(10,15,20)

modelMatrix now looks like this

```(1    0    0    0)
(0    1    0    0)
(0    0    1    0)
(10   15   20    1)
```

Now, if we multiply this matrix by our vector (1  2   3  1), we get (11  17  23  1), ie our vector has been translated correctly by (10  15  20).

The reason is very simple. The translations for x, y and z are put at the bottom left of the matrix as you can see above, and they are multiplied by the fourth item in our position vector, which I told you is always 1. So what that fourth item does is to simply add in whatever translation figure is given in the bottom row of the matrix. And that’s why that fourth item is there.

If this isn’t clear, look at what happens when we multiply the first column of the matrix by the vector, to get the new x value for the vector = 1×1 + 0x2 + 0x3 + 10×1 = 11

So you can always tell what the current translation values are by looking at the bottom left of the modelMatrix!

### Rotations

Suppose our modelMatrix looks like this below, with two values swapped around and we multiply by the same vector as before, what do we get?

```(1    0    0    0)    x   (1   2   3    1)
(0    0   -1    0)
(0    1    0    0)
(0    0    0    1)
```

The four new vector values are

```1x1 + 0x2 + 0x3 + 0x1 = 1
0x1 + 0x2 + 1x3 + 0x1 = 3
0x1 + -1x2 + 0x3 + 0x1 =-2
0x1 + 0x2 + 0x3 + 1x1 = 1
```

So we get ( 1  3  -2  1). What does this mean?

We have just rotated 90 degrees on the x axis. If you stood in front of me and I pushed you, so you fell onto your back, that’s the way we have just rotated. Let’s check the results.

If we rotate forwards, it doesn’t affect the x value, because we haven’t moved left or right. So that should still be 1.

The y value was 2, pointing straight up in the air. After we rotate forward, it is lying on its back, pointing forwards into negative z (remember, in 3D, z is negative in front of us). So the y value is now at -2 on the z axis.

The z value was 3, pointing forward towards us. When we rotate, the z value will be pointing upwards, at 3 on what was the y axis.

So we expect the new vector to be ( 1  3  -2  1), which it is.

This simple example shows how the top left 3×3 part of the matrix can be used to do rotations. For any rotation, there is a 3×3 set of numbers which will correctly rotate any vector. I won’t bore you with the formulae that are used to calculate the matrix values.

So the top left 3×3 part of the matrix handles rotations, and the bottom row holds the translations.

It’s really very clever.

### Scaling

If you use the scale command to change the size of what you are drawing, OpenGL multiplies the rotation part of modelMatrix by the scale value, so if that value is 3, then the top left 3×3 cells are multiplied by 3. This will make any vector 3 times larger, which is what you want.

### How OpenGL uses modelMatrix

Each frame, OpenGL starts off with the default modelMatrix, and as you translate, scale and rotate, it adjusts modelMatrix. When you draw, it applies modelMatrix to each position vector (in the case of images, these are the corner positions), and if you are drawing a mesh, then each vertex will be adjusted.

When you use pushMatrix() to store current settings, Codea stores a copy of the current modelMatrix, and when you use popMatrix, Codea puts that copy back into modelMatrix.

Very simple, very clever.

From → 3D, Graphics