# How to apply all transformations to an object at low level?

I am new to Blender (and to some extent to python). I have pieced together this function that rotates and scales an Object at low level by modifying the matrices:

def rotate_scale_object(inObj, angle, axis, scaling):
orig_loc, orig_rot, orig_scale = inObj.matrix_world.decompose()
orig_loc_mat   = Matrix.Translation(orig_loc)
orig_rot_mat   = orig_rot.to_matrix().to_4x4()
orig_scale_mat = (Matrix.Scale(scaling,4,(1,0,0)) @ Matrix.Scale(scaling,4,(0,1,0)) @ Matrix.Scale(scaling,4,(0,0,1)))
# assemble the new matrix
inObj.matrix_world = orig_loc_mat @ rot_mat @ orig_rot_mat @ orig_scale_mat
#update_matrices(inObj)
return inObj


I call it in my script as follow:

obj = bpy.context.active_object
obj = scale_rotate_smooth_color(obj, angle = -90, axis = "X", scaling = 0.01)


It works very well: the object is rotated & scaled as expected. Yet, I am missing a way to "apply" these transformations to the object, as one would do by pressing Ctrl + A and select Apply all transformations.

Is there a way to do this "low level", without resorting to bpy.ops.object.transform_apply(location=True, rotation=True, scale=True)?

• Thanks for the suggestion. I will definitively implement it this way. Dec 1 '19 at 16:00
• obj.data.transform(obj.matrix_world) obj.data.update() matrix = Matrix.Identity(4) obj.matrix_world = matrix Jun 14 at 14:20

Mesh transform

Does a child object inherit the matrix from the parent?

Applying the transform.

• Set the basis matrix value to identity for any or all of location, rotation scale.

• Transform the mesh and or child objects to reflect the change

For all transforms.

import bpy

context = bpy.context

ob = context.object
mb = ob.matrix_basis
if hasattr(ob.data, "transform"):
ob.data.transform(mb)
for c in ob.children:
c.matrix_local = mb @ c.matrix_local

ob.matrix_basis.identity()


To apply only rotation.

Similarly will show the process of only applying rotation. Transform the data and children such that the rotation part of matrix basis is identity.

Method below uses the Matrix.decompose to reduce the transform into its three components. The rotation is defined as a quaternion. Another way to decompose is discussed in

How to Decompose and Compose the local transform matrix

import bpy
context = bpy.context
from mathutils import Matrix

ob = context.object
mw = ob.matrix_world
mb = ob.matrix_basis

loc, rot, scale = mb.decompose()

# rotation
T = Matrix.Translation(loc)
R = rot.to_matrix().to_4x4()
S = Matrix.Diagonal(scale).to_4x4()

if hasattr(ob.data, "transform"):
ob.data.transform(R)

for c in ob.children:
c.matrix_local = R @ c.matrix_local

ob.matrix_basis = T @ S


For rotation and scale

...:
ob.data.transform(R @ S)

for c in ob.children:
c.matrix_local = (R @ S) @ c.matrix_local

ob.matrix_basis = T


ie set the basis to make identity of applied property, transform mesh and children by the jconverse. eg applying all is transforming by T @ R @ S and setting to I @ I @ I transform & scale T @ I @ S --> I @ R @ S (where I is identity matrix)

Method for all or any

import bpy
from mathutils import Matrix

def apply_transfrom(ob, use_location=False, use_rotation=False, use_scale=False):
mb = ob.matrix_basis
I = Matrix()
loc, rot, scale = mb.decompose()

# rotation
T = Matrix.Translation(loc)
#R = rot.to_matrix().to_4x4()
R = mb.to_3x3().normalized().to_4x4()
S = Matrix.Diagonal(scale).to_4x4()

transform = [I, I, I]
basis = [T, R, S]

def swap(i):
transform[i], basis[i] = basis[i], transform[i]

if use_location:
swap(0)
if use_rotation:
swap(1)
if use_scale:
swap(2)

M = transform[0] @ transform[1] @ transform[2]
if hasattr(ob.data, "transform"):
ob.data.transform(M)
for c in ob.children:
c.matrix_local = M @ c.matrix_local

ob.matrix_basis = basis[0] @ basis[1] @ basis[2]

# test call
apply_transfrom(bpy.context.object, use_rotation=True)


Recent answer using Mesh.transform Problem with rotating objects by script

• Exactly what I was missing. Thanks a lot. Dec 1 '19 at 16:07
• cheers, prob should have used mult by inverse instead of setting to identity. eg to apply rotation make a rotation matrix, R apply it to mesh me.transform(R), then mult matrix_world by R.inverted() Dec 1 '19 at 16:15
• This didn't work for me, which is why I asked another question. But it got closed. I wanted to apply rotations to my meshes after adding rotation eulers. In the end I rewrote my code to perform the rotation directly on the meshes instead of using bpy.ops. Jun 30 at 11:05
• Apologies, fixed and fixed. Probably relates to comment above also. Edited this one re-opened other. Jun 30 at 13:24
• Nice one! Thanks for the edits! Jun 30 at 14:28