1
$\begingroup$

I have some motion capture data in an FBX file. Using Autodesk MotionBuilder I can export it to BVH. It seems to work well, except for the rest position, which is very strange:

enter image description here enter image description here

The screenshots above were taken in Blender 2.78, but the rest position is the same when opening the file in bvhacker.

The animation plays out just fine, but without the rest position it is nearly impossible to rig a character.

In Blender, I tried Pose > Apply Pose as Rest Pose, but that ends up distorting the entire animation, so it is useless.

Is there a way to redefine the rest position to a standard T-pose in a BVH file while still preserving the animation?

$\endgroup$
2
$\begingroup$

I spent two days trying to find the solution and ended up finding it an hour after posting the question here.

The solution is to run a script provided by batFINGER in this thread: Create pose from existing armature

I'll copy the script here just keep things in one place, but I don't claim to have written it. All credits to batFINGER.

import bpy
from bpy import context

remove_constraints = True
scene = context.scene
scene.frame_set(1) # TPOSE frame
rig1 = context.object
# copy the rig and armature
rig2 = rig1.copy()
rig2.data = rig2.data.copy()
scene.objects.link(rig2)
scene.objects.active = rig2
bpy.ops.object.mode_set(mode='POSE')
# apply the pose in frame 1
bpy.ops.pose.armature_apply()
if not rig2.animation_data:
    rig2.animation_data_create()
# remove animation from dupe
rig2.animation_data.action = None
# add copy transform constraint to each bone
for pb in rig2.pose.bones:
    ct = pb.constraints.get(pb.name)    
    if ct is not None:
        ct.influence = 1
        continue
    ct = pb.constraints.new('COPY_TRANSFORMS')
    ct.name = pb.name
    ct.target = rig1
    ct.subtarget = pb.name

action = rig1.animation_data.action
f = action.frame_range.x
# add a keyframe to each frame of new rig
while f < action.frame_range.y:
    scene.frame_set(f)
    for pb in rig2.pose.bones:
        #pb2 = rig1.pose.bones.get(pb.name)
        m = rig2.convert_space(pb, pb.matrix, to_space='LOCAL')
        if pb.rotation_mode == 'QUATERNION':
            pb.rotation_quaternion = m.to_quaternion()
            pb.keyframe_insert("rotation_quaternion", frame=f)
        else:

        # add rot mode checking 
            pb.rotation_euler = m.to_euler(pb.rotation_mode)
            pb.keyframe_insert("rotation_euler", frame=f)
        pb.location = m.to_translation()

        pb.keyframe_insert("location", frame=f)
    f += 1

# set constraints to zero or remove entirely.
for pb in rig2.pose.bones:
    ct = pb.constraints.get(pb.name)    
    if ct is not None:
        if remove_constraints:
            pb.constraints.remove(ct)
        else:
            ct.influence = 0
$\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.