# Blender Python Bites #6 – Performing arbitrary transforms

Transformation matrices are a concise way to represent linear transformations in 3D space. They let you model any linear transformation you can imagine using a single 4x4 matrix.

Here’s how we can perform transformations like translate, rotate and scale along arbitrary axes using them in the Blender API. 👇🏻

Let’s assume the arbitrary axis to be a line that passes through p1 and p2, where:

```
import bpy
from mathutils import Matrix, Vector
p1 = Vector((1, 3, 2))
p2 = Vector((-4, -2, -7))
```

Subtracting p2 from p1, we get p1 -> p2 vector

```
direction = p2 - p1
```

In order to be able to use this for transformations, we need the unit vector pointing in this direction. We can get this using `Vector.normalize()`

```
direction.normalize()
```

Or if you don’t want to modify ‘direction’ in-place:

```
direction_n = direction.normalized()
```

Now we can use this direction vector to perform our transformations.

Let’s use the gorgeous default cube:

```
obj = bpy.data.objects['Cube']
```

## 1. Translation

To translate an object in this direction, we do:

```
obj.location += magnitude * direction
```

Where magnitude is the number of units we want to move our object along ‘direction’. E.g. To move 2 units along ‘direction’:

```
obj.location += 2 * direction
```

This would translate our cube like so:

## 2. Rotation

To rotate an object along ‘direction’, we do:

```
import math
matrix_rotation = Matrix.Rotation(math.radians(30), 4, direction)
obj.matrix_world @= matrix_rotation
```

Where the first argument in `Matrix.Rotation()`

is the angle of rotation (converted to radians using `math.radians`

). This creates a transformation matrix for rotation.

The `obj.matrix_world`

is the transformation matrix of our object in question. By doing a matrix multiplication `@=`

of this with our rotation matrix, we can perform rotations along an arbitrary axis.

If you are running this in the Python Console directly, you can re-run the last line a few times to see how the cube rotates.

## 3. Scaling

To scale an object 2 units along ‘direction’, we do:

```
matrix_scale = Matrix.Scale(2, 4, direction)
obj.matrix_world @= matrix_scale
```

Where the first argument in `Matrix.Scale()`

is the number of units by which we want to scale. The `Matrix.Scale()`

function lets us create a transformation matrix for scaling.

But scaling an object like this wouldn’t produce the effect we imagine. Because performing a scaling transform in object mode behaves differently from translation or rotation.

In order to get the desired effect, we can use the bmesh module

```
import bmesh
# Create a new BMesh object
mesh = bmesh.new()
# Add the mesh data from our object
mesh.from_mesh(obj.data)
# Apply the transform using mesh.transfor() method
mesh.transform(matrix_scale)
# Nothing would change yet, since we have to apply these tranforms
# back to our original object
mesh.to_mesh(obj.data)
# Free the BMesh object
mesh.free()
```

And that’s it. If you notice, our object is now scaled along our ‘direction’ vector:

So that’s how you can perform transformations on arbitrary axes. The same can be applied to mimic tools like vertex slide and many other transforms we do in Blender.

As an exercise, see if you can implement a vertex slide operation using matrices and the bmesh module. 🙌🏻

## Resources

- Linear Algebra series by 3Blue1Brown
- Mathematics for Computer Graphics book by Springer

## Subscribe to my newsletter

Join other *Technical Artists*, *Developers* and *CG enthusiasts* who receive my latest posts on Blender, Python, scripting, computer graphics and more directly to their inbox.