# Meshes with Python & Blender: Cubes and Matrices

25.08.2017 @ Tutorials

Welcome to the sec­ond part in this series. It’s time to get into some math and learn how to con­trol the posi­tion, rota­tion and scale of the mesh.

This tuto­r­i­al builds on the lessons of part one. If you find your­self lost too often, try going back. Today we will quick­ly look into mak­ing cubes, and then jump into con­trol­ling the mesh and ori­gin point’s posi­tions. Finally we’ll dive into trans­for­ma­tion matri­ces and learn how to per­form trans­for­ma­tions nice and fast.

## The usual setup

Let’s start by import­ing the pack­ages we need. Besides the usu­al `bpy`, we are also going to use the `radians()` func­tion from Python’s math pack­age, as well as the `Matrix` class from mathutils (this one is from Blender).

As before, I’ll have a sec­tion to put vari­ables in, then util­i­ty func­tions and final­ly the main code sec­tions. The `vert()` func­tion looks use­less now but we’ll need it for the next bit.

## Making the cube

Making a cube is less glam­orous than you would expect since there’s no fan­cy algo­rithm to make them. Instead we have to input the vert posi­tions and faces man­u­al­ly. Luckily cubes only have 6 faces and 8 ver­tices.

Run the script now and you will be reward­ed with a very default cube. Now that was easy! Let’s see what we can do with it.

## Moving the origin point

Every object in Blender has an ori­gin point that deter­mines their posi­tion in 3D space. In fact when we talk about an object’s posi­tion we actu­al­ly talk about the posi­tion of its ori­gin point. On the oth­er hand when we talk about an ori­gin points’ posi­tion we actu­al­ly talk about the ori­gin points’ posi­tion rel­a­tive to the mesh.

Confused? Look at the fol­low­ing dia­gram.

As you can see when the orange dot (the ori­gin point) is on the grid, the object’s posi­tion is (0, 0, 0) while when it’s up by 1 on the Z axis the posi­tion is posi­tion is (0, 0, 1). But the inter­est­ing bit is the mesh’s posi­tion. In both cas­es the mesh if off­set by 1, but in the sec­ond case it is ‑1. If the mesh’s posi­tion was (0, 0, 0) it would be up in the air, right where the ori­gin is. As you can see, the mesh posi­tion is rel­a­tive to the ori­gin but inde­pen­dent from the origin’s posi­tion in the scene.

Knowing this, there are two things we can do:

• Change the mesh in rela­tion to the ori­gin point. This is the same as mov­ing the mesh in edit mode.

• Change the ori­gin point while leav­ing the mesh in the same place. For this tuto­r­i­al that would be the cen­ter of the scene.

We will begin by chang­ing the posi­tion of the mesh rel­a­tive to the ori­gin point I will be call­ing this off­set to keep things short.

We can use the vert func­tion to move the mesh with a sim­ple addi­tion.

An off­set of 1 on Z will make the cube rest on the grid with the ori­gin point at its bot­tom.

Now let’s try mov­ing the ori­gin point while keep­ing the cube at the cen­ter of the scene. There’s only one small prob­lem: we can’t move the ori­gin itself. Moving the ori­gin is mov­ing the object, since the ori­gin rep­re­sents its posi­tion in space.

What we have to do is to change the ori­gin is move the mesh as before and move the object by the oppo­site of that off­set.

Remember loca­tion is a tuple, so we have to use an expres­sion to set it.

Try run­ning the code now. The cube mesh is back at the cen­ter of the scene. But the ori­gin point (and the object) is now at (0, 0, ‑1).

Since we are chang­ing the loca­tion using the neg­a­tive of the off­set, the result­ing posi­tion of the object is neg­a­tive. Likewise using a neg­a­tive off­set results in a pos­i­tive posi­tion for the object. Give it a shot.

So what if you want to change the ori­gin and also change the mesh posi­tion in any arbi­trary way so it’s not always at the cen­ter of scene? We can add anoth­er off­set to rep­re­sent that. And then we can add this off­set in the loca­tion expres­sion to move the mesh. Let’s also rename the pre­vi­ous off­set to keep things clear.

Note that we have to use `enumerate()` now to get an index for the addi­tion.

There are sev­er­al oth­er things we could do with expres­sions and the `vert()` func­tion. But there’s anoth­er way of trans­form­ing mesh­es and objects. A way that is both clean­er and faster.

Enter the Matrix

## Matrices

In math matri­ces are rec­tan­gu­lar arrays of num­bers (and some­times oth­er things). They can be added, sub­tract­ed and mul­ti­plied between them­selves. You will find matri­ces in almost every field where math is involved.

The only field we care about though, is com­put­er graph­ics and in this con­text matri­ces are used often to rep­re­sent trans­for­ma­tions. This includes things like trans­la­tion, scal­ing or rota­tion. Matrices that rep­re­sent lin­ear trans­for­ma­tions like these are called “Transformation Matrices”.

Objects posi­tion, rota­tion and scale are defined as trans­for­ma­tion matri­ces in rela­tion to a coor­di­nate sys­tem. Even when you think there’s no trans­for­ma­tion!

For instance, let’s imag­ine a “default object”. This object sits at coor­di­nates (0, 0, 0) of the scene, has a scale of 1 and a rota­tion of 0 (on all axis). We can rep­re­sent the loca­tion, scale or rota­tion of any object as a trans­for­ma­tion matrix of this default object. In Blender this is called a World Matrix, and it is a prop­er­ty avail­able in all objects.

By the way, “scene coor­di­nates” are actu­al­ly called “World Coordinates” in Blender. There are oth­er coor­di­nate spaces, as well as matri­ces for them but we will look into that in anoth­er part of this series (promise!).

Note that you don’t need to be a matrix wiz­ard to use them. The blender devs have blessed us with a `Matrix` class that does almost all the work for us, and you might not even have to see a matrix while you’re work­ing with them. Feel free to jump to “Putting it all togeth­er” if you’re not inter­est­ed in the math.

Still here? Alright, let’s play with this matrix con­cept for a moment. Go ahead and add a new object (using `Shift+A`). Select it, then paste this script on a text edi­tor and run it.

You should see this out­put in the ter­mi­nal:

``````--------------------------------------------------------------------------------
World Matrix
<Matrix 4x4 (1.0000, 0.0000, 0.0000, 0.0000)
(0.0000, 1.0000, 0.0000, 0.0000)
(0.0000, 0.0000, 1.0000, 0.0000)
(0.0000, 0.0000, 0.0000, 1.0000)>
``````

Since we haven’t moved, rotat­ed or done any­thing to the object, its val­ues are the same as our imag­i­nary “default object”. A matrix like this is called an `Identity Matrix` in math, and it means there’s no trans­for­ma­tion.

Now move the cube some­where and run the script again.

``````--------------------------------------------------------------------------------
World Matrix
<Matrix 4x4 (1.0000, 0.0000, 0.0000, -8.8360)
(0.0000, 1.0000, 0.0000, -1.1350)
(0.0000, 0.0000, 1.0000,  8.9390)
(0.0000, 0.0000, 0.0000,  1.0000)>
``````

Aha! Now the matrix includes some change. The val­ues will be dif­fer­ent depend­ing on where you move the object. As you can see the last col­umn includes the X, Y, Z coor­di­nates in rela­tion to the cen­ter of the scene (world space).

What if we reset the loca­tion (`Alt-G`) and try scal­ing instead?

``````--------------------------------------------------------------------------------
World Matrix
<Matrix 4x4 (0.7280,  0.0000, 0.0000, 0.0000)
(0.0000, -1.4031, 0.0000, 0.0000)
(0.0000,  0.0000, 1.7441, 0.0000)
(0.0000,  0.0000, 0.0000, 1.0000)>
``````

Now the last col­umn has no change since the object is back at (0, 0, 0) However we can see three val­ues have changed to rep­re­sent scal­ing on X, Y and Z.

Rotation is more com­pli­cat­ed since you can rotate around three axis and each rota­tion is rep­re­sent­ed by trans­for­ma­tions on the oth­er two axis. This goes a bit out of scope for this tuto­r­i­al, so I’ll leave sev­er­al links at the end in case you want to get deep­er into the math.

``````--------------------------------------------------------------------------------
World Matrix
<Matrix 4x4 (-0.9182,  0.3398, -0.2037, 0.0000)
(-0.2168, -0.8612, -0.4597, 0.0000)
(-0.3316, -0.3780,  0.8644, 0.0000)
( 0.0000,  0.0000,  0.0000, 1.0000)>
``````

You might also be won­der­ing about the last row. Transformation matri­ces for 3D are actu­al­ly 4D, the last row is an extra dimen­sion. This is a math­e­mat­i­cal “trick” to enable the matrix to per­form trans­la­tions. Again, I won’t get too tech­ni­cal about this. Check the links at the end for more info. In any case, it’s not impor­tant for our pur­pos­es since it will nev­er change.

Here’s a dia­gram of the dif­fer­ent trans­for­ma­tions:

## Using Matrices

Transformation matri­ces can be com­bined to cre­ate a sin­gle matrix that includes all the result of all the trans­for­ma­tions. This is done by mul­ti­ply­ing them. That means we can take an object’s world matrix and mul­ti­ply it by a trans­for­ma­tion matrix to get a new matrix that includes the changes in both matri­ces. We can then assign it as the object’s world matrix and thus trans­form the object.

Or to put it in code:

It’s time to whip out that `Matrix` class and see how we can use it to gen­er­ate matri­ces.

### Translation

Let’s start with the eas­i­est: mov­ing stuff. All we have to do is call the `Translation` method of the `Matrix` class with a vec­tor (or tuple) of val­ues for each axis.

### Scaling

Scaling takes three argu­ments. The first one is the scale fac­tor. The sec­ond one is the size of the matrix, it can be either 2 (2×2) or 4(4x4). But since we are work­ing with 3D objects this should always be 4. The final argu­ments is a vec­tor to spec­i­fies the axis to scale. This can be either zero for no scal­ing, or 1 to scale.

### Rotation

Rotation takes almost the same argu­ments as scale. The first is the angle of rota­tion in radi­ans. The sec­ond is the size of the matrix (same as before). And the third is the axis of the rota­tion. You can pass a string like ‘X’, ‘Y’ or ‘Z’, or a vec­tor like the one in scale.

### Putting it all together

We can chain trans­for­ma­tions togeth­er by mul­ti­ply­ing them one after the oth­er. But beware, Matrix mul­ti­pli­ca­tion is not com­mu­ta­tive. Order does mat­ter. Start by trans­la­tion, then rota­tion and scale. If you’re get­ting strange val­ues that look like round­ing errors, look at the order in which you are mul­ti­ply­ing.

Matrices can also be used to change the mesh instead of the object. To do this we can use the `transform()` method of in objects. All it asks for is that you give it a matrix.

Don’t for­get we can also com­bine matri­ces by mul­ti­pli­ca­tion so you can do sev­er­al trans­for­ma­tions in one go.

Not only are matri­ces faster but this method also goes straight to C, so it per­forms con­sid­er­ably bet­ter than cal­cu­lat­ing the posi­tion of each ver­tex in Python (which is quite slow and expen­sive). On top of that, we can do this in a sin­gle line.

Awesome.