diff --git a/release/scripts/modules/mocap_tools.py b/release/scripts/modules/mocap_tools.py index 33e9105201c..1ce76dfbe6f 100644 --- a/release/scripts/modules/mocap_tools.py +++ b/release/scripts/modules/mocap_tools.py @@ -567,3 +567,13 @@ def rotate_fix_armature(arm_data): for bone in connectedBones: arm_data.edit_bones[bone].use_connect = True bpy.ops.object.mode_set(mode='OBJECT', toggle=False) + + +def scale_fix_armature(performer_obj, enduser_obj): + perf_bones = performer_obj.data.bones + end_bones = enduser_obj.data.bones + + #perf_avg = performer_obj.dimensions + #end_avg = enduser_obj.dimensions + #print(perf_avg, end_avg) + #performer_obj.scale /= (perf_avg / end_avg) diff --git a/release/scripts/modules/retarget.py b/release/scripts/modules/retarget.py index 0b694453865..e8c9f3e25aa 100644 --- a/release/scripts/modules/retarget.py +++ b/release/scripts/modules/retarget.py @@ -105,7 +105,12 @@ def createIntermediate(performer_obj, enduser_obj, root, s_frame, e_frame, scene else: perf_bone = performer_bones[perf_bone_name[0].name] inter_bone.matrix_basis = singleBoneRetarget(inter_bone, perf_bone) - + elif inter_bone.parent: + if "Temp" in inter_bone.parent.name: + inter_bone.parent.bone.use_inherit_rotation = True + inter_bone.bone.use_inherit_rotation = True + else: + inter_bone.bone.use_inherit_rotation = True inter_bone.keyframe_insert("rotation_quaternion") for child in inter_bone.children: retargetPerfToInter(child) @@ -119,12 +124,14 @@ def createIntermediate(performer_obj, enduser_obj, root, s_frame, e_frame, scene bpy.ops.object.mode_set(mode='EDIT') #add some temporary connecting bones in case end user bones are not connected to their parents for bone in inter_obj.data.edit_bones: - if not bone.use_connect and bone.parent: + if not bone.use_connect and bone.parent and inter_obj.data.bones[bone.name].reverseMap: newBone = inter_obj.data.edit_bones.new("Temp") - newBone.head = bone.parent.head + newBone.head = bone.parent.tail newBone.tail = bone.head newBone.parent = bone.parent bone.parent = newBone + bone.use_connect = True + newBone.use_connect = True #resets roll bpy.ops.armature.calculate_roll(type='Z') bpy.ops.object.mode_set(mode="OBJECT") @@ -165,7 +172,7 @@ def retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene): if trg_bone.parent and trg_bone.bone.use_inherit_rotation: srcParent = src_bone.parent - if not trg_bone.bone.use_connect: + if "Temp" in srcParent.name: srcParent = srcParent.parent parent_mat = srcParent.matrix parent_rest = trg_bone.parent.bone.matrix_local @@ -187,6 +194,8 @@ def retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene): end_bone.keyframe_insert("rotation_axis_angle") else: end_bone.keyframe_insert("rotation_euler") + if not end_bone.bone.use_connect: + end_bone.keyframe_insert("location") for bone in end_bone.children: bakeTransform(bone) @@ -384,11 +393,16 @@ def NLASystemInitialize(enduser_obj, s_frame): def totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame): perf_arm = performer_obj.data end_arm = enduser_obj.data + 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") inter_obj = createIntermediate(performer_obj, enduser_obj, root, s_frame, e_frame, scene) + print("retargeting from intermediate to end user") retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene) + print("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) restoreObjMat(performer_obj, enduser_obj, perf_obj_mat, enduser_obj_mat, stride_bone) @@ -396,6 +410,7 @@ def totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame): bpy.ops.object.select_name(name=inter_obj.name, extend=False) bpy.ops.object.delete() NLASystemInitialize(enduser_obj, s_frame) + print("retargeting done!") if __name__ == "__main__": diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py index 356de00e8ee..0e623f44d9a 100644 --- a/release/scripts/startup/ui_mocap.py +++ b/release/scripts/startup/ui_mocap.py @@ -191,6 +191,7 @@ class MocapPanel(bpy.types.Panel): row.operator("mocap.samples", text='Samples to Beziers') row.operator("mocap.denoise", text='Clean noise') row.operator("mocap.rotate_fix", text='Fix BVH Axis Orientation') + row.operator("mocap.scale_fix", text='Auto scale Performer') row2 = self.layout.row(align=True) row2.operator("mocap.looper", text='Loop animation') row2.operator("mocap.limitdof", text='Constrain Rig') @@ -430,6 +431,27 @@ class OBJECT_OT_RotateFixArmature(bpy.types.Operator): return isinstance(context.active_object.data, bpy.types.Armature) +class OBJECT_OT_ScaleFixArmature(bpy.types.Operator): + bl_idname = "mocap.scale_fix" + bl_label = "Scales performer armature to match target armature" + + def execute(self, context): + enduser_obj = bpy.context.active_object + performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj][0] + mocap_tools.scale_fix_armature(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_AddMocapConstraint(bpy.types.Operator): bl_idname = "mocap.addconstraint" bl_label = "Add constraint to target armature"