0
$\begingroup$

I'm trying to use Blender to test some matrix transforms but I'm still trying to learn at the same time. The problem is how to use the Python API to apply a rotation matrix, but to start with I have tried this step.

First I added a Mesh Plane then Scaled it along Y axis so it forms a rectangle.

Running the code causes the plane to rotate but the shape is "restricted" by the scale of the shape before the transform. I expected the whole plane to rotate around the x-axis and keep the shape.

import mathutils
from mathutils import Matrix
from math import radians
import bpy

mat_rot = mathutils.Matrix.Rotation(radians(15.0), 4, 'X')

curr_obj = bpy.context.active_object
obj_mat = curr_obj.data
obj_mat.transform(Matrix(mat_rot))
obj_mat.update()

I also notice in the Properties Transform, the Rotation X does not change. Can anyone help me understand what's going on?

UPDATE

lemon, thanks for info on using obj.matrix_world. I have now tried this code now, but even the results are still not as expected. The shape doesn't keep the 6*6 square shape and the Rotation X is only 40.1deg instead of the 45deg. Any ideas?

import mathutils
from mathutils import Matrix
from math import radians
import bpy

bpy.ops.mesh.primitive_plane_add(location=(0, 0, 0))
bpy.ops.transform.resize(value=(6, 6, 1))
obj = bpy.context.active_object
mat_rot = Matrix.Rotation(radians(45.0), 4, 'X')
obj.matrix_world = obj.matrix_world @ mat_rot
$\endgroup$
  • $\begingroup$ obj_mat.transform here changes the mesh vertices (at mesh level). Object transforms (at object level) are still applied after that. If you want to rotate at object level, you can obj.matrix_world = obj.matrix_world @ mat_rot $\endgroup$ – lemon Aug 29 '19 at 10:01
  • $\begingroup$ My bad I meant obj.matrix_world = mat_rot @ obj.matrix_world $\endgroup$ – lemon Aug 29 '19 at 10:51
1
$\begingroup$

In your second example, the shape changes, because your are transforming the mat_rot by the matrix_world, but you need to do it the other way around.

obj.matrix_world = mat_rot @ obj.matrix_world

Further, your code should be streamlined to apply the transformations at object level (and not through ops).

from mathutils import Matrix
from math import radians
import bpy

bpy.ops.mesh.primitive_plane_add(location=(0, 0, 0))

obj = bpy.context.active_object

mat_rot = Matrix.Rotation(radians(45.0), 4, 'X')
mat_sca_x = Matrix.Scale(6, 4, (1, 0, 0))

mat_sca_y = Matrix.Scale(6, 4, (0, 1, 0))
obj.matrix_world = mat_rot @ mat_sca_x @ mat_sca_y

And finally, you can rely on other methods than ops, to add your geometry. See this answer for details on adding geometry from scratch.

from mathutils import Matrix
from math import radians
import bpy
import bmesh

# Create the object and mesh datablock.
me = bpy.data.meshes.new("me")
obj = bpy.data.objects.new("obj", me)

# Apply the transformation.
mat_rot = Matrix.Rotation(radians(45.0), 4, 'X')
mat_sca = Matrix.Scale(6, 4)
obj.matrix_world = mat_rot @ mat_sca

# Add the grid as the mesh
bm = bmesh.new()
bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1)
bm.to_mesh(me)

# Link the object to the scene.
scene = bpy.context.scene
scene.collection.objects.link(obj)
| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you, very good information for me! $\endgroup$ – PJD Aug 29 '19 at 11:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.