[Bf-blender-cvs] [9a4844cfdb1] master: Tests: Animation, added unittests for FCurve evaluation

Sybren A. Stüvel noreply at git.blender.org
Fri May 1 12:00:27 CEST 2020


Commit: 9a4844cfdb1a4a29e1bf66b045d4e2e4a0a5dd0f
Author: Sybren A. Stüvel
Date:   Fri May 1 11:56:43 2020 +0200
Branches: master
https://developer.blender.org/rB9a4844cfdb1a4a29e1bf66b045d4e2e4a0a5dd0f

Tests: Animation, added unittests for FCurve evaluation

This introduces unittests for FCurve evaluation.

No functional changes to actual Blender code.

Differential Revision: https://developer.blender.org/D6778

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

A	tests/gtests/blenkernel/BKE_fcurve_test.cc
M	tests/gtests/blenkernel/CMakeLists.txt

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

diff --git a/tests/gtests/blenkernel/BKE_fcurve_test.cc b/tests/gtests/blenkernel/BKE_fcurve_test.cc
new file mode 100644
index 00000000000..82622f961b6
--- /dev/null
+++ b/tests/gtests/blenkernel/BKE_fcurve_test.cc
@@ -0,0 +1,210 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2020 by Blender Foundation.
+ */
+#include "testing/testing.h"
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BKE_fcurve.h"
+
+#include "ED_keyframing.h"
+
+#include "DNA_anim_types.h"
+}
+
+// Epsilon for floating point comparisons.
+static const float EPSILON = 1e-7f;
+
+TEST(evaluate_fcurve, EmptyFCurve)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+  EXPECT_EQ(evaluate_fcurve(fcu, 47.0f), 0.0f);
+  free_fcurve(fcu);
+}
+
+TEST(evaluate_fcurve, OnKeys)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+
+  insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
+  insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
+  insert_vert_fcurve(fcu, 3.0f, 19.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF);
+
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.0f), 7.0f, EPSILON);   // hits 'on or before first' function
+  EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f), 13.0f, EPSILON);  // hits 'between' function
+  EXPECT_NEAR(evaluate_fcurve(fcu, 3.0f), 19.0f, EPSILON);  // hits 'on or after last' function
+
+  /* Also test within a specific time epsilon of the keys, as this was an issue in T39207.
+   * This epsilon is just slightly smaller than the epsilon given to binarysearch_bezt_index_ex()
+   * in fcurve_eval_between_keyframes(), so it should hit the "exact" code path. */
+  float time_epsilon = 0.00008f;
+  EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f - time_epsilon), 13.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 2.0f + time_epsilon), 13.0f, EPSILON);
+
+  free_fcurve(fcu);
+}
+
+TEST(evaluate_fcurve, InterpolationConstant)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+
+  EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0);
+  EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1);
+
+  fcu->bezt[0].ipo = BEZT_IPO_CONST;
+  fcu->bezt[1].ipo = BEZT_IPO_CONST;
+
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 7.0f, EPSILON);
+
+  free_fcurve(fcu);
+}
+
+TEST(evaluate_fcurve, InterpolationLinear)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+
+  EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0);
+  EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1);
+
+  fcu->bezt[0].ipo = BEZT_IPO_LIN;
+  fcu->bezt[1].ipo = BEZT_IPO_LIN;
+
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 8.5f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 10.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 11.5f, EPSILON);
+
+  free_fcurve(fcu);
+}
+
+TEST(evaluate_fcurve, InterpolationBezier)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+
+  EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0);
+  EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1);
+
+  EXPECT_EQ(fcu->bezt[0].ipo, BEZT_IPO_BEZ);
+  EXPECT_EQ(fcu->bezt[1].ipo, BEZT_IPO_BEZ);
+
+  // Test with default handles.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.8297067f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 10.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 12.170294f, EPSILON);
+
+  // Test with modified handles.
+  fcu->bezt[0].vec[0][0] = 0.71855f;  // left handle X
+  fcu->bezt[0].vec[0][1] = 6.22482f;  // left handle Y
+  fcu->bezt[0].vec[2][0] = 1.35148f;  // right handle X
+  fcu->bezt[0].vec[2][1] = 7.96806f;  // right handle Y
+
+  fcu->bezt[1].vec[0][0] = 1.66667f;  // left handle X
+  fcu->bezt[1].vec[0][1] = 10.4136f;  // left handle Y
+  fcu->bezt[1].vec[2][0] = 2.33333f;  // right handle X
+  fcu->bezt[1].vec[2][1] = 15.5864f;  // right handle Y
+
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.25f), 7.945497f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.50f), 9.3495407f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.75f), 11.088551f, EPSILON);
+
+  free_fcurve(fcu);
+}
+
+TEST(evaluate_fcurve, InterpolationBounce)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+
+  EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0);
+  EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1);
+
+  fcu->bezt[0].ipo = BEZT_IPO_BOUNCE;
+  fcu->bezt[1].ipo = BEZT_IPO_BOUNCE;
+
+  fcu->bezt[0].easing = BEZT_IPO_EASE_IN;
+  fcu->bezt[1].easing = BEZT_IPO_EASE_AUTO;
+
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.4f), 8.3649998f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.5f), 8.4062500f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 1.8f), 11.184999f, EPSILON);
+
+  free_fcurve(fcu);
+}
+
+TEST(evaluate_fcurve, ExtrapolationLinearKeys)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+
+  EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0);
+  EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1);
+  fcu->bezt[0].ipo = BEZT_IPO_LIN;
+  fcu->bezt[1].ipo = BEZT_IPO_LIN;
+
+  fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+  // Before first keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 5.5f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 0.50f), 4.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), -8.0f, EPSILON);
+  // After last keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 17.5f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 22.0f, EPSILON);
+
+  fcu->extend = FCURVE_EXTRAPOLATE_CONSTANT;
+  // Before first keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 7.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), 7.0f, EPSILON);
+  // After last keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 13.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 13.0f, EPSILON);
+
+  free_fcurve(fcu);
+}
+
+TEST(evaluate_fcurve, ExtrapolationBezierKeys)
+{
+  FCurve *fcu = static_cast<FCurve *>(MEM_callocN(sizeof(FCurve), "FCurve"));
+
+  EXPECT_EQ(insert_vert_fcurve(fcu, 1.0f, 7.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 0);
+  EXPECT_EQ(insert_vert_fcurve(fcu, 2.0f, 13.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NO_USERPREF), 1);
+
+  fcu->bezt[0].vec[0][0] = 0.71855f;  // left handle X
+  fcu->bezt[0].vec[0][1] = 6.22482f;  // left handle Y
+  fcu->bezt[0].vec[2][0] = 1.35148f;  // right handle X
+  fcu->bezt[0].vec[2][1] = 7.96806f;  // right handle Y
+
+  fcu->bezt[1].vec[0][0] = 1.66667f;  // left handle X
+  fcu->bezt[1].vec[0][1] = 10.4136f;  // left handle Y
+  fcu->bezt[1].vec[2][0] = 2.33333f;  // right handle X
+  fcu->bezt[1].vec[2][1] = 15.5864f;  // right handle Y
+
+  fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+  // Before first keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 6.3114409f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, -0.50f), 2.8686447f, EPSILON);
+  // After last keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 18.81946f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 24.63892f, EPSILON);
+
+  fcu->extend = FCURVE_EXTRAPOLATE_CONSTANT;
+  // Before first keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 0.75f), 7.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, -1.50f), 7.0f, EPSILON);
+  // After last keyframe.
+  EXPECT_NEAR(evaluate_fcurve(fcu, 2.75f), 13.0f, EPSILON);
+  EXPECT_NEAR(evaluate_fcurve(fcu, 3.50f), 13.0f, EPSILON);
+
+  free_fcurve(fcu);
+}
diff --git a/tests/gtests/blenkernel/CMakeLists.txt b/tests/gtests/blenkernel/CMakeLists.txt
index bbc274c5ddb..017d3412d25 100644
--- a/tests/gtests/blenkernel/CMakeLists.txt
+++ b/tests/gtests/blenkernel/CMakeLists.txt
@@ -23,7 +23,9 @@ set(INC
   ..
   ../../../source/blender/blenkernel
   ../../../source/blender/blenlib
+  ../../../source/blender/editors/include
   ../../../source/blender/makesdna
+  ../../../source/blender/makesrna
   ../../../intern/guardedalloc
   ../../../intern/atomic
 )
@@ -39,3 +41,4 @@ if(WITH_BUILDINFO)
 endif()
 
 BLENDER_TEST(BKE_armature "bf_blenloader;bf_blenkernel;bf_blenlib;${BUILDINFO}")
+BLENDER_TEST(BKE_fcurve "bf_blenloader;bf_blenkernel;bf_editor_animation")



More information about the Bf-blender-cvs mailing list