Advertisement
Guest User

Untitled

a guest
Apr 8th, 2020
257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.19 KB | None | 0 0
  1. import bpy
  2. from math import degrees
  3. from mathutils import Quaternion
  4.  
  5.  
  6. C= bpy.context
  7. D= bpy.data
  8.  
  9. def clean_empties():
  10.     for ob in D.scenes['Scene'].objects:
  11.             if ob.type == "EMPTY":
  12.                 D.scenes['Scene'].objects.unlink(ob)
  13.  
  14.  
  15.  
  16. class Armature_converter:
  17.     """Translates the animation of one armature to another with different zero pose"""
  18.     bpy.types.Bone.diff_quat = bpy.props.FloatVectorProperty(
  19.             "Difference rotation",
  20.             subtype= "QUATERNION",
  21.             size = 4,
  22.             default=(1,0,0,0))
  23.  
  24.     bpy.types.Bone.diff_vec = bpy.props.FloatVectorProperty(
  25.             "Difference position",
  26.             subtype= "TRANSLATION",
  27.             size = 3,
  28.             default=(0,0,0))
  29.    
  30.     def __init__(self, source, target):
  31.         self.source = D.objects[source]
  32.         self.target = D.objects[target]
  33.         self.root_translation = True
  34.         self.inherit_rotations = True
  35.         self.range = {"min" : 0, "max" : float("inf")}
  36.  
  37.         self.set_poseposition("REST")
  38.  
  39.         C.scene.objects.active = self.target
  40.         bpy.ops.object.mode_set(mode = 'POSE')
  41.  
  42.         print("Converting armature {} to {}\n".format(source, target))
  43.  
  44.  
  45.     def set_poseposition(self, mode = "POSE"):
  46.         self.source.data.pose_position = mode
  47.         self.target.data.pose_position = mode
  48.  
  49.     def get_basebone(self, where="source"):
  50.         #ATTENTION!! source return data Bone, target returns PoseBone!
  51.         if where == "source":
  52.             basebone = [b for b in self.source.data.bones if b.parent is None]
  53.         else:
  54.             basebone = [b for b in self.target.pose.bones if b.parent is None]
  55.  
  56.         if len(basebone) != 1:
  57.             raise Exception("The base armature has to have exactly one base bone")
  58.         else:
  59.             basebone = basebone[0]
  60.  
  61.         return basebone
  62.  
  63.     def reset_pose(self):
  64.         self.get_basebone("target").rotation_quaternion.identity()
  65.         self.walk_bones(self.get_basebone("target"), lambda b: b.rotation_quaternion.identity())
  66.  
  67.     def get_pose_diff(self):
  68.         if not self.inherit_rotations:
  69.             for b in self.target.data.bones:
  70.                 b.use_inherit_rotation = False
  71.             return
  72.        
  73.         for b in self.target.data.bones:
  74.             b.use_inherit_rotation = True
  75.  
  76.         self.reset_pose()
  77.         self.walk_bones(self.get_basebone(), self.get_bone_diff)
  78.  
  79.        
  80.     def get_bone_diff(self, bone):
  81.         rot_bone =  bone.matrix.to_quaternion()
  82.         other = self.target.data.bones[bone.name]
  83.         rot_other = other.matrix.to_quaternion()
  84.  
  85.         bone.diff_quat = rot_bone.rotation_difference( rot_other )
  86.  
  87.     def set_bone_from_diff(self, bone):
  88.         t_bone = self.target.pose \
  89.                     .bones[bone.name]
  90.  
  91.         C.scene.objects.active = self.target
  92.         bpy.ops.object.mode_set(mode = 'POSE')
  93.  
  94.         ###
  95.         if self.root_translation:
  96.             v = self.source.pose.bones[bone.name].location
  97.         else:
  98.             v = (0,0,0)
  99.  
  100.         self.target.pose \
  101.                 .bones[bone.name] \
  102.                 .location = v
  103.  
  104.         ###
  105.         if not self.inherit_rotations:
  106.             self.set_poseposition()
  107.             # bpy.ops.object.mode_set(mode = 'OBJECT')     
  108.             # e = bpy.ops.object.empty_add(type='ARROWS', radius=0.3, view_align=False,
  109.             #           location=  self.source.pose.bones[bone.name].tail, rotation= self.source.pose.bones[bone.name].matrix.to_euler(),
  110.             #           layers=(True,) + (False,) * 19)
  111.  
  112.             m = self.source.pose.bones[bone.name].matrix.copy()
  113.             m.resize_4x4()
  114.             t_bone.matrix = m
  115.  
  116.             # bpy.ops.object.select_all(action = 'DESELECT')
  117.             # self.target.select = True
  118.            
  119.                                
  120.             return
  121.  
  122.         ###
  123.         t_bone.rotation_quaternion *= bone.diff_quat.conjugated() \
  124.                                         * self.source.pose.bones[bone.name].rotation_quaternion
  125.  
  126.         # print("{:16} | {} | {}".format(bone.name, bone.diff_quat, bone.diff_quat))
  127.    
  128.     def set_pose_from_diff(self):
  129.         self.reset_pose()
  130.         self.set_bone_from_diff(self.get_basebone())
  131.         self.walk_bones(self.get_basebone(), self.set_bone_from_diff)
  132.    
  133.     @staticmethod
  134.     def walk_bones(bone, handler):
  135.         for ch in bone.children:
  136.             handler(ch)
  137.             Armature_converter.walk_bones(ch, handler)
  138.  
  139.     def convert_animation(self):
  140.         name = self.get_basebone("target").name
  141.        
  142.         keyframes = self.source.animation_data.action.fcurves[0].keyframe_points
  143.         for i,keypoint in enumerate(keyframes):
  144.             if i < self.range["min"]: continue
  145.             if i > self.range["max"]: break
  146.  
  147.             C.scene.frame_set(keypoint.co[0])
  148.             self.set_pose_from_diff()
  149.            
  150.             if self.root_translation:
  151.                 self.target.keyframe_insert(\
  152.                     'pose.bones["'+ name +'"].location',
  153.                         index=-1,
  154.                         frame=bpy.context.scene.frame_current,
  155.                         group=name)
  156.  
  157.             for b in self.target.pose.bones:
  158.                 # print("Setting key to %s"% b.name)
  159.                 self.target.keyframe_insert(\
  160.                     'pose.bones["'+ b.name +'"].rotation_quaternion',
  161.                         index=-1,
  162.                         frame=bpy.context.scene.frame_current,
  163.                         group=b.name)
  164.  
  165.         print("Done")
  166.  
  167.  
  168. def main():
  169.     # Don't ee all operators in info window
  170.     bpy.app.debug_wm = False
  171.     clean_empties()
  172.  
  173.     a = Armature_converter('SOURCE','TARGET')
  174.     a.range["max"] = 20
  175.     a.root_translation = True
  176.     a.inherit_rotations = True
  177.     a.get_pose_diff()
  178.  
  179.     a.convert_animation()
  180.     # a.set_pose_from_diff()
  181.     a.set_poseposition()
  182.  
  183.     # See all operators in info window
  184.     bpy.app.debug_wm = True
  185.  
  186.     # e = bpy.ops.object.empty_add(type='ARROWS', radius=0.3, view_align=False,
  187.             #   location=  self.source.pose.bones[bone.name].tail, rotation= (diff.conjugated()).to_euler(),
  188.             #   layers=(True,) + (False,) * 19)
  189.    
  190. if __name__ == '__main__':
  191.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement