Thursday, 7 July 2011

Copying Poses with Constraints in Blender

Often I find that I need to use the copy and paste pose buttons to get a smooth transition when animating a ChildOf constraint.  Blender's built in copy and paste pose buttons ignore constraints so I coded my own.  Basically select the bones you want, run the 'copy pose to buffer' script, then change frame to after your constraint influence has been changed and run the 'paste pose from buffer' script.  This way you can get nice smooth transitions across those constraint changes...



'Copy Pose to Buffer'



import bpy
from mathutils import Matrix


def getmat(bone, active, context, ignoreparent):
    '''Helper function for visual transform copy,
       gets the active transform in bone space
    '''
    data_bone = context.active_object.data.bones[bone.name]
    #all matrices are in armature space unless commented otherwise
    otherloc = active.matrix  # final 4x4 mat of target, location.
    bonemat_local = Matrix(data_bone.matrix_local)  # self rest matrix
    if data_bone.parent:
        parentposemat = Matrix(
           context.active_object.pose.bones[data_bone.parent.name].matrix)
        parentbonemat = Matrix(data_bone.parent.matrix_local)
    else:
        parentposemat = bonemat_local.copy()
        parentbonemat = bonemat_local.copy()


        parentposemat.identity()
        parentbonemat.identity()


    if parentbonemat == parentposemat or ignoreparent:
        newmat = bonemat_local.inverted() * otherloc
    else:
        bonemat = parentbonemat.inverted() * bonemat_local


        newmat = bonemat.inverted() * parentposemat.inverted() * otherloc
    return newmat
    


for each_bone in bpy.context.selected_pose_bones:
    
    ws_loc_matrix=getmat(each_bone, each_bone, bpy.context, False)
    ws_rot_matrix=getmat(each_bone, each_bone,bpy.context,
        not bpy.context.active_object.data.bones[each_bone.name].use_inherit_rotation)
    ws_sc_matrix=getmat(each_bone, each_bone,bpy.context,
        not bpy.context.active_object.data.bones[each_bone.name].use_inherit_scale)
    each_bone['ws_loc_matrix']=ws_loc_matrix
    each_bone['ws_rot_matrix']=ws_rot_matrix
    each_bone['ws_sc_matrix']=ws_sc_matrix




'Paste Pose from Buffer'



import bpy
import mathutils


def rotcopy(item, mat):
    '''copy rotation to item from matrix mat depending on item.rotation_mode'''
    if item.rotation_mode == 'QUATERNION':
        item.rotation_quaternion = mat.to_3x3().to_quaternion()
    elif item.rotation_mode == 'AXIS_ANGLE':
        quat = mat.to_3x3().to_quaternion()
        item.rotation_axis_angle = mathutils.Vector([quat.axis[0],
           quat.axis[1], quat.axis[2], quat.angle])
    else:
        item.rotation_euler = mat.to_3x3().to_euler(item.rotation_mode)


for each_bone in bpy.context.selected_pose_bones:
    ws_loc_matrix=mathutils.Matrix(each_bone['ws_loc_matrix'])
    ws_rot_matrix=mathutils.Matrix(each_bone['ws_rot_matrix'])
    ws_sc_matrix=mathutils.Matrix(each_bone['ws_sc_matrix'])
    each_bone.location=ws_loc_matrix.to_translation()
    each_bone.scale=ws_sc_matrix.to_scale()
    rotcopy(each_bone,ws_rot_matrix)
    
    
    

No comments:

Post a Comment