Search code examples
pythonmatrixblender

Force matrix_world to be recalculated in Blender


I'm designing an add-on for blender, that changes the location of certain vertices of an object. Every object in blender has a matrix_world atribute, that holds a matrix that transposes the coordinates of the vertices from the object to the world frame.

print(object.matrix_world) # unit matrix (as expected)
object.location += mathutils.Vector((5,0,0))
object.rotation_quaternion *= mathutils.Quaternion((0.0, 1.0, 0.0), math.radians(45))
print(object.matrix_world) # Also unit matrix!?!

The above snippet shows that after the translation, you still have the same matrix_world. How can I force blender to recalculate the matrix_world?


Solution

  • You should call Scene.update after changing those values, otherwise Blender won't recalculate matrix_world until it's needed [somewhere else]. The reason, according to the "Gotcha's" section in the API docs, is that this re-calc is an expensive operation, so it's not done right away:

    Sometimes you want to modify values from python and immediately access the updated values, eg:

    Once changing the objects bpy.types.Object.location you may want to access its transformation right after from bpy.types.Object.matrix_world, but this doesn’t work as you might expect.

    Consider the calculations that might go into working out the objects final transformation, this includes:

    • animation function curves.
    • drivers and their pythons expressions.
    • constraints
    • parent objects and all of their f-curves, constraints etc.

    To avoid expensive recalculations every time a property is modified, Blender defers making the actual calculations until they are needed.

    However, while the script runs you may want to access the updated values.

    This can be done by calling bpy.types.Scene.update after modifying values which recalculates all data that is tagged to be updated.