10
$\begingroup$

I'm trying to track the (x,y,z) location of an animated object. For a small test, I translated the default cube ('Cube') along the x axis and baked keyframes. The animation plays fine.

I adapted the suggestion for this question to try and print the location at each keyframe.

import bpy
cube=bpy.data.objects['Cube']
for f in cube.animation_data.action.fcurves:
    for k in f.keyframe_points:
        pos=cube.location
        print(pos)

Run from the shell, the output is

<Vector (0.0000, 0.0000, 0.0000)>
<Vector (0.0000, 0.0000, 0.0000)>
<Vector (0.0000, 0.0000, 0.0000)>
...
<Vector (0.0000, 0.0000, 0.0000)>

If I go to the last keyframe and execute cube.location, it correctly returns

Vector((6.924227714538574, 0.0, 0.0)) 

How can I get the location at each keyframe?

$\endgroup$
  • $\begingroup$ Would using bpy.context.scene.frame_set(frame) and reading cube.location be a bad idea? $\endgroup$ – kilbee Dec 17 '13 at 23:18
  • $\begingroup$ And then iterating through the frames? It doesn't seem like a bad idea. My sum total Blender experience is currently measured in hours, so anything that seems like it might work sounds good to me. $\endgroup$ – kmm Dec 17 '13 at 23:31
  • 2
    $\begingroup$ Yes, exactly. cube.location reads the location from current context frame, thats why you are getting the results from the frame you run the script from. So to get the right results with cube.location you need to change the context with the bpy.context.scene.frame_set(frame). $\endgroup$ – kilbee Dec 17 '13 at 23:45
9
$\begingroup$

The reason your script was returning 0, 0, 0 is because you were printing the location of the object on the current frame.

Basically your code says:

Print the location of the cube object the same number of times as there are number of keyframes.

So as mentioned by kilbee you need to set the scene frame to the frame that the keyframe is on in order to read the location of the object on that frame.

By combining your code with kilbee's:

import bpy

ob = bpy.context.object

for f in ob.animation_data.action.fcurves:
    for k in f.keyframe_points:
        fr = k.co[0]
        bpy.context.scene.frame_set(fr)
        pos=ob.location
        print(pos)

This way you only check frames with keyframes, as opposed to checking every frame.

$\endgroup$
6
$\begingroup$

Anyway to get the data you want (for frames for example 1-40):

for frame in range(1,40):
    bpy.context.scene.frame_set(frame)
    print(cube.location)

Upside is you dont have to bake the animation to get the data for each frame, downside is that with complex scenes it might be very time consuming to execute the script.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.