[Bf-blender-cvs] [b83a8d6fc43] master: Cleanup: Animation, unify FCurve extrapolation

Sybren A. Stüvel noreply at git.blender.org
Fri May 1 15:40:36 CEST 2020


Commit: b83a8d6fc43adc6d842f096ce8eaff0a95cd7e29
Author: Sybren A. Stüvel
Date:   Fri May 1 15:33:19 2020 +0200
Branches: master
https://developer.blender.org/rBb83a8d6fc43adc6d842f096ce8eaff0a95cd7e29

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

===================================================================

M	source/blender/blenkernel/intern/fcurve.c

===================================================================

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 */



More information about the Bf-blender-cvs mailing list