# How to get the updated rotation of an object during soft body physics simulation?

I am trying to get the updated rotation of an object during simulation in Blender 2.92. However, I am not able to get what I want. I appreciate if someone can help me with this.

As you may know, you will always get the original object's location and rotation if you do bpy.context.object.rotation_euler or bpy.context.object.location for each frame. However, you can get the object location if you make a vertex group from the original object vertices and add an empty object to it. This has allowed me to track the object and get its updated location. However, this trick does not seem to work for getting the updated rotation of the object for each frame. Even the empty's rotation does not match with the original object rotation before I start the simulation. For each frame of the simulation also I get more or less completely random rotation vectors from the empty if I print its rotation.

Does anyone have a solution for this?

vertices_to_add = []
for vertex in bpy.data.objects['Cube'].vertices:

# add vertices to vertex group
group = self.obj.vertex_groups.new(name='Group')

# create an empty
bpy.context.object.rotation_euler =  bpy.data.objects['Cube'].rotation_euler

bpy.context.object.constraints["Copy Location"].target = self.obj
bpy.context.object.constraints["Copy Location"].subtarget = "Group"

bpy.context.object.constraints["Copy Rotation"].target = self.obj
bpy.context.object.constraints["Copy Rotation"].subtarget = "Group"

# Later on I do the followings to print the current rotation of the Empty
for frame in range(1, num_frames+1):
bpy.context.scene.frame_set(frame)
print(bpy.data.objects['Empty'].rotation_euler) # this always prints the original object rotation
print(bpy.data.objects["Empty"].matrix_world.to_euler('XYZ')) # This gives me completely random rotation vectors

• Assuming Blender 2.8/2.9? Apr 7 at 3:31
• @RonJensen Yes, 2.92
– Amir
Apr 7 at 3:37
• Can you clarify (maybe visualize on another object) why the rotation values appear random. Could it be that the copy rotation constraint clamps its values to range (in degrees) of (-180, 180) ? Apr 7 at 5:22
• @batFINGER The Empty's rotation is not as random as I thought as the Z rotation is mostly around 0 but the X and Y rotation values seem pretty random (-180, 180)
– Amir
Apr 7 at 10:10
• @batFINGER Apparently the solution I posted does not work for soft bodies but works well for rigid bodies. I didn't think t would be necessary for me to make it explicit that I am doing soft body simulation.
– Amir
Apr 7 at 15:33

Issue with all vert coords in vg summing to zero.

Made a quick demo to have a squiz,

Using 2.91 ran into this issue

Default Cube set up to drop on plane using physics. An all vertex group "Group" is added, and two constraints, as demonstrated with code above.

All constraints use default values unless otherwise stated.

Obvservations:

For copy rotation constraint.

Using no subtarget --> Empty same rotation as cube.

When using all vert vg "Group" as a subtarget --> Resulted in Identity (zero) rotation.

Using a group with only 3 vertices --> Empty rotates, but is aligned to normal of 3 verts plane.

Editing the cube by moving one corner such that it is no longer symmetrical also sees rotation when all verts used as subtarget.

Similarly if both constraints are replaced with one copy transform constraint, in which case "Group" makes the empty disappear (scale to zero). Despite there being only unit scale on all objects involved

Didn't try but the other similar constraint would be parent to.

Conclusion.

Either don't use a subtarget, or make sure the sum of all vert coords in subtarget group do not sum to zero, for constraints that involve rotation.

Really only need the subtarget if also deforming the mesh.

Perhaps someone can elaborate whether this behaviour re using all verts vg as a subgroup not rotating is by design, or a bug of sorts, when caused by the sum of all cube verts being zero a zero vector...

With one of the working options selected, used script below to add an empty at each tenth frame with same matrix world as constrained empty.

import bpy
scene = bpy.context.scene
fs, fe = scene.frame_start, scene.frame_end
tg = bpy.data.objects["Empty"]

for frame in range(fs, fe):
scene.frame_set(frame)
print(frame, tg.matrix_world.to_euler('XYZ')) # This gives me completely random rotation vectors
if not frame % 10:
mt = bpy.context.object
mt.matrix_world = tg.matrix_world
mt.name = f"frame_{frame}"
mt.show_name = True


With the physics baked, ran it and the added empties align with the constrained empty at their respective frame.

PS can make an all vert group with

group.add(range(len(mesh.vertices)), 1.0, "ADD")

• Thank you so much for taking the time to write a fully-fledged solution. Do you think this should also work for soft bodies?
– Amir
Apr 7 at 15:35
• Would help if you added a small test blend with set-up pasteall.org/blend Apr 7 at 15:58