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:
authorSybren A. Stüvel <sybren@blender.org>2020-05-01 16:33:19 +0300
committerSybren A. Stüvel <sybren@blender.org>2020-05-01 16:38:45 +0300
commitb83a8d6fc43adc6d842f096ce8eaff0a95cd7e29 (patch)
treeea226962b497ccf43a9b19a7f44cc9e7c1d5bed3 /source/blender/blenkernel
parentf651548c2e15f0e7f0ec9a7ab6b94c7e3cd08d1c (diff)
Cleanup: Animation, unify FCurve extrapolation
Previously there were two functions for FCurve extrapolation, one for before the first keyframe, and the other for after the last. After the previous cleanup made the variable names consistent, it was clear that the code was almost identical. The biggest difference was in the sign of many of the calculations, which was cancelled out by swapping `B-A` to `A-B`. This showed that the computations are actually the same, and the only remaining difference was which neighbouring handle to use in case of Bézier curves. No functional changes. # Conflicts: # source/blender/blenkernel/intern/fcurve.c
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/intern/fcurve.c69
1 files changed, 14 insertions, 55 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index f49d1adb8cd..2506c937dc5 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1415,15 +1415,17 @@ static void berekeny(float f1, float f2, float f3, float f4, float *o, int b)
/* -------------------------- */
-static float fcurve_eval_keyframes_before_first(FCurve *fcu, BezTriple *bezts, float evaltime)
+static float fcurve_eval_keyframes_extrapolate(
+ FCurve *fcu, BezTriple *bezts, float evaltime, int endpoint_offset, int direction_to_neighbor)
{
- BezTriple *endpoint_bezt = bezts; /* The first keyframe. */
- BezTriple *neighbor_bezt = endpoint_bezt + 1; /* The second keyframe. */
+ BezTriple *endpoint_bezt = bezts + endpoint_offset; /* The first/last keyframe. */
+ BezTriple *neighbor_bezt = endpoint_bezt +
+ direction_to_neighbor; /* The second (to last) keyframe. */
if (endpoint_bezt->ipo == BEZT_IPO_CONST || fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT ||
(fcu->flag & FCURVE_DISCRETE_VALUES) != 0) {
- /* Constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, so just extend first
- * keyframe's value. */
+ /* Constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, so just extend the
+ * endpoint's value. */
return endpoint_bezt->vec[1][1];
}
@@ -1445,64 +1447,21 @@ static float fcurve_eval_keyframes_before_first(FCurve *fcu, BezTriple *bezts, f
return endpoint_bezt->vec[1][1] - (fac * dx);
}
- /* Use the first handle (earlier) of first BezTriple to calculate the gradient and thus the value
- * of the curve at evaltime. */
+ /* Use the gradient of the second handle (later) of neighbour to calculate the gradient and thus
+ * the value of the curve at evaltime */
+ int handle = direction_to_neighbor > 0 ? 0 : 2;
float dx = endpoint_bezt->vec[1][0] - evaltime;
- float fac = endpoint_bezt->vec[1][0] - endpoint_bezt->vec[0][0];
+ float fac = endpoint_bezt->vec[1][0] - endpoint_bezt->vec[handle][0];
/* Prevent division by zero. */
if (fac == 0.0f) {
return endpoint_bezt->vec[1][1];
}
- fac = (endpoint_bezt->vec[1][1] - endpoint_bezt->vec[0][1]) / fac;
+ fac = (endpoint_bezt->vec[1][1] - endpoint_bezt->vec[handle][1]) / fac;
return endpoint_bezt->vec[1][1] - (fac * dx);
}
-static float fcurve_eval_keyframes_after_last(FCurve *fcu, BezTriple *bezts, float evaltime)
-{
- BezTriple *endpoint_bezt = bezts + fcu->totvert - 1; /* The last keyframe. */
- BezTriple *neighbor_bezt = endpoint_bezt - 1; /* The second to last keyframe. */
-
- if (endpoint_bezt->ipo == BEZT_IPO_CONST || fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT ||
- (fcu->flag & FCURVE_DISCRETE_VALUES) != 0) {
- /* Constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, so just extend last
- * keyframe's value. */
- return endpoint_bezt->vec[1][1];
- }
-
- if (endpoint_bezt->ipo == BEZT_IPO_LIN) {
- /* Use the next center point instead of our own handle for linear interpolated extrapolate. */
- if (fcu->totvert == 1) {
- return endpoint_bezt->vec[1][1];
- }
-
- float dx = evaltime - endpoint_bezt->vec[1][0];
- float fac = endpoint_bezt->vec[1][0] - neighbor_bezt->vec[1][0];
-
- /* Prevent division by zero. */
- if (fac == 0.0f) {
- return endpoint_bezt->vec[1][1];
- }
-
- fac = (endpoint_bezt->vec[1][1] - neighbor_bezt->vec[1][1]) / fac;
- return endpoint_bezt->vec[1][1] + (fac * dx);
- }
-
- /* Use the gradient of the second handle (later) of last BezTriple to calculate the gradient and
- * thus the value of the curve at evaltime */
- float dx = evaltime - endpoint_bezt->vec[1][0];
- float fac = endpoint_bezt->vec[2][0] - endpoint_bezt->vec[1][0];
-
- /* Prevent division by zero. */
- if (fac == 0.0f) {
- return endpoint_bezt->vec[1][1];
- }
-
- fac = (endpoint_bezt->vec[2][1] - endpoint_bezt->vec[1][1]) / fac;
- return endpoint_bezt->vec[1][1] + (fac * dx);
-}
-
/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */
static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime)
{
@@ -1521,10 +1480,10 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
/* evaluation time at or past endpoints? */
if (prevbezt->vec[1][0] >= evaltime) {
- cvalue = fcurve_eval_keyframes_before_first(fcu, bezts, evaltime);
+ cvalue = fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, 0, +1);
}
else if (lastbezt->vec[1][0] <= evaltime) {
- cvalue = fcurve_eval_keyframes_after_last(fcu, bezts, evaltime);
+ cvalue = fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, fcu->totvert - 1, -1);
}
else {
/* evaltime occurs somewhere in the middle of the curve */