4
$\begingroup$

I am trying to get the frame-by-frame location of the softbody physics simulation (collision of softbody cube with a plane).

I am incrementing the frame of the simulation using set_frame

However every time I get the location, whether it be from bpy.data.objects["Cube"].matrix_world.translation or bpy.data.objects["Cube"].location it gives me the initial location of the cube for every frame. I can see in blender that the cube has moved though.

I also used bpy.context.view_layer.update() before getting the location of the cube and its still giving me the same results. This is for blender 2.91.

here is the loop I am setting frames and attempting to get location from:

for frame in range(1, 200):
    file_name = "frame_" + str(frame) + ".obj"
    bpy.context.scene.frame_set(frame)
    bpy.context.view_layer.update()
    print(bpy.data.objects["Cube"].matrix_world.translation)

Thanks.

Previous posts I have tried the solutions for include:

Location of an object at a specific frame

How can I get the location of an object at each keyframe?

Looping Through Frames of Physics Simulation and Getting Object Info with Blender Python

https://stackoverflow.com/questions/57691141/location-of-objects-not-changing-in-any-frame-for-physics-simulation

I suspect this is the reason that the object's location constantly returns as the first frame:

The point I circled in red is the initial location of the object I believe, but the screepcap is the final frame in the scene.

enter image description here

$\endgroup$
1

1 Answer 1

1
$\begingroup$

A softbody sim isn't going to update the origin point based on the changing position of the mesh - the object origin "stays" at its original position, even if the sim itself does not (rigid bodies are different since the object itself doesn't deform, so the whole object moves together). I tried running a softbody locally and it had the same issue.

If you need to keep track of a central location, you can take the average of all the points (in world space, of course), using the current depsgraph:

import bpy
import bmesh

context = bpy.context
obj = context.scene.objects['Cube']
world_matrix = obj.matrix_world

for frame in range(1, 50):
    file_name = "frame_" + str(frame) + ".obj"
    context.scene.frame_set(frame)
    context.view_layer.update()
    depsgraph = context.evaluated_depsgraph_get()
    bm = bmesh.new()
    bm.from_object(obj, depsgraph)
    x, y, z = 0.0, 0.0, 0.0
    for v in bm.verts:
        v_x, v_y, v_z = world_matrix @ v.co
        x += v_x
        y += v_y
        z += v_z
        
#    print(frame, [world_matrix @ v.co for v in bm.verts])
    num_verts = len(bm.verts)
    x /= num_verts
    y /= num_verts
    z /= num_verts
    print(frame, (x, y, z))
    bm.free()

Cheers :)

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .