[I reformulate the question to something more concrete]

I have 2 different .bvh files with 2 poses. From one pose I want to find the transform to get the second pose. If I compute the rotation to align one bone to the other bone (see Figure 1)

enter image description here

I get that I should rotate Z axis 45º, and if I put this rotation in Pose mode I can align the 2 bones (see Figure 2)

enter image description here

However, if I write 45º in the .bvh file the alignment goes completely wrong (see Figure 3)

enter image description here

I think probably rotation should be expressed in armature coordinates but I can't find how to do that in the .bvh files.

  • $\begingroup$ The bvh importer exporter bundled with blender, both imports to and exports from joint empties. Suggest posting code if you want help with what you have. $\endgroup$
    – batFINGER
    Mar 8 '18 at 12:24
  • $\begingroup$ I can share a couple of bvh files I'm trying as example. To compute rotation angles I use Matlab. What I want to do is to compute a bvh file that contains all skeleton positions. bvh1 bvh2 . In the second frame, I should find the rotations to get to the bvh target. $\endgroup$ Mar 8 '18 at 15:17

Retarget animation

of one rig to another which differs only by rest pose

Given your two example bvh files produced rigs, toy_example_source and toy_example_target It looks like you want to do same as this qanda

Since your two rigs only differ by rest pose can snap target to source using a global copy transforms constraint. The new transforms of the snapped bone can be grabbed from the pose bones matrix. The local coordinates of the new transform using Object.convert_space(...)

Edit the name of source and target rigs to suit.

import bpy
from bpy import context

remove_constraints = True
scene = context.scene
rig1 = scene.objects["toy_example_source"]

rig2 = scene.objects["toy_example_target"]
if not rig2.animation_data:
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
    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:
    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)

        # 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:
            ct.influence = 0
  • $\begingroup$ Somehow this puts me in the way of solving my problem, but still is not enough for what I need to do. The approach I'm following is, 1) convert all my 3d points from skeleton to .bvh file with 1 frame, 2) align 1.bvh, with all other converted .bvh, 3) export .bvh with blender. However, this .bvh I want to use with MakeHuman, and blender .bvh exports 6 channels which makes it not compatible with MH. My problem still is how I convert these rotations of bones to world coordinates. convert_space(..) give me always same values no matter what I put in to_space $\endgroup$ Mar 13 '18 at 16:43

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.