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
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']
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:
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.
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.
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. 🙌🏻
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.