# Transform matrix on a scaled object

I have to create boxes, cylinders and spheres, to scale them and to rototranslate them in space by using a matrix transform. This is the code for a box:

myObj_TR = Matrix((
(1, 0, 0, 0),
(0, 0.707, 0.707, 0),
(0, -0.707, 0.707, 0),
(1, 0, 0, 1)))

bpy.ops.transform.resize(value=(1,2,.3))

myObj = bpy.context.object
myObj.data.transform(myObj_TR)
myObj.data.update()


The problem is that in this way the box results sheared; it seems that the scaling is actually applied after the rototranslation.

I think that a workaround should be parenting my objects and then rototranslate the parent. Are there alternative ways?

Thank you

You are applying transformation at object level with bpy.ops.transform.resize() and on data level with myObj.data.transform(). The data transform is directly applied to vertices. The vertices' position simply is updated and the transformation is lost. When applying the transformation to the object the matrix is stored (if possible) in the translation, rotation and scale properties of the object. The object transform is applied on the vertex positions. In your case this results in objMatrix @ dataMatrix or scaleMatrix @ locrotMatrix.

You want to swap that order. I would advise you to either apply the transformation to the object or the data.

You can construct the final matrix separately first.

import bpy
from mathutils import Matrix

mat_rot = Matrix([[1,  0,     0,     0],
[0,  0.707, 0.707, 0],
[0, -0.707, 0.707, 0],
[1,  0,     0,     1]])

mat_scale = Matrix([[1, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 3, 0],
[0, 0, 0, 1]])

mat = mat_rot @ mat_scale


If you want to apply this matrix at the object level, use object.matrix_world.

bpy.ops.mesh.primitive_cube_add()
myObj = bpy.context.object
myObj.matrix_world = mat


If you want to apply this matrix at the data level, use data.transform().

bpy.ops.mesh.primitive_cube_add()
myObj = bpy.context.object
myObj.data.transform(mat)


From the comments: If you don't import your matrix, but are constructing them from scratch, use the Helper constructors from the Matrix class, such as Matrix.Diagonal or Matrix.Rotation

• Worth noting: bpy.ops.transform... applies on a data level when in edit mode. (on selected geometry). There are nice constructors for matrices eg R = Matrix.Rotation(radians(45), 4, 'X') and S = Matrix.Diagonal((1, 2, 0.3)).to_4x4() note element 3,3 in scale matrix is 1, not 0, could create complications Nov 8 '19 at 8:19