19
$\begingroup$

I am looking for help on how to export armatures and their animations in a custom export script.

I wish to have an animation format similar to BVH, i.e. a bunch of [Xposition Yposition Zposition] Xrotation Yrotation Zrotation for each bone for each keyframe.

Given the model (which exports fine using the bvh exporter), how does one get the keyframe data? A long time searching the object tree of bpy has left me somewhat baffled.

$\endgroup$
2
  • $\begingroup$ Welcome to the site :) Tutorial requests are considered off topic here. If you are looking for a tutorial, then youtube or Blender Artists would be a better place to look. If you have a specific question like "How to access keyframe data with python", then this is the place. $\endgroup$
    – gandalf3
    Commented Apr 7, 2014 at 20:26
  • $\begingroup$ Noted. Any help would be appreciated (not necessarily full tutorials). My question is basically what you stated "How to access keyframe data with python", as I can do the rest. $\endgroup$
    – rspencer
    Commented Apr 7, 2014 at 20:29

3 Answers 3

21
$\begingroup$

A common way to get the animation data is to loop over the scene's frame range and read the matrices for every single frame. This is okay most of the time, and way easier to do than reading the F-Curve data directly (which won't include F-Curve modifiers and Drivers AFAIK).

Assume the Armature object is currently active:

import bpy

sce = bpy.context.scene
ob = bpy.context.object

for f in range(sce.frame_start, sce.frame_end+1):
    sce.frame_set(f)
    print("Frame %i" % f)

    for pbone in ob.pose.bones:
        print(pbone.name, pbone.matrix) # bone in object space

bpy.types.PoseBone.matrix

You may use the utility function convert_space to avoid fancy matrix math.

$\endgroup$
0
23
$\begingroup$

To actually get the keyframe data (and not the bones' transform matrix as in CodemanX answer), you need to get the desired action, its fcurves, and finally all the keypoints.

The fcurves are named with bone.location .quaternion and .scale for all channels (x,y,z) or (w,x,y,z) and are further distinguished via their index.

action = bpy.data.actions["action_id"]
for fcu in action.fcurves:
    print(fcu.data_path + " channel " + str(fcu.array_index))
    for keyframe in fcu.keyframe_points:
        print(keyframe.co) #coordinates x,y

Check the API documentation on the Keyframes structure to see what you can do with it:

$\endgroup$
2
  • 1
    $\begingroup$ I think this answer is better. It actually answers the question in the title. However, could you clarify: given an object bpy.data.objects["Cube"], how do I get the action(s) of that object? $\endgroup$
    – Ludwik
    Commented Jul 16, 2015 at 15:33
  • $\begingroup$ Thanks for the code, brita_! There are two syntactic errors, maybe you would consider editing them? A missing str() and a missing colon: for fcu in action.fcurves: print(fcu.data_path + " channel " + str(fcu.array_index)) for keyframe in fcu.keyframe_points: print(keyframe.co) $\endgroup$ Commented Aug 1, 2015 at 6:06
5
$\begingroup$

To get all the keyframes of actions of an object that have been "pushed down" or stored in NLA.

tracks = bpy.data.objects['Cube'].animation_data.nla_tracks
for track in tracks:
    for strip in track.strips:
        print(strip.action)
        action=strip.action

        for fcu in action.fcurves:
            print(fcu.data_path + " channel " + str(fcu.array_index))
            for keyframe in fcu.keyframe_points:
                print(keyframe.co) #coordinates x,y
$\endgroup$
1
  • $\begingroup$ iterating over nla_tracks freezes my blender session. Any Idea why? Blender 3.0 $\endgroup$
    – MaKaNu
    Commented Jan 9, 2022 at 12:48

You must log in to answer this question.

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