[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [37104] branches/soc-2011-pepper/release/ scripts/modules/retarget.py: 2nd commit of mine.

Benjy Cook benjycook at hotmail.com
Thu Jun 2 19:19:07 CEST 2011


Revision: 37104
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=37104
Author:   benjycook
Date:     2011-06-02 17:19:07 +0000 (Thu, 02 Jun 2011)
Log Message:
-----------
2nd commit of mine. Contains retarget.py, which has functions for retargeting an animated armature to a second one, given a user mapping of the hiearchy. Currently creates an intermediate skeleton that solves some of the major issues. WIP

Added Paths:
-----------
    branches/soc-2011-pepper/release/scripts/modules/retarget.py

Added: branches/soc-2011-pepper/release/scripts/modules/retarget.py
===================================================================
--- branches/soc-2011-pepper/release/scripts/modules/retarget.py	                        (rev 0)
+++ branches/soc-2011-pepper/release/scripts/modules/retarget.py	2011-06-02 17:19:07 UTC (rev 37104)
@@ -0,0 +1,136 @@
+import bpy
+from mathutils import *
+from math import radians, acos
+performer_obj = bpy.data.objects["performer"]
+enduser_obj = bpy.data.objects["enduser"]
+scene = bpy.context.scene
+
+# dictionary of mapping
+bonemap = { "LeftFoot": ("DEF_Foot.L","DEF_Toes.L"),
+            "LeftUpLeg": "DEF_Thigh.L",
+            "Hips": "DEF_Hip",
+            "LowerBack": "DEF_Spine",
+            "Spine": "DEF_Torso",
+            "Neck": "DEF_Neck",
+            "Neck1": "DEF_Neck",
+            "Head": "DEF_Head",
+            "LeftShoulder": "DEF_Shoulder.L",
+            "LeftArm": "DEF_Forearm.L",
+            "LeftForeArm": "DEF_Arm.L",
+            "LeftHand": "DEF_Hand.L",
+            "RightShoulder": "DEF_Shoulder.R",
+            "RightArm": "DEF_Forearm.R",
+            "RightForeArm": "DEF_Arm.R",
+            "RightHand": "DEF_Hand.R",
+            "RightFoot": ("DEF_Foot.R","DEF_Toes.R"),
+            "RightUpLeg": "DEF_Thigh.R",
+            "RightLeg": "DEF_Shin.R",
+            "LeftLeg": "DEF_Shin.L"}
+# creation of a reverse map
+# multiple keys get mapped to list values
+bonemapr = {}
+for key in bonemap.keys():
+    if not bonemap[key] in bonemapr:
+        if type(bonemap[key])==type((0,0)):
+            for key_x in bonemap[key]:
+                bonemapr[key_x] = [key]
+        else:
+            bonemapr[bonemap[key]] = [key]
+    else:
+        bonemapr[bonemap[key]].append(key)
+        
+# list of empties created to keep track of "original"
+# position data
+# in final product, these locations can be stored as custom props
+
+constraints = []
+
+#creation of intermediate armature
+# the intermediate armature has the hiearchy of the end user,
+# does not have rotation inheritence
+# and bone roll is identical to the performer
+# its purpose is to copy over the rotations
+# easily while concentrating on the hierarchy changes
+def createIntermediate():
+    
+    #creates and keyframes an empty with its location
+    #the original position of the tail bone
+    #useful for storing the important data in the original motion
+    #i.e. using this empty to IK the chain to that pos.
+    def locOfOriginal(inter_bone,perf_bone):
+        if not perf_bone.name+"Org" in bpy.data.objects:
+            bpy.ops.object.add()
+            empty = bpy.context.active_object
+            empty.name = perf_bone.name+"Org"
+        empty = bpy.data.objects[perf_bone.name+"Org"]
+        offset = perf_bone.vector
+        scaling = perf_bone.length / inter_bone.length
+        offset/=scaling
+        empty.location = inter_bone.head + offset
+        empty.keyframe_insert("location")
+    
+    #Simple 1to1 retarget of a bone
+    def singleBoneRetarget(inter_bone,perf_bone):
+            perf_world_rotation = perf_bone.matrix * performer_obj.matrix_world         
+            inter_world_base_rotation = inter_bone.bone.matrix_local * inter_obj.matrix_world
+            inter_world_base_inv = Matrix(inter_world_base_rotation)
+            inter_world_base_inv.invert()
+            return (inter_world_base_inv.to_3x3() * perf_world_rotation.to_3x3()).to_4x4()
+        
+    #uses 1to1 and interpolation/averaging to match many to 1 retarget    
+    def manyPerfToSingleInterRetarget(inter_bone,performer_bones_s):
+        retarget_matrices = [singleBoneRetarget(inter_bone,perf_bone) for perf_bone in performer_bones_s]
+        lerp_matrix = Matrix()
+        for i in range(len(retarget_matrices)-1):
+            first_mat = retarget_matrices[i]
+            next_mat = retarget_matrices[i+1]
+            lerp_matrix = first_mat.lerp(next_mat,0.5)
+        return lerp_matrix
+    
+    #determines the type of hierachy change needed and calls the 
+    #right function        
+    def retargetPerfToInter(inter_bone):
+        if inter_bone.name in bonemapr.keys():
+            perf_bone_name = bonemapr[inter_bone.name]
+            #is it a 1 to many?
+            if type(bonemap[perf_bone_name[0]])==type((0,0)):
+                perf_bone = performer_bones[perf_bone_name[0]]
+                if inter_bone.name == bonemap[perf_bone_name[0]][0]:
+                    locOfOriginal(inter_bone,perf_bone)
+            else:
+                # then its either a many to 1 or 1 to 1
+                
+                if len(perf_bone_name) > 1:
+                    performer_bones_s = [performer_bones[name] for name in perf_bone_name]
+                    #we need to map several performance bone to a single
+                    inter_bone.matrix_basis = manyPerfToSingleInterRetarget(inter_bone,performer_bones_s)
+                else:
+                    perf_bone = performer_bones[perf_bone_name[0]]
+                    inter_bone.matrix_basis = singleBoneRetarget(inter_bone,perf_bone)
+                    
+        inter_bone.keyframe_insert("rotation_quaternion")
+        for child in inter_bone.children:
+            retargetPerfToInter(child)
+            
+    #creates the intermediate armature object        
+    bpy.ops.object.select_name(name="enduser",extend=False)
+    bpy.ops.object.duplicate(linked=False)
+    bpy.context.active_object.name = "intermediate"
+    inter_obj = bpy.context.active_object
+    bpy.ops.object.mode_set(mode='EDIT')
+    #resets roll 
+    bpy.ops.armature.calculate_roll(type='Z')
+    bpy.ops.object.mode_set(mode="OBJECT")
+    performer_bones = performer_obj.pose.bones
+    inter_bones =  inter_obj.pose.bones
+    
+    #clears inheritance
+    for inter_bone in inter_bones:
+        inter_bone.bone.use_inherit_rotation = False
+        
+    for t in range(1,150):
+        scene.frame_set(t)
+        inter_bone = inter_bones["DEF_Hip"]
+        retargetPerfToInter(inter_bone)
+         
+createIntermediate()   
\ No newline at end of file


Property changes on: branches/soc-2011-pepper/release/scripts/modules/retarget.py
___________________________________________________________________
Added: svn:eol-style
   + native




More information about the Bf-blender-cvs mailing list