Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjy Cook <benjycook@hotmail.com>2011-08-11 17:47:49 +0400
committerBenjy Cook <benjycook@hotmail.com>2011-08-11 17:47:49 +0400
commit87e9c0ffaa5f8f64ccdea5c2ce74dfbd0edf0e43 (patch)
tree9bcb6b1a975da85c3dfa145f5cf0fa4b6562f79a /release/scripts
parentfee7337249342c3d5a332358883af9afe961f38d (diff)
Advanced Retargeting option: If the end user armature is complex, on the level of Sintel/Mancandy rigs, the user is requested to mark Advanced Retargeting, and constraints will be semi automatically configured to retarget the animation and then Retargeting will bake and remove these constraints
Diffstat (limited to 'release/scripts')
-rw-r--r--release/scripts/modules/retarget.py89
-rw-r--r--release/scripts/startup/ui_mocap.py51
2 files changed, 127 insertions, 13 deletions
diff --git a/release/scripts/modules/retarget.py b/release/scripts/modules/retarget.py
index 9415553d4ff..88a5c3a620a 100644
--- a/release/scripts/modules/retarget.py
+++ b/release/scripts/modules/retarget.py
@@ -21,6 +21,7 @@
import bpy
from mathutils import *
from math import radians, acos
+from bl_operators import nla
import cProfile
@@ -264,6 +265,7 @@ def copyTranslation(performer_obj, enduser_obj, perfFeet, root, s_frame, e_frame
v = locDeriv[key][i]
hipV = locDeriv[perfRoot][i]
endV = locDeriv[perf_bones[key].bone.map][i]
+ print(v.length,)
if (v.length < 0.1):
#this is a plant frame.
#lets see what the original hip delta is, and the corresponding
@@ -284,6 +286,7 @@ def copyTranslation(performer_obj, enduser_obj, perfFeet, root, s_frame, e_frame
stride_bone.name = "stride_bone"
print(stride_bone)
stride_bone.location = Vector((0, 0, 0))
+ print(linearAvg)
if linearAvg:
#determine the average change in scale needed
avg = sum(linearAvg) / len(linearAvg)
@@ -295,6 +298,8 @@ def copyTranslation(performer_obj, enduser_obj, perfFeet, root, s_frame, e_frame
newTranslation = (tailLoc(perf_bones[perfRoot]) / avg)
stride_bone.location = enduser_obj_mat * (newTranslation - initialPos)
stride_bone.keyframe_insert("location")
+ else:
+ stride_bone.keyframe_insert("location")
stride_bone.animation_data.action.name = ("Stride Bone " + action_name)
return stride_bone
@@ -439,10 +444,66 @@ def NLASystemInitialize(enduser_arm, context):#enduser_obj, name):
anim_data.action = None
+def preAdvancedRetargeting(performer_obj, enduser_obj):
+ createDictionary(performer_obj.data, enduser_obj.data)
+ bones = enduser_obj.pose.bones
+ map_bones = [bone for bone in bones if bone.bone.reverseMap]
+ for bone in map_bones:
+ perf_bone = bone.bone.reverseMap[0].name
+ addLocalRot = False;
+ if bone.bone.use_connect or not bone.constraints:
+ locks = bone.lock_location
+ if not (locks[0] or locks[1] or locks[2]):
+ cons = bone.constraints.new('COPY_LOCATION')
+ cons.name = "retargetTemp"
+ cons.use_x = not locks[0]
+ cons.use_y = not locks[1]
+ cons.use_z = not locks[2]
+ cons.target = performer_obj
+ cons.subtarget = perf_bone
+ addLocalRot = True
+
+
+ cons2 = bone.constraints.new('COPY_ROTATION')
+ cons2.name = "retargetTemp"
+ locks = bone.lock_rotation
+ cons2.use_x = not locks[0]
+ cons2.use_y = not locks[1]
+ cons2.use_z = not locks[2]
+ cons2.target = performer_obj
+ cons2.subtarget = perf_bone
+
+ if addLocalRot:
+ for constraint in bone.constraints:
+ if constraint.type == 'COPY_ROTATION':
+ constraint.target_space = 'LOCAL'
+ constraint.owner_space = 'LOCAL_WITH_PARENT'
+
+
+def prepareForBake(enduser_obj):
+ bones = enduser_obj.pose.bones
+ for bone in bones:
+ bone.bone.select = False
+ map_bones = [bone for bone in bones if bone.bone.reverseMap]
+ for bone in map_bones:
+ for cons in bone.constraints:
+ if "retargetTemp" in cons.name:
+ bone.bone.select = True
+
+def cleanTempConstraints(enduser_obj):
+ bones = enduser_obj.pose.bones
+ map_bones = [bone for bone in bones if bone.bone.reverseMap]
+ for bone in map_bones:
+ for cons in bone.constraints:
+ if "retargetTemp" in cons.name:
+ bone.constraints.remove(cons)
+
#Main function that runs the retargeting sequence.
+#If advanced == True, we assume constraint's were already created
def totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame):
perf_arm = performer_obj.data
end_arm = enduser_obj.data
+ advanced = end_arm.advancedRetarget
try:
enduser_obj.animation_data.action = bpy.data.actions.new("temp")
@@ -450,27 +511,33 @@ def totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame):
except:
print("no need to create new action")
-
print("creating Dictionary")
feetBones, root = createDictionary(perf_arm, end_arm)
print("cleaning stuff up")
perf_obj_mat, enduser_obj_mat = cleanAndStoreObjMat(performer_obj, enduser_obj)
- turnOffIK(enduser_obj)
- print("Creating intermediate armature (for first pass)")
- inter_obj = createIntermediate(performer_obj, enduser_obj, root, s_frame, e_frame, scene)
- print("First pass: retargeting from intermediate to end user")
-
-
- retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene)
+ if not advanced:
+ turnOffIK(enduser_obj)
+ print("Creating intermediate armature (for first pass)")
+ inter_obj = createIntermediate(performer_obj, enduser_obj, root, s_frame, e_frame, scene)
+ print("First pass: retargeting from intermediate to end user")
+ retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene)
+ else:
+ prepareForBake(enduser_obj)
+ print("Retargeting pose (Advanced Retarget)")
+ nla.bake(s_frame, e_frame, action=enduser_obj.animation_data.action, only_selected=True, do_pose=True, do_object=False)
name = performer_obj.animation_data.action.name
enduser_obj.animation_data.action.name = "Base " + name
print("Second pass: retargeting root translation and clean up")
stride_bone = copyTranslation(performer_obj, enduser_obj, feetBones, root, s_frame, e_frame, scene, enduser_obj_mat)
- IKRetarget(performer_obj, enduser_obj, s_frame, e_frame, scene)
+ if not advanced:
+ IKRetarget(performer_obj, enduser_obj, s_frame, e_frame, scene)
restoreObjMat(performer_obj, enduser_obj, perf_obj_mat, enduser_obj_mat, stride_bone)
bpy.ops.object.mode_set(mode='OBJECT')
- bpy.ops.object.select_name(name=inter_obj.name, extend=False)
- bpy.ops.object.delete()
+ if not advanced:
+ bpy.ops.object.select_name(name=inter_obj.name, extend=False)
+ bpy.ops.object.delete()
+ else:
+ cleanTempConstraints(enduser_obj)
bpy.ops.object.select_name(name=enduser_obj.name, extend=False)
if not name in [tracks.name for tracks in end_arm.mocapNLATracks]:
diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py
index 0788366547e..06d0bb0b415 100644
--- a/release/scripts/startup/ui_mocap.py
+++ b/release/scripts/startup/ui_mocap.py
@@ -140,9 +140,26 @@ class MocapNLATracks(bpy.types.PropertyGroup):
bpy.utils.register_class(MocapNLATracks)
+
+def advancedRetargetToggle(self, context):
+ enduser_obj = context.active_object
+ performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj]
+ if enduser_obj is None or len(performer_obj) != 1:
+ print("Need active and selected armatures")
+ return
+ else:
+ performer_obj = performer_obj[0]
+ if self.advancedRetarget:
+ retarget.preAdvancedRetargeting(performer_obj, enduser_obj)
+ else:
+ retarget.cleanTempConstraints(enduser_obj)
+
+
+
bpy.types.Armature.stitch_settings = bpy.props.PointerProperty(type=AnimationStitchSettings)
bpy.types.Armature.active_mocap = bpy.props.StringProperty(update=retarget.NLASystemInitialize)
bpy.types.Armature.mocapNLATracks = bpy.props.CollectionProperty(type=MocapNLATracks)
+bpy.types.Armature.advancedRetarget = bpy.props.BoolProperty(default=False, update=advancedRetargetToggle)
#Update function for IK functionality. Is called when IK prop checkboxes are toggled.
@@ -189,7 +206,7 @@ def toggleIKBone(self, context):
for bone in cnstrn_bone.parent_recursive:
if not bone.is_in_ik_chain:
bone.IKRetarget = False
-
+
class MocapMapping(bpy.types.PropertyGroup):
name = bpy.props.StringProperty()
@@ -281,6 +298,7 @@ class MocapPanel(bpy.types.Panel):
mapRow.operator("mocap.savemapping", text='Save mapping')
mapRow.operator("mocap.loadmapping", text='Load mapping')
self.layout.prop(data=performer_obj.animation_data.action, property='name', text='Action Name')
+ self.layout.prop(enduser_arm, "advancedRetarget", text='Advanced Retarget')
self.layout.operator("mocap.retarget", text='RETARGET!')
@@ -396,6 +414,35 @@ class OBJECT_OT_RetargetButton(bpy.types.Operator):
return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature)
else:
return False
+
+
+ #~ class OBJECT_OT_AdvancedRetargetButton(bpy.types.Operator):
+ #~ '''Prepare for advanced retargeting '''
+ #~ bl_idname = "mocap.preretarget"
+ #~ bl_label = "Prepares retarget of active action from Performer to Enduser"
+
+ #~ def execute(self, context):
+ #~ scene = context.scene
+ #~ s_frame = scene.frame_start
+ #~ e_frame = scene.frame_end
+ #~ enduser_obj = context.active_object
+ #~ performer_obj = [obj for obj in context.selected_objects if obj != enduser_obj]
+ #~ if enduser_obj is None or len(performer_obj) != 1:
+ #~ print("Need active and selected armatures")
+ #~ else:
+ #~ performer_obj = performer_obj[0]
+ #~ retarget.preAdvancedRetargeting(performer_obj, enduser_obj)
+ #~ return {"FINISHED"}
+
+ #~ @classmethod
+ #~ def poll(cls, context):
+ #~ if context.active_object:
+ #~ activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature)
+ #~ performer_obj = [obj for obj in context.selected_objects if obj != context.active_object]
+ #~ if performer_obj:
+ #~ return activeIsArmature and isinstance(performer_obj[0].data, bpy.types.Armature)
+ #~ else:
+ #~ return False
class OBJECT_OT_SaveMappingButton(bpy.types.Operator):
@@ -715,7 +762,7 @@ class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator):
stitch_settings = context.active_object.data.stitch_settings
return (stitch_settings.first_action and stitch_settings.second_action)
return False
-
+
def register():
bpy.utils.register_module(__name__)