Added IK functionality to retargeting. If rig contains an IK constraint, in addition...
authorBenjy Cook <benjycook@hotmail.com>
Sun, 26 Jun 2011 19:54:29 +0000 (19:54 +0000)
committerBenjy Cook <benjycook@hotmail.com>
Sun, 26 Jun 2011 19:54:29 +0000 (19:54 +0000)
release/scripts/modules/retarget.py
release/scripts/startup/ui_mocap.py

index 8fe8c6937bb42d027b64a3a1a2f8b91aa800a6c9..8cbd7129dd34d453a79f2df425e0ebbdfa306657 100644 (file)
@@ -269,13 +269,6 @@ def copyTranslation(performer_obj, enduser_obj, perfFeet, bonemap, bonemapr, roo
         bpy.ops.object.add()
         stride_bone = bpy.context.active_object
         stride_bone.name = "stride_bone"
-        bpy.ops.object.select_name(name=stride_bone.name, extend=False)
-        bpy.ops.object.select_name(name=enduser_obj.name, extend=True)
-        bpy.ops.object.mode_set(mode='POSE')
-        bpy.ops.pose.select_all(action='DESELECT')
-        root_bone = end_bones[root]
-        root_bone.bone.select = True
-        bpy.ops.pose.constraint_add_with_targets(type='CHILD_OF')
         for t in range(s_frame, e_frame):
             scene.frame_set(t)
             newTranslation = (tailLoc(perf_bones[perfRoot]) / avg)
@@ -283,7 +276,57 @@ def copyTranslation(performer_obj, enduser_obj, perfFeet, bonemap, bonemapr, roo
             stride_bone.keyframe_insert("location")
 
 
+def IKRetarget(bonemap, bonemapr, performer_obj, enduser_obj, s_frame, e_frame, scene):
+    end_bones = enduser_obj.pose.bones
+    for pose_bone in end_bones:
+        if "IK" in [constraint.type for constraint in pose_bone.constraints]:
+            # set constraint target to corresponding empty if targetless,
+            # if not, keyframe current target to corresponding empty
+            perf_bone = bonemapr[pose_bone.name]
+            if isinstance(perf_bone, list):
+                perf_bone = bonemapr[pose_bone.name][-1]
+            end_empty = bpy.data.objects[perf_bone + "Org"]
+            ik_constraint = [constraint for constraint in pose_bone.constraints if constraint.type == "IK"][0]
+            if not ik_constraint.target:
+                ik_constraint.target = end_empty
+            else:
+                #Bone target
+                target_is_bone = False
+                if ik_constraint.subtarget:
+                    target = ik_constraint.target.pose.bones[ik_constraint.subtarget]
+                    target.bone.use_local_location = False
+                    target_is_bone = True
+                else:
+                    target = ik_constraint.target
+                for t in range(s_frame, e_frame):
+                    scene.frame_set(t)
+                    if target_is_bone:
+                        final_loc = end_empty.location - target.bone.matrix_local.to_translation()
+                    else:
+                        final_loc = end_empty.location
+                    target.location = final_loc
+                    target.keyframe_insert("location")
+            ik_constraint.mute = False
+
+
+def turnOffIK(enduser_obj):
+    end_bones = enduser_obj.pose.bones
+    for pose_bone in end_bones:
+        if pose_bone.is_in_ik_chain:
+            pass
+            # TODO:
+            # set stiffness according to place on chain
+            # and values from analysis that is stored in the bone
+            #pose_bone.ik_stiffness_x = 0.5
+            #pose_bone.ik_stiffness_y = 0.5
+            #pose_bone.ik_stiffness_z = 0.5
+        if "IK" in [constraint.type for constraint in pose_bone.constraints]:
+            ik_constraint = [constraint for constraint in pose_bone.constraints if constraint.type == "IK"][0]
+            ik_constraint.mute = True
+
+
 def totalRetarget():
+    print("retargeting...")
     enduser_obj = bpy.context.active_object
     performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj]
     if enduser_obj is None or len(performer_obj) != 1:
@@ -296,9 +339,11 @@ def totalRetarget():
     s_frame = scene.frame_start
     e_frame = scene.frame_end
     bonemap, bonemapr, root = createDictionary(perf_arm)
+    turnOffIK(enduser_obj)
     inter_obj, inter_arm = createIntermediate(performer_obj, enduser_obj, bonemap, bonemapr, root, s_frame, e_frame, scene)
     retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene)
     copyTranslation(performer_obj, enduser_obj, ["RightFoot", "LeftFoot"], bonemap, bonemapr, root, s_frame, e_frame, scene)
+    IKRetarget(bonemap, bonemapr, performer_obj, enduser_obj, s_frame, e_frame, scene)
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.select_name(name=inter_obj.name, extend=False)
     bpy.ops.object.delete()
index 8454a99d4d5c4550b82e21a616b59d46d6962fb9..9c540771b443e1286e2092f116ba37c220976afb 100644 (file)
@@ -60,14 +60,24 @@ class MocapPanel(bpy.types.Panel):
             self.layout.label("Select performer rig and target rig (as active)")
         else:
             performer_obj = performer_obj[0]
-            if performer_obj.data.name in bpy.data.armatures and enduser_obj.data.name in bpy.data.armatures:
-                perf = performer_obj.data
-                enduser_arm = enduser_obj.data
-                for bone in perf.bones:
-                    row = self.layout.row(align=True)
-                    row.label(bone.name)
-                    row.prop_search(bone, "map", enduser_arm, "bones")
-                self.layout.operator("mocap.retarget", text='RETARGET!')
+            if performer_obj.data and enduser_obj.data:
+                if performer_obj.data.name in bpy.data.armatures and enduser_obj.data.name in bpy.data.armatures:
+                    perf = performer_obj.data
+                    enduser_arm = enduser_obj.data
+                    perf_pose_bones = enduser_obj.pose.bones
+                    for bone in perf.bones:
+                        row = self.layout.row(align=True)
+                        row.label(bone.name)
+                        row.prop_search(bone, "map", enduser_arm, "bones")
+                        label_mod = "FK"
+                        if bone.map:
+                            pose_bone = perf_pose_bones[bone.map]
+                            if pose_bone.is_in_ik_chain:
+                                label_mod = "IK"
+                            if "IK" in [constraint.type for constraint in pose_bone.constraints]:
+                                label_mod = "IKEnd"
+                        row.label(label_mod)
+                    self.layout.operator("mocap.retarget", text='RETARGET!')
 
 
 class OBJECT_OT_RetargetButton(bpy.types.Operator):