1
$\begingroup$

Hey there Blender Community,

I'm trying to figure out the optimal way to use Blender's physics engine to perform simulations and access the information from each frame of the simulation for various other purposes. The idea, ultimately, is to be able to loop through the frames of the animation once the simulation is complete and get information about an object's location, for example, after a rigid body collision.

I was able to successfully accomplish something like this with the following method:

def analyze_scene():
    scene = bpy.data.scenes['Scene'].frame_end
    object = bpy.data.objects[object]
    frameInfo = []
    for frame in range(1, scene.frame_end):
        scene.frame_current = frame
        bpy.ops.ptcache.bake_all(bake=False)
        frameInfo.append({"name": object.name, "frame": frame,
            "translation": object.matrix_world.translation})

    return frameInfo

(Note: There may be an error in this code, but it's just an outline of what I'm doing).

The issue with this is having to call "update all to frame" (bake_all) with every frame. Is there a better way of doing this that isn't so computationally expensive? I've experimented with Scene.update() to no avail.

My thanks in advance for any assistance.

$\endgroup$
1
  • $\begingroup$ Can you please confirm how exactly you are using this solution and what Blender version it is for? I am guessing this is for Blender 2.79b? I am hoping I could record the live viewport playback of rigid body physics to keyframes. This would allow me to mouse grab and throw objects around, and hit other objects, recording that in real time with physics running. Very different from an "animated" rigid body object which is NOT affected by gravity. Thanks in advance! $\endgroup$ Commented Dec 25, 2023 at 5:33

1 Answer 1

4
$\begingroup$

You don't need to call bpy.ops.ptcache.bake_all() for every frame, as it runs the simulation for every frame.

Just move the call to bake_all() above your loop, just after setting frame_current to frame_end :

def analyze_scene():
    scene = bpy.data.scenes['Scene']
    object = bpy.data.objects[object]
    frameInfo = []
    scene.frame_current = scene.frame_end
    bpy.ops.ptcache.bake_all(bake=False)

    for frame in range(1, scene.frame_end):
        scene.frame_current = frame
        frameInfo.append({"name": object.name, "frame": frame,
            "translation": object.matrix_world.translation})

    return frameInfo

This should run many times faster, with the code you've given, you were running a simulation of all frames for each frame between 1 and frame_end.

EDIT : If you just want to iterate through the frames, you don't need to bake anything, just change the current frame with scene.frame_set(frame) instead of scene.frame_current = frame. As long as you do this with an incrementing frame, Blender will compute the keypoints for each frame. For example :

def analyze_scene():
    scene = bpy.data.scenes['Scene']
    object = bpy.data.objects[object]
    frameInfo = []

    for frame in range(scene.frame_start,
                       scene.frame_end,
                       scene.frame_step):
        scene.frame_set(frame)
        frameInfo.append({
            "name": object.name, "frame": frame,
            "translation": object.matrix_world.translation
        })

    return frameInfo

NOTE : You also had written scene = bpy.data.scenes['Scene'].frame_end in your code, I corrected it with scene = bpy.data.scenes['Scene'], I guess that is what you meant.

$\endgroup$
4
  • $\begingroup$ Thanks for the response, @pistache! I'll give this a try and let you know the results. $\endgroup$ Commented May 30, 2018 at 7:22
  • $\begingroup$ @ColinConwell : could you tell me if there's a problem with this solution ? or accept it ? (i'm just asking because my low reputation prohibits me from commenting anywhere on this site) $\endgroup$
    – pistache
    Commented Jun 20, 2018 at 16:43
  • 1
    $\begingroup$ Apologies for the delay. Your solution does work! Thanks again. $\endgroup$ Commented Jun 21, 2018 at 17:49
  • $\begingroup$ Can you please confirm how exactly you are using this solution and what Blender version it is for? I am guessing this is for Blender 2.79b? I am hoping I could record the live viewport playback of rigid body physics to keyframes. This would allow me to mouse grab and throw objects around, and hit other objects, recording that in real time with physics running. Very different from an "animated" rigid body object which is NOT affected by gravity. Thanks in advance! $\endgroup$ Commented Dec 25, 2023 at 5:34

You must log in to answer this question.

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