diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2020-11-28 14:50:03 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2020-11-28 15:54:18 +0300 |
commit | c99d76773509516f1543190d422fb3be4c3021a4 (patch) | |
tree | 2fcf969757c00445e5ead14323802e127b7b6ec5 | |
parent | b3f20eed6e85249d15724543743cb049e7991622 (diff) |
Fix some naming and comments in F-Curve smoothing code.
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 37 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 9 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_curve_types.h | 12 |
3 files changed, 40 insertions, 18 deletions
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 091d542c43d..3ad94853078 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -3205,7 +3205,7 @@ static void calchandleNurb_intern(BezTriple *bezt, const float eps = 1e-5; /* assume normal handle until we check */ - bezt->f5 = HD_AUTOTYPE_NORMAL; + bezt->auto_handle_type = HD_AUTOTYPE_NORMAL; if (bezt->h1 == 0 && bezt->h2 == 0) { return; @@ -3298,7 +3298,7 @@ static void calchandleNurb_intern(BezTriple *bezt, float ydiff2 = next->vec[1][1] - bezt->vec[1][1]; if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) { bezt->vec[0][1] = bezt->vec[1][1]; - bezt->f5 = HD_AUTOTYPE_SPECIAL; + bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL; } else { /* handles should not be beyond y coord of two others */ if (ydiff1 <= 0.0f) { @@ -3325,7 +3325,7 @@ static void calchandleNurb_intern(BezTriple *bezt, float ydiff2 = next->vec[1][1] - bezt->vec[1][1]; if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) { bezt->vec[2][1] = bezt->vec[1][1]; - bezt->f5 = HD_AUTOTYPE_SPECIAL; + bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL; } else { /* handles should not be beyond y coord of two others */ if (ydiff1 <= 0.0f) { @@ -3673,24 +3673,33 @@ static bool tridiagonal_solve_with_limits(float *a, * | | | | | | * | | | | | | * | | | | | | - * |-------t1---------t2--------- ~ --------tN-------------------> time (co 0) + * |------dx1--------dx2--------- ~ -------dxN-------------------> time (co 0) + * + * Notation: + * + * x[i], y[i] - keyframe coordinates + * h[i] - right handle y offset from y[i] + * + * dx[i] = x[i] - x[i-1] + * dy[i] = y[i] - y[i-1] + * * Mathematical basis: * * 1. Handle lengths on either side of each point are connected by a factor * ensuring continuity of the first derivative: * - * l[i] = t[i+1]/t[i] + * l[i] = dx[i+1]/dx[i] * * 2. The tridiagonal system is formed by the following equation, which is derived * by differentiating the bezier curve and specifies second derivative continuity * at every point: * - * l[i]^2 * h[i-1] + (2*l[i]+2) * h[i] + 1/l[i+1] * h[i+1] = (y[i]-y[i-1])*l[i]^2 + y[i+1]-y[i] + * l[i]^2 * h[i-1] + (2*l[i]+2) * h[i] + 1/l[i+1] * h[i+1] = dy[i]*l[i]^2 + dy[i+1] * * 3. If this point is adjacent to a manually set handle with X size not equal to 1/3 * of the horizontal interval, this equation becomes slightly more complex: * - * l[i]^2 * h[i-1] + (3*(1-R[i-1])*l[i] + 3*(1-L[i+1])) * h[i] + 1/l[i+1] * h[i+1] = (y[i]-y[i-1])*l[i]^2 + y[i+1]-y[i] + * l[i]^2 * h[i-1] + (3*(1-R[i-1])*l[i] + 3*(1-L[i+1])) * h[i] + 1/l[i+1] * h[i+1] = dy[i]*l[i]^2 + dy[i+1] * * The difference between equations amounts to this, and it's obvious that when R[i-1] * and L[i+1] are both 1/3, it becomes zero: @@ -3699,6 +3708,14 @@ static bool tridiagonal_solve_with_limits(float *a, * * 4. The equations for zero acceleration border conditions are basically the above * equation with parts omitted, so the handle size correction also applies. + * + * 5. The fully cyclic curve case is handled by eliminating one of the end points, + * and instead of border conditions connecting the curve via a set of equations: + * + * l[0] = l[N] = dx[1] / dx[N] + * dy[0] = dy[N] + * Continuity equation (item 2) for i = 0. + * Substitute h[0] for h[N] and h[N-1] for h[-1] */ /* clang-format on */ @@ -3801,8 +3818,8 @@ static void bezier_output_handle(BezTriple *bezt, bool right, float dy, bool end static bool bezier_check_solve_end_handle(BezTriple *bezt, char htype, bool end) { - return (htype == HD_VECT) || - (end && ELEM(htype, HD_AUTO, HD_AUTO_ANIM) && bezt->f5 == HD_AUTOTYPE_NORMAL); + return (htype == HD_VECT) || (end && ELEM(htype, HD_AUTO, HD_AUTO_ANIM) && + bezt->auto_handle_type == HD_AUTOTYPE_NORMAL); } static float bezier_calc_handle_adj(float hsize[2], float dx) @@ -3995,7 +4012,7 @@ static void bezier_handle_calc_smooth_fcurve( static bool is_free_auto_point(BezTriple *bezt) { - return BEZT_IS_AUTOH(bezt) && bezt->f5 == HD_AUTOTYPE_NORMAL; + return BEZT_IS_AUTOH(bezt) && bezt->auto_handle_type == HD_AUTOTYPE_NORMAL; } void BKE_nurb_handle_smooth_fcurve(BezTriple *bezt, int total, bool cyclic) diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index bcd2fe098b7..ce710e2f7d4 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1285,14 +1285,14 @@ void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag) if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) { bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1]; /* Remember that these keyframes are special, they don't need to be adjusted. */ - bezt->f5 = HD_AUTOTYPE_SPECIAL; + bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL; } } } /* Avoid total smoothing failure on duplicate keyframes (can happen during grab). */ if (prev && prev->vec[1][0] >= bezt->vec[1][0]) { - prev->f5 = bezt->f5 = HD_AUTOTYPE_SPECIAL; + prev->auto_handle_type = bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL; } /* Advance pointers for next iteration. */ @@ -1309,10 +1309,11 @@ void calchandles_fcurve_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag) } /* If cyclic extrapolation and Auto Clamp has triggered, ensure it is symmetric. */ - if (cycle && (first->f5 != HD_AUTOTYPE_NORMAL || last->f5 != HD_AUTOTYPE_NORMAL)) { + if (cycle && (first->auto_handle_type != HD_AUTOTYPE_NORMAL || + last->auto_handle_type != HD_AUTOTYPE_NORMAL)) { first->vec[0][1] = first->vec[2][1] = first->vec[1][1]; last->vec[0][1] = last->vec[2][1] = last->vec[1][1]; - first->f5 = last->f5 = HD_AUTOTYPE_SPECIAL; + first->auto_handle_type = last->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL; } /* Do a second pass for auto handle: compute the handle to have 0 acceleration step. */ diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 372cfb225fa..3bf58203bef 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -133,8 +133,8 @@ typedef struct BezTriple { /** BEZT_IPO_ELASTIC. */ float amplitude, period; - /** F5: used for auto handle to distinguish between normal handle and exception (extrema). */ - char f5; + /** Used during auto handle calculation to mark special cases (local extremes). */ + char auto_handle_type; char _pad[3]; } BezTriple; @@ -465,10 +465,14 @@ typedef enum eBezTriple_Handle { HD_ALIGN_DOUBLESIDE = 5, /* align handles, displayed both of them. used for masks */ } eBezTriple_Handle; -/* f5 (beztriple) */ +/* auto_handle_type (beztriple) */ typedef enum eBezTriple_Auto_Type { + /* Normal automatic handle that can be refined further. */ HD_AUTOTYPE_NORMAL = 0, - HD_AUTOTYPE_SPECIAL = 1, + /* Handle locked horizontal due to being an Auto Clamped local + * extreme or a curve endpoint with Constant extrapolation. + * Further smoothing is disabled. */ + HD_AUTOTYPE_LOCKED_FINAL = 1, } eBezTriple_Auto_Type; /* interpolation modes (used only for BezTriple->ipo) */ |