diff options
author | Sybren A. Stüvel <sybren@blender.org> | 2020-10-05 14:16:10 +0300 |
---|---|---|
committer | Sybren A. Stüvel <sybren@blender.org> | 2020-10-05 15:26:51 +0300 |
commit | 8b72d9cc1530fb6fbd37b6a2e02aa61242f8d24a (patch) | |
tree | edd465845cef829425286888de28862e21cfc031 /source/blender/blenkernel/intern/fcurve_test.cc | |
parent | dfbf8682980ba51451ccc7d1ee4cc02497dfeec3 (diff) |
Insert keyframes while preserving shape of curve
Apply the De Casteljau algorithm to split the Bèzier curve at the X
coordinate where the new key is inserted, and uses the result to update
both the newly inserted and surrounding handles.
For curves that use Auto keyframes this has been largely addressed by
the new algorithm from D2884. This commit extends this to non-auto
handles.
This code is heavily based on D3172 by Alexander Gavrilov (@angavrilov).
Manifest Task: https://developer.blender.org/T81353
Diffstat (limited to 'source/blender/blenkernel/intern/fcurve_test.cc')
-rw-r--r-- | source/blender/blenkernel/intern/fcurve_test.cc | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/fcurve_test.cc b/source/blender/blenkernel/intern/fcurve_test.cc index a6f65a7c9b3..dd672df744b 100644 --- a/source/blender/blenkernel/intern/fcurve_test.cc +++ b/source/blender/blenkernel/intern/fcurve_test.cc @@ -210,4 +210,67 @@ TEST(evaluate_fcurve, ExtrapolationBezierKeys) BKE_fcurve_free(fcu); } +TEST(fcurve_subdivide, BKE_bezt_subdivide_handles) +{ + FCurve *fcu = BKE_fcurve_create(); + + /* Insert two keyframes and set handles to something non-default. */ + EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0); + EXPECT_EQ(insert_vert_fcurve(fcu, 13.0f, 2.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1); + + fcu->bezt[0].h1 = fcu->bezt[0].h2 = HD_FREE; + fcu->bezt[0].vec[0][0] = -5.0f; + fcu->bezt[0].vec[0][1] = 0.0f; + fcu->bezt[0].vec[2][0] = 2.0f; + fcu->bezt[0].vec[2][1] = 4.0f; + + fcu->bezt[1].h1 = fcu->bezt[1].h2 = HD_FREE; + fcu->bezt[1].vec[0][0] = 13.0f; + fcu->bezt[1].vec[0][1] = -2.0f; + fcu->bezt[1].vec[2][0] = 16.0f; + fcu->bezt[1].vec[2][1] = -3.0f; + + /* Create new keyframe point with defaults from insert_vert_fcurve(). */ + BezTriple beztr; + const float x = 7.375f; // at this X-coord, the FCurve should evaluate to 1.000f. + const float y = 1.000f; + beztr.vec[0][0] = x - 1.0f; + beztr.vec[0][1] = y; + beztr.vec[1][0] = x; + beztr.vec[1][1] = y; + beztr.vec[2][0] = x + 1.0f; + beztr.vec[2][1] = y; + beztr.h1 = beztr.h2 = HD_AUTO_ANIM; + beztr.ipo = BEZT_IPO_BEZ; + + /* This should update the existing handles as well as the new BezTriple. */ + float y_delta; + BKE_bezt_subdivide_handles(&beztr, &fcu->bezt[0], &fcu->bezt[1], &y_delta); + + EXPECT_FLOAT_EQ(y_delta, 0.0f); + + EXPECT_FLOAT_EQ(fcu->bezt[0].vec[0][0], -5.0f); // Left handle should not be touched. + EXPECT_FLOAT_EQ(fcu->bezt[0].vec[0][1], 0.0f); + EXPECT_FLOAT_EQ(fcu->bezt[0].vec[1][0], 1.0f); // Coordinates should not be touched. + EXPECT_FLOAT_EQ(fcu->bezt[0].vec[1][1], 0.0f); + EXPECT_FLOAT_EQ(fcu->bezt[0].vec[2][0], 1.5f); // Right handle should be updated. + EXPECT_FLOAT_EQ(fcu->bezt[0].vec[2][1], 2.0f); + + EXPECT_FLOAT_EQ(fcu->bezt[1].vec[0][0], 13.0f); // Left handle should be updated. + EXPECT_FLOAT_EQ(fcu->bezt[1].vec[0][1], 0.0f); + EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][0], 13.0f); // Coordinates should not be touched. + EXPECT_FLOAT_EQ(fcu->bezt[1].vec[1][1], 2.0f); + EXPECT_FLOAT_EQ(fcu->bezt[1].vec[2][0], 16.0f); // Right handle should not be touched + EXPECT_FLOAT_EQ(fcu->bezt[1].vec[2][1], -3.0f); + + EXPECT_FLOAT_EQ(beztr.vec[0][0], 4.5f); // Left handle should be updated. + EXPECT_FLOAT_EQ(beztr.vec[0][1], 1.5f); + EXPECT_FLOAT_EQ(beztr.vec[1][0], 7.375f); // Coordinates should not be touched. + EXPECT_FLOAT_EQ(beztr.vec[1][1], 1.0f); + EXPECT_FLOAT_EQ(beztr.vec[2][0], 10.250); // Right handle should be updated. + EXPECT_FLOAT_EQ(beztr.vec[2][1], 0.5); + + BKE_fcurve_free(fcu); +} + } // namespace blender::bke::tests |