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

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mocap/mocap_tools.py')
-rw-r--r--mocap/mocap_tools.py63
1 files changed, 35 insertions, 28 deletions
diff --git a/mocap/mocap_tools.py b/mocap/mocap_tools.py
index 91c92a98..3f910411 100644
--- a/mocap/mocap_tools.py
+++ b/mocap/mocap_tools.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
-from math import sqrt, radians
+from math import sqrt, radians, floor, ceil
import bpy
import time
from mathutils import Vector, Matrix
@@ -108,6 +108,13 @@ class dataPoint:
self.u = u
+# Helper to convert from a sampled fcurve back to editable keyframes one.
+def make_editable_fcurves(fcurves):
+ for fc in fcurves:
+ if fc.sampled_points:
+ fc.convert_to_keyframes(floor(fc.sampled_points[0].co[0]), ceil(fc.sampled_points[-1].co[0]) + 1)
+
+
#Cross Correlation Function
#http://en.wikipedia.org/wiki/Cross_correlation
#IN: curvesA, curvesB - bpy_collection/list of fcurves to analyze. Auto-Correlation is when they are the same.
@@ -233,7 +240,6 @@ def autoloop_anim():
# group_mode - boolean, indicating wether we should place bezier keyframes on the same x (frame), or optimize each individual curve.
#OUT: None. Deletes the existing curves and creates the new beziers.
def simplifyCurves(curveGroup, error, reparaError, maxIterations, group_mode):
-
#Calculates the unit tangent of point v
def unitTangent(v, data_pts):
tang = NdVector((0, 0, 0, 0, 0))
@@ -416,26 +422,17 @@ def simplifyCurves(curveGroup, error, reparaError, maxIterations, group_mode):
#Create data_pts, a list of dataPoint type, each is assigned index i, and an NdVector
def createDataPts(curveGroup, group_mode):
- data_pts = []
+ make_editable_fcurves(curveGroup if group_mode else (curveGroup,))
+
if group_mode:
print([x.data_path for x in curveGroup])
- for i in range(len(curveGroup[0].keyframe_points)):
- x = curveGroup[0].keyframe_points[i].co.x
- y1 = curveGroup[0].evaluate(i)
- y2 = curveGroup[1].evaluate(i)
- y3 = curveGroup[2].evaluate(i)
- y4 = 0
- if len(curveGroup) == 4:
- y4 = curveGroup[3].evaluate(i)
- data_pts.append(dataPoint(i, NdVector((x, y1, y2, y3, y4))))
+ comp_cos = (0,) * (4 - len(curveGroup)) # We need to add that number of null cos to get our 5D vector.
+ kframes = sorted(set(kf.co.x for fc in curveGroup for kf in fc.keyframe_points))
+ data_pts = [dataPoint(i, NdVector((fra,) + tuple(fc.evaluate(fra) for fc in curveGroup) + comp_cos))
+ for i, fra in enumerate(kframes)]
else:
- for i in range(len(curveGroup.keyframe_points)):
- x = curveGroup.keyframe_points[i].co.x
- y1 = curveGroup.keyframe_points[i].co.y
- y2 = 0
- y3 = 0
- y4 = 0
- data_pts.append(dataPoint(i, NdVector((x, y1, y2, y3, y4))))
+ data_pts = [dataPoint(i, NdVector((kf.co.x, kf.co.y, 0, 0, 0)))
+ for i, kf in enumerate(curveGroup.keyframe_points)]
return data_pts
#Recursively fit cubic beziers to the data_pts between s and e
@@ -460,8 +457,8 @@ def simplifyCurves(curveGroup, error, reparaError, maxIterations, group_mode):
else:
bez = fitSingleCubic(data_pts, s, e)
- #recalculate max error and point where it occurs
- maxError, maxErrorPt = maxErrorAmount(data_pts, bez, s, e)
+ #recalculate max error and point where it occurs
+ maxError, maxErrorPt = maxErrorAmount(data_pts, bez, s, e)
#repara wasn't enough, we need 2 beziers for this range.
#Split the bezier at point of maximum error
@@ -479,37 +476,44 @@ def simplifyCurves(curveGroup, error, reparaError, maxIterations, group_mode):
if group_mode:
for fcurve in curveGroup:
for i in range(len(fcurve.keyframe_points) - 1, 0, -1):
- fcurve.keyframe_points.remove(fcurve.keyframe_points[i])
+ fcurve.keyframe_points.remove(fcurve.keyframe_points[i], fast=True)
else:
fcurve = curveGroup
for i in range(len(fcurve.keyframe_points) - 1, 0, -1):
- fcurve.keyframe_points.remove(fcurve.keyframe_points[i])
+ fcurve.keyframe_points.remove(fcurve.keyframe_points[i], fast=True)
- #insert the calculated beziers to blender data.\
+ #insert the calculated beziers to blender data.
if group_mode:
for fullbez in beziers:
for i, fcurve in enumerate(curveGroup):
bez = [Vector((vec[0], vec[i + 1])) for vec in fullbez]
- newKey = fcurve.keyframe_points.insert(frame=bez[0].x, value=bez[0].y)
+ newKey = fcurve.keyframe_points.insert(frame=bez[0].x, value=bez[0].y, options={'FAST'})
newKey.handle_right = (bez[1].x, bez[1].y)
- newKey = fcurve.keyframe_points.insert(frame=bez[3].x, value=bez[3].y)
+ newKey = fcurve.keyframe_points.insert(frame=bez[3].x, value=bez[3].y, options={'FAST'})
newKey.handle_left = (bez[2].x, bez[2].y)
else:
for bez in beziers:
for vec in bez:
vec.resize_2d()
- newKey = fcurve.keyframe_points.insert(frame=bez[0].x, value=bez[0].y)
+ newKey = fcurve.keyframe_points.insert(frame=bez[0].x, value=bez[0].y, options={'FAST'})
newKey.handle_right = (bez[1].x, bez[1].y)
- newKey = fcurve.keyframe_points.insert(frame=bez[3].x, value=bez[3].y)
+ newKey = fcurve.keyframe_points.insert(frame=bez[3].x, value=bez[3].y, options={'FAST'})
newKey.handle_left = (bez[2].x, bez[2].y)
+ # We used fast remove/insert, time to update the curves!
+ for fcurve in (curveGroup if group_mode else (curveGroup,)):
+ fcurve.update()
+
# indices are detached from data point's frame (x) value and
# stored in the dataPoint object, represent a range
data_pts = createDataPts(curveGroup, group_mode)
+ if not data_pts:
+ return
+
s = 0 # start
e = len(data_pts) - 1 # end
@@ -517,6 +521,7 @@ def simplifyCurves(curveGroup, error, reparaError, maxIterations, group_mode):
#begin the recursive fitting algorithm.
fitCubic(data_pts, s, e)
+
#remove old Fcurves and insert the new ones
createNewCurves(curveGroup, beziers, group_mode)
@@ -607,6 +612,8 @@ def denoise(obj, fcurves):
Implementation of non-linear blur filter.
Finds spikes in the fcurve, and replaces spikes that are too big with the average of the surrounding keyframes.
"""
+ make_editable_fcurves(fcurves)
+
for fcurve in fcurves:
org_pts = fcurve.keyframe_points[:]