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:
-rw-r--r--release/scripts/modules/mocap_tools.py90
-rw-r--r--release/scripts/modules/retarget.py27
-rw-r--r--release/scripts/startup/ui_mocap.py20
3 files changed, 96 insertions, 41 deletions
diff --git a/release/scripts/modules/mocap_tools.py b/release/scripts/modules/mocap_tools.py
index 3f821270e3c..f4b6a93f531 100644
--- a/release/scripts/modules/mocap_tools.py
+++ b/release/scripts/modules/mocap_tools.py
@@ -105,64 +105,75 @@ class dataPoint:
self.u = u
-def autoloop_anim():
- context = bpy.context
- obj = context.active_object
- fcurves = [x for x in obj.animation_data.action.fcurves if x.select]
-
- data = []
- end = len(fcurves[0].keyframe_points)
+def crossCorrelationMatch(curvesA, curvesB, margin):
+ dataA = []
+ dataB = []
+ end = len(curvesA[0].keyframe_points)
for i in range(1, end):
vec = []
- for fcurve in fcurves:
+ for fcurve in curvesA:
vec.append(fcurve.evaluate(i))
- data.append(NdVector(vec))
+ dataA.append(NdVector(vec))
+ vec = []
+ for fcurve in curvesB:
+ vec.append(fcurve.evaluate(i))
+ dataB.append(NdVector(vec))
def comp(a, b):
return a * b
- N = len(data)
+ N = len(dataA)
Rxy = [0.0] * N
for i in range(N):
for j in range(i, min(i + N, N)):
- Rxy[i] += comp(data[j], data[j - i])
+ Rxy[i] += comp(dataA[j], dataB[j - i])
for j in range(i):
- Rxy[i] += comp(data[j], data[j - i + N])
+ Rxy[i] += comp(dataA[j], dataB[j - i + N])
Rxy[i] /= float(N)
-
def bestLocalMaximum(Rxy):
Rxyd = [Rxy[i] - Rxy[i - 1] for i in range(1, len(Rxy))]
maxs = []
for i in range(1, len(Rxyd) - 1):
a = Rxyd[i - 1]
b = Rxyd[i]
- print(a, b)
#sign change (zerocrossing) at point i, denoting max point (only)
if (a >= 0 and b < 0) or (a < 0 and b >= 0):
maxs.append((i, max(Rxy[i], Rxy[i - 1])))
- return max(maxs, key=lambda x: x[1])[0]
- flm = bestLocalMaximum(Rxy[0:int(len(Rxy))])
-
- diff = []
-
- for i in range(len(data) - flm):
- diff.append((data[i] - data[i + flm]).lengthSq)
+ return [x[0] for x in maxs]
+ #~ return max(maxs, key=lambda x: x[1])[0]
+
+ flms = bestLocalMaximum(Rxy[0:int(len(Rxy))])
+ ss = []
+ for flm in flms:
+ diff = []
+
+ for i in range(len(dataA) - flm):
+ diff.append((dataA[i] - dataB[i + flm]).lengthSq)
+
+ def lowerErrorSlice(diff, e):
+ #index, error at index
+ bestSlice = (0, 100000)
+ for i in range(e, len(diff) - e):
+ errorSlice = sum(diff[i - e:i + e + 1])
+ if errorSlice < bestSlice[1]:
+ bestSlice = (i, errorSlice, flm)
+ return bestSlice
+
+ s = lowerErrorSlice(diff, margin)
+ ss.append(s)
- def lowerErrorSlice(diff, e):
- #index, error at index
- bestSlice = (0, 100000)
- for i in range(e, len(diff) - e):
- errorSlice = sum(diff[i - e:i + e + 1])
- if errorSlice < bestSlice[1]:
- bestSlice = (i, errorSlice)
- return bestSlice[0]
+ ss.sort(key = lambda x: x[1])
+ return ss[0][2], ss[0][0], dataA
- margin = 2
+def autoloop_anim():
+ context = bpy.context
+ obj = context.active_object
+ fcurves = [x for x in obj.animation_data.action.fcurves if x.select]
- s = lowerErrorSlice(diff, margin)
+ margin = 10
- print(flm, s)
+ flm, s, data = crossCorrelationMatch(fcurves, fcurves, margin)
loop = data[s:s + flm + margin]
#find *all* loops, s:s+flm, s+flm:s+2flm, etc...
@@ -824,3 +835,18 @@ def anim_stitch(context, enduser_obj):
pt.handle_left.y-=offset[i]
pt.handle_right.y-=offset[i]
+
+def guess_anim_stitch(context, enduser_obj):
+ stitch_settings = enduser_obj.data.stitch_settings
+ action_1 = stitch_settings.first_action
+ action_2 = stitch_settings.second_action
+ TrackNamesA = enduser_obj.data.mocapNLATracks[action_1]
+ TrackNamesB = enduser_obj.data.mocapNLATracks[action_2]
+ mocapA = bpy.data.actions[TrackNamesA.base_track]
+ mocapB = bpy.data.actions[TrackNamesB.base_track]
+ curvesA = mocapA.fcurves
+ curvesB = mocapB.fcurves
+ flm, s, data = crossCorrelationMatch(curvesA, curvesB, 10)
+ print(flm,s)
+ enduser_obj.data.stitch_settings.blend_frame = flm
+ enduser_obj.data.stitch_settings.second_offset = s \ No newline at end of file
diff --git a/release/scripts/modules/retarget.py b/release/scripts/modules/retarget.py
index 0235bfc1474..827d3d11ddc 100644
--- a/release/scripts/modules/retarget.py
+++ b/release/scripts/modules/retarget.py
@@ -305,6 +305,7 @@ def copyTranslation(performer_obj, enduser_obj, perfFeet, root, s_frame, e_frame
def IKRetarget(performer_obj, enduser_obj, s_frame, e_frame, scene):
+ bpy.ops.object.select_name(name=enduser_obj.name, extend=False)
end_bones = enduser_obj.pose.bones
for pose_bone in end_bones:
ik_constraint = hasIKConstraint(pose_bone)
@@ -313,9 +314,12 @@ def IKRetarget(performer_obj, enduser_obj, s_frame, e_frame, scene):
# set constraint target to corresponding empty if targetless,
# if not, keyframe current target to corresponding empty
perf_bone = pose_bone.bone.reverseMap[-1].name
+ bpy.ops.object.mode_set(mode='EDIT')
orgLocTrg = originalLocationTarget(pose_bone, enduser_obj)
+ bpy.ops.object.mode_set(mode='OBJECT')
if not ik_constraint.target:
- ik_constraint.target = orgLocTrg
+ ik_constraint.target = enduser_obj
+ ik_constraint.subtarget = pose_bone.name+"IK"
target = orgLocTrg
# There is a target now
@@ -337,6 +341,7 @@ def IKRetarget(performer_obj, enduser_obj, s_frame, e_frame, scene):
target.keyframe_insert("location")
ik_constraint.mute = False
scene.frame_set(s_frame)
+ bpy.ops.object.mode_set(mode='OBJECT')
def turnOffIK(enduser_obj):
@@ -379,14 +384,17 @@ def restoreObjMat(performer_obj, enduser_obj, perf_obj_mat, enduser_obj_mat, str
#create (or return if exists) the related IK empty to the bone
def originalLocationTarget(end_bone, enduser_obj):
- if not end_bone.name + "Org" in bpy.data.objects:
- bpy.ops.object.add()
- empty = bpy.context.active_object
- empty.name = end_bone.name + "Org"
- empty.empty_draw_size = 0.1
- empty.parent = enduser_obj
- empty = bpy.data.objects[end_bone.name + "Org"]
- return empty
+ if not end_bone.name + "IK" in enduser_obj.data.bones:
+ newBone = enduser_obj.data.edit_bones.new(end_bone.name + "IK")
+ newBone.head = end_bone.tail
+ newBone.tail = end_bone.tail + Vector((0,0.1,0))
+ #~ empty = bpy.context.active_object
+ #~ empty.name = end_bone.name + "Org"
+ #~ empty.empty_draw_size = 0.1
+ #~ empty.parent = enduser_obj
+ else:
+ newBone = enduser_obj.pose.bones[end_bone.name + "IK"]
+ return newBone
#create the specified NLA setup for base animation, constraints and tweak layer.
@@ -530,6 +538,7 @@ def totalRetarget(performer_obj, enduser_obj, scene, s_frame, e_frame):
stride_bone = copyTranslation(performer_obj, enduser_obj, feetBones, root, s_frame, e_frame, scene, enduser_obj_mat)
if not advanced:
IKRetarget(performer_obj, enduser_obj, s_frame, e_frame, scene)
+ bpy.ops.object.select_name(name=stride_bone.name, extend=False)
restoreObjMat(performer_obj, enduser_obj, perf_obj_mat, enduser_obj_mat, stride_bone)
bpy.ops.object.mode_set(mode='OBJECT')
if not advanced:
diff --git a/release/scripts/startup/ui_mocap.py b/release/scripts/startup/ui_mocap.py
index dd5e6fa5d6d..19a96750e49 100644
--- a/release/scripts/startup/ui_mocap.py
+++ b/release/scripts/startup/ui_mocap.py
@@ -382,6 +382,7 @@ class ExtraToolsPanel(bpy.types.Panel):
layout.prop(settings, "blend_amount")
layout.prop(settings, "second_offset")
layout.prop_search(settings, "stick_bone", context.active_object.pose, "bones")
+ layout.operator('mocap.animstitchguess', text="Guess Settings")
layout.operator('mocap.animstitch', text="Stitch Animations")
@@ -765,6 +766,25 @@ class OBJECT_OT_AnimationStitchingButton(bpy.types.Operator):
return False
+class OBJECT_OT_GuessAnimationStitchingButton(bpy.types.Operator):
+ '''Guesses the stitch frame and second offset for animation stitch'''
+ bl_idname = "mocap.animstitchguess"
+ bl_label = "Guesses the stitch frame and second offset for animation stitch"
+
+ def execute(self, context):
+ mocap_tools.guess_anim_stitch(context, context.active_object)
+ return {"FINISHED"}
+
+ @classmethod
+ def poll(cls, context):
+ activeIsArmature = False
+ if context.active_object:
+ activeIsArmature = isinstance(context.active_object.data, bpy.types.Armature)
+ if activeIsArmature:
+ 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__)