diff options
author | Sybren A. Stüvel <sybren@blender.org> | 2020-05-01 15:29:50 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@blender.org> | 2020-05-01 16:38:45 +0300 |
commit | 75370684fa89103c097487d5cda8390ffb6cbc8e (patch) | |
tree | fddc6fc5cb821c7a66ad57e7ca0bdd46e71eaa95 /source/blender/blenkernel/intern/fcurve.c | |
parent | b523911e860e6602cf4dc3df67a405b469f22b74 (diff) |
Cleanup: Animation, split FCurve extrapolation into separate functions
The `fcurve_eval_keyframes` consists of three parts:
- Before the first keyframe
- After the last keyframe
- Between the keyframes
This commit splits the first two parts into separate functions. This is
the first of a series of refactors, which will be committed into smaller
parts so that each is easier to follow & validate.
No functional changes.
Diffstat (limited to 'source/blender/blenkernel/intern/fcurve.c')
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 188 |
1 files changed, 110 insertions, 78 deletions
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index b07bf8c89b1..0ce5cce27dc 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1415,60 +1415,35 @@ static void berekeny(float f1, float f2, float f3, float f4, float *o, int b) /* -------------------------- */ -/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */ -static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) +static float fcurve_eval_keyframes_before_first(FCurve *fcu, BezTriple *bezts, float evaltime) { - const float eps = 1.e-8f; - BezTriple *bezt, *prevbezt, *lastbezt; - float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac; - unsigned int a; - int b; + BezTriple *bezt, *prevbezt; + float dx, fac; float cvalue = 0.0f; /* get pointers */ - a = fcu->totvert - 1; prevbezt = bezts; bezt = prevbezt + 1; - lastbezt = prevbezt + a; - /* evaluation time at or past endpoints? */ - if (prevbezt->vec[1][0] >= evaltime) { - /* before or on first keyframe */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) && - !(fcu->flag & FCURVE_DISCRETE_VALUES)) { - /* linear or bezier interpolation */ - if (prevbezt->ipo == BEZT_IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate - */ - if (fcu->totvert == 1) { - cvalue = prevbezt->vec[1][1]; - } - else { - bezt = prevbezt + 1; - dx = prevbezt->vec[1][0] - evaltime; - fac = bezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac = (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue = prevbezt->vec[1][1] - (fac * dx); - } - else { - cvalue = prevbezt->vec[1][1]; - } - } + /* before or on first keyframe */ + if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) && + !(fcu->flag & FCURVE_DISCRETE_VALUES)) { + /* linear or bezier interpolation */ + if (prevbezt->ipo == BEZT_IPO_LIN) { + /* Use the next center point instead of our own handle for + * linear interpolated extrapolate + */ + if (fcu->totvert == 1) { + cvalue = prevbezt->vec[1][1]; } else { - /* Use the first handle (earlier) of first BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ + bezt = prevbezt + 1; dx = prevbezt->vec[1][0] - evaltime; - fac = prevbezt->vec[1][0] - prevbezt->vec[0][0]; + fac = bezt->vec[1][0] - prevbezt->vec[1][0]; /* prevent division by zero */ if (fac) { - fac = (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac; + fac = (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac; cvalue = prevbezt->vec[1][1] - (fac * dx); } else { @@ -1477,49 +1452,63 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime } } else { - /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, - * so just extend first keyframe's value + /* Use the first handle (earlier) of first BezTriple to calculate the + * gradient and thus the value of the curve at evaltime */ - cvalue = prevbezt->vec[1][1]; + dx = prevbezt->vec[1][0] - evaltime; + fac = prevbezt->vec[1][0] - prevbezt->vec[0][0]; + + /* prevent division by zero */ + if (fac) { + fac = (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac; + cvalue = prevbezt->vec[1][1] - (fac * dx); + } + else { + cvalue = prevbezt->vec[1][1]; + } } } - else if (lastbezt->vec[1][0] <= evaltime) { - /* after or on last keyframe */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) && - !(fcu->flag & FCURVE_DISCRETE_VALUES)) { - /* linear or bezier interpolation */ - if (lastbezt->ipo == BEZT_IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate - */ - if (fcu->totvert == 1) { - cvalue = lastbezt->vec[1][1]; - } - else { - prevbezt = lastbezt - 1; - dx = evaltime - lastbezt->vec[1][0]; - fac = lastbezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac = (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue = lastbezt->vec[1][1] + (fac * dx); - } - else { - cvalue = lastbezt->vec[1][1]; - } - } + else { + /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, + * so just extend first keyframe's value + */ + cvalue = prevbezt->vec[1][1]; + } + + return cvalue; +} + +static float fcurve_eval_keyframes_after_last(FCurve *fcu, BezTriple *bezts, float evaltime) +{ + BezTriple *prevbezt, *lastbezt; + float dx, fac; + unsigned int a; + float cvalue = 0.0f; + + /* get pointers */ + a = fcu->totvert - 1; + prevbezt = bezts; + lastbezt = prevbezt + a; + + /* after or on last keyframe */ + if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) && + !(fcu->flag & FCURVE_DISCRETE_VALUES)) { + /* linear or bezier interpolation */ + if (lastbezt->ipo == BEZT_IPO_LIN) { + /* Use the next center point instead of our own handle for + * linear interpolated extrapolate + */ + if (fcu->totvert == 1) { + cvalue = lastbezt->vec[1][1]; } else { - /* Use the gradient of the second handle (later) of last BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ + prevbezt = lastbezt - 1; dx = evaltime - lastbezt->vec[1][0]; - fac = lastbezt->vec[2][0] - lastbezt->vec[1][0]; + fac = lastbezt->vec[1][0] - prevbezt->vec[1][0]; /* prevent division by zero */ if (fac) { - fac = (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac; + fac = (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac; cvalue = lastbezt->vec[1][1] + (fac * dx); } else { @@ -1528,13 +1517,56 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime } } else { - /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, - * so just extend last keyframe's value + /* Use the gradient of the second handle (later) of last BezTriple to calculate the + * gradient and thus the value of the curve at evaltime */ - cvalue = lastbezt->vec[1][1]; + dx = evaltime - lastbezt->vec[1][0]; + fac = lastbezt->vec[2][0] - lastbezt->vec[1][0]; + + /* prevent division by zero */ + if (fac) { + fac = (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac; + cvalue = lastbezt->vec[1][1] + (fac * dx); + } + else { + cvalue = lastbezt->vec[1][1]; + } } } else { + /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, + * so just extend last keyframe's value + */ + cvalue = lastbezt->vec[1][1]; + } + + return cvalue; +} + +/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */ +static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) +{ + const float eps = 1.e-8f; + BezTriple *bezt, *prevbezt, *lastbezt; + float v1[2], v2[2], v3[2], v4[2], opl[32]; + unsigned int a; + int b; + float cvalue = 0.0f; + + /* get pointers */ + a = fcu->totvert - 1; + prevbezt = bezts; + bezt = prevbezt + 1; + lastbezt = prevbezt + a; + + /* evaluation time at or past endpoints? */ + if (prevbezt->vec[1][0] >= evaltime) { + cvalue = fcurve_eval_keyframes_before_first(fcu, bezts, evaltime); + } + else if (lastbezt->vec[1][0] <= evaltime) { + cvalue = fcurve_eval_keyframes_after_last(fcu, bezts, evaltime); + } + else { /* evaltime occurs somewhere in the middle of the curve */ bool exact = false; |