I'm an apprentice on blender and get in trouble with topic above. I would like to apply an animation data from Rig-A to Rig-B, through 3rd party exporter.
From Rig-A: 'arm.L'(-155.44)->'forearm.L'(-98.53)->'wrist.L'(-94.33)
To Rig-B: 'arm.L'(-55.81)->'forearm.L'(-125.86)->'wrist.L'(-56.3)

But there are differnce in roll settings between these two Rigs. Then I tried to correct the animation data with bpy like below, in advance of export.
As you see, this code does not work well, because it does not count the roll transmittion processing, which I can not get through. Your help is greatly appreciated.

import bpy
import math
import mathutils

fix_rot_bones = ['arm.R','arm.L','forearm.R','forearm.L','wrist.R','wrist.L']

obj = bpy.context.active_object
arm = obj.pose
action = anim.action
initial_frame = 30

def overwrite(bone, frame_, path_):
    bone.keyframe_insert(data_path = path_ ,frame = frame_)

def fix_rot(name, frame):
    if name in fix_rot_bones:
        if(name == 'arm.R'):
            mat_rot_arm = mathutils.Matrix.Rotation(math.radians(-100), 4, 'X')
        if(name == 'arm.L'):
            mat_rot_arm = mathutils.Matrix.Rotation(math.radians(-100), 4, 'X')
        # Same processing on the rest of bones
        quat_rot = mat_rot_arm.to_quaternion()
        arm.bones[name].rotation_quaternion *= quat_rot
        overwrite(arm.bones[name], frame, 'rotation_quaternion')

# find key points and hit fix function on each key points
def detector(fix_bones, fix_):
    for group in action.groups :
        if (group.name in fix_bones) :
            for channel in group.channels :
                if (channel.array_index == 3) :
                    for point in channel.keyframe_points :
                        if (fix_ == 'fix_rot'):
                            fix_rot(group.name, point.co[0])

detector(fix_rot_bones, 'fix_rot')

For the ordinary case you might convert the pose matrix like this

import bpy

arm_src = bpy.data.objects['Armature_Source']
arm_tgt = bpy.data.objects['Armature_Target']

def mat_offset(pose_bone):
    bone = pose_bone.bone
    mat = bone.matrix.to_4x4()
    mat.translation = bone.head
    if pose_bone.parent:
        mat.translation.y += bone.parent.length
    return mat

def adjust_pose_mat(source):
    target = arm_tgt.pose.bones[source.name]

    mat = (mat_offset(target).inverted() * 
           mat_offset(source) * 

    target.matrix_basis = mat

for pb in arm_src.pose.bones:

Example Blend:

| improve this answer | |
  • $\begingroup$ Thank you so much. I would try again with your code from now and make a report of the result later. Thank you, again. $\endgroup$ – Yayoi Sakura Sep 27 '16 at 12:31

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.