Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import bpy
- from math import degrees
- from mathutils import Quaternion
- C= bpy.context
- D= bpy.data
- def clean_empties():
- for ob in D.scenes['Scene'].objects:
- if ob.type == "EMPTY":
- D.scenes['Scene'].objects.unlink(ob)
- class Armature_converter:
- """Translates the animation of one armature to another with different zero pose"""
- bpy.types.Bone.diff_quat = bpy.props.FloatVectorProperty(
- "Difference rotation",
- subtype= "QUATERNION",
- size = 4,
- default=(1,0,0,0))
- bpy.types.Bone.diff_vec = bpy.props.FloatVectorProperty(
- "Difference position",
- subtype= "TRANSLATION",
- size = 3,
- default=(0,0,0))
- def __init__(self, source, target):
- self.source = D.objects[source]
- self.target = D.objects[target]
- self.root_translation = True
- self.inherit_rotations = True
- self.range = {"min" : 0, "max" : float("inf")}
- self.set_poseposition("REST")
- C.scene.objects.active = self.target
- bpy.ops.object.mode_set(mode = 'POSE')
- print("Converting armature {} to {}\n".format(source, target))
- def set_poseposition(self, mode = "POSE"):
- self.source.data.pose_position = mode
- self.target.data.pose_position = mode
- def get_basebone(self, where="source"):
- #ATTENTION!! source return data Bone, target returns PoseBone!
- if where == "source":
- basebone = [b for b in self.source.data.bones if b.parent is None]
- else:
- basebone = [b for b in self.target.pose.bones if b.parent is None]
- if len(basebone) != 1:
- raise Exception("The base armature has to have exactly one base bone")
- else:
- basebone = basebone[0]
- return basebone
- def reset_pose(self):
- self.get_basebone("target").rotation_quaternion.identity()
- self.walk_bones(self.get_basebone("target"), lambda b: b.rotation_quaternion.identity())
- def get_pose_diff(self):
- if not self.inherit_rotations:
- for b in self.target.data.bones:
- b.use_inherit_rotation = False
- return
- for b in self.target.data.bones:
- b.use_inherit_rotation = True
- self.reset_pose()
- self.walk_bones(self.get_basebone(), self.get_bone_diff)
- def get_bone_diff(self, bone):
- rot_bone = bone.matrix.to_quaternion()
- other = self.target.data.bones[bone.name]
- rot_other = other.matrix.to_quaternion()
- bone.diff_quat = rot_bone.rotation_difference( rot_other )
- def set_bone_from_diff(self, bone):
- t_bone = self.target.pose \
- .bones[bone.name]
- C.scene.objects.active = self.target
- bpy.ops.object.mode_set(mode = 'POSE')
- ###
- if self.root_translation:
- v = self.source.pose.bones[bone.name].location
- else:
- v = (0,0,0)
- self.target.pose \
- .bones[bone.name] \
- .location = v
- ###
- if not self.inherit_rotations:
- self.set_poseposition()
- # bpy.ops.object.mode_set(mode = 'OBJECT')
- # e = bpy.ops.object.empty_add(type='ARROWS', radius=0.3, view_align=False,
- # location= self.source.pose.bones[bone.name].tail, rotation= self.source.pose.bones[bone.name].matrix.to_euler(),
- # layers=(True,) + (False,) * 19)
- m = self.source.pose.bones[bone.name].matrix.copy()
- m.resize_4x4()
- t_bone.matrix = m
- # bpy.ops.object.select_all(action = 'DESELECT')
- # self.target.select = True
- return
- ###
- t_bone.rotation_quaternion *= bone.diff_quat.conjugated() \
- * self.source.pose.bones[bone.name].rotation_quaternion
- # print("{:16} | {} | {}".format(bone.name, bone.diff_quat, bone.diff_quat))
- def set_pose_from_diff(self):
- self.reset_pose()
- self.set_bone_from_diff(self.get_basebone())
- self.walk_bones(self.get_basebone(), self.set_bone_from_diff)
- @staticmethod
- def walk_bones(bone, handler):
- for ch in bone.children:
- handler(ch)
- Armature_converter.walk_bones(ch, handler)
- def convert_animation(self):
- name = self.get_basebone("target").name
- keyframes = self.source.animation_data.action.fcurves[0].keyframe_points
- for i,keypoint in enumerate(keyframes):
- if i < self.range["min"]: continue
- if i > self.range["max"]: break
- C.scene.frame_set(keypoint.co[0])
- self.set_pose_from_diff()
- if self.root_translation:
- self.target.keyframe_insert(\
- 'pose.bones["'+ name +'"].location',
- index=-1,
- frame=bpy.context.scene.frame_current,
- group=name)
- for b in self.target.pose.bones:
- # print("Setting key to %s"% b.name)
- self.target.keyframe_insert(\
- 'pose.bones["'+ b.name +'"].rotation_quaternion',
- index=-1,
- frame=bpy.context.scene.frame_current,
- group=b.name)
- print("Done")
- def main():
- # Don't ee all operators in info window
- bpy.app.debug_wm = False
- clean_empties()
- a = Armature_converter('SOURCE','TARGET')
- a.range["max"] = 20
- a.root_translation = True
- a.inherit_rotations = True
- a.get_pose_diff()
- a.convert_animation()
- # a.set_pose_from_diff()
- a.set_poseposition()
- # See all operators in info window
- bpy.app.debug_wm = True
- # e = bpy.ops.object.empty_add(type='ARROWS', radius=0.3, view_align=False,
- # location= self.source.pose.bones[bone.name].tail, rotation= (diff.conjugated()).to_euler(),
- # layers=(True,) + (False,) * 19)
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement