Here is a script I've been working on to do this for bvh files. Basically it adds a copy transform constraint to each pose bone, then using Object.convert_space
, retargets animation to another rig with same bones.
It's good practice to keep scale on armatures to unity, to avoid issues. Applying scale to both armatures. Ctrl-A scale will make the scale (1, 1, 1). I applied rotation as well and put the armature objects at location (0, 0, 0) before running script..
import bpy
from bpy import context
remove_constraints = False
scene = context.scene
rig1 = scene.objects["hands_reference_skeleton"]
rig2 = scene.objects["hands_reference_skeleton.001"]
if not rig2.animation_data:
rig2.animation_data_create()
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(int(f))
context.view_layer.update()
r2 = rig2.evaluated_get(context.evaluated_depsgraph_get())
for pb in r2.pose.bones:
#pb2 = rig1.pose.bones.get(pb.name)
m = rig2.convert_space(
pose_bone=pb,
matrix=pb.matrix,
from_space='POSE',
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