1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "Testing/BsConsoleTestOutput.h"
4#include "Testing/BsTestSuite.h"
5#include "Animation/BsAnimationCurve.h"
6#include "Particles/BsParticleDistribution.h"
7
8namespace bs
9{
10 float evalPosition(float acceleration, float velocity, float time)
11 {
12 return acceleration * time * time * 0.5f + velocity * time;
13 }
14
15 float evalVelocity(float acceleration, float time)
16 {
17 return acceleration * time;
18 }
19
20 class CoreTestSuite : public TestSuite
21 {
22 public:
23 CoreTestSuite();
24
25 private:
26 void testAnimCurveIntegration();
27 void testLookupTable();
28 };
29
30 CoreTestSuite::CoreTestSuite()
31 {
32 BS_ADD_TEST(CoreTestSuite::testAnimCurveIntegration);
33 BS_ADD_TEST(CoreTestSuite::testLookupTable);
34 }
35
36 void CoreTestSuite::testAnimCurveIntegration()
37 {
38 static constexpr float EPSILON = 0.0001f;
39
40 // Construct some curves
41 TAnimationCurve<float> curveConstant(
42 {
43 TKeyframe<float>{ 1.0f, 0.0f, 0.0f, 0.0f },
44 });
45
46 TAnimationCurve<float> curveLinear(
47 {
48 TKeyframe<float>{ 0.0f, 0.0f, 1.0f, 0.0f },
49 TKeyframe<float>{ 1.0f, 1.0f, 0.0f, 1.0f }
50 });
51
52 TAnimationCurve<float> curveAcceleration(
53 {
54 TKeyframe<float>{ -9.81f, 0.0f, 0.0f, 0.0f },
55 TKeyframe<float>{ -9.81f, 0.0f, 0.0f, 10.0f }
56 });
57
58 {
59 TCurveIntegrationCache<float> cache;
60 BS_TEST_ASSERT(Math::approxEquals(curveConstant.evaluateIntegrated(0.0f, cache), 0.0f, EPSILON));
61 BS_TEST_ASSERT(Math::approxEquals(curveConstant.evaluateIntegrated(0.5f, cache), 0.5f, EPSILON));
62 BS_TEST_ASSERT(Math::approxEquals(curveConstant.evaluateIntegrated(1.0f, cache), 1.0f, EPSILON));
63 }
64
65 {
66 TCurveIntegrationCache<float> cache;
67 BS_TEST_ASSERT(Math::approxEquals(curveLinear.evaluateIntegrated(0.0f, cache), 0.0f, EPSILON));
68 BS_TEST_ASSERT(Math::approxEquals(curveLinear.evaluateIntegrated(0.5f, cache), 0.125f, EPSILON));
69 BS_TEST_ASSERT(Math::approxEquals(curveLinear.evaluateIntegrated(1.0f, cache), 0.5f, EPSILON));
70 }
71
72 {
73 TCurveIntegrationCache<float> cache;
74
75 float times[] = { 0.0f, 0.5f, 1.0f };
76 for(auto time : times)
77 {
78 BS_TEST_ASSERT(Math::approxEquals(curveConstant.evaluateIntegratedDouble(time, cache),
79 evalPosition(1.0f, 0.0f, time), EPSILON));
80 }
81 }
82
83 {
84 TCurveIntegrationCache<float> cache;
85
86 float times[] = { 0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 10.0f };
87 for(auto time : times)
88 {
89 BS_TEST_ASSERT(Math::approxEquals(curveAcceleration.evaluateIntegrated(time, cache),
90 evalVelocity(-9.81f, time), EPSILON));
91 }
92
93 std::pair<float, float> range = curveAcceleration.calculateRangeIntegrated(cache);
94 BS_TEST_ASSERT(Math::approxEquals(range.first, -98.1f, EPSILON));
95 BS_TEST_ASSERT(Math::approxEquals(range.second, 0.0f, EPSILON));
96 }
97
98 {
99 TCurveIntegrationCache<float> cache;
100
101 float times[] = { 0.0f, 0.5f, 1.0f, 2.0f, 3.0f, 5.0f, 10.0f };
102 for(auto time : times)
103 {
104 BS_TEST_ASSERT(Math::approxEquals(curveAcceleration.evaluateIntegratedDouble(time, cache),
105 evalPosition(-9.81f, 0.0f, time)));
106 }
107
108 std::pair<float, float> range = curveAcceleration.calculateRangeIntegratedDouble(cache);
109 BS_TEST_ASSERT(Math::approxEquals(range.first, -490.5f, EPSILON));
110 BS_TEST_ASSERT(Math::approxEquals(range.second, 0.0f, EPSILON));
111 }
112 }
113
114 void CoreTestSuite::testLookupTable()
115 {
116 static constexpr float EPSILON = 0.0001f;
117
118 TAnimationCurve<Vector3> curve
119 ({
120 TKeyframe<Vector3>{ Vector3(0.0f, 0.0f, 0.0f), Vector3::ZERO, Vector3::ONE, 0.0f },
121 TKeyframe<Vector3>{ Vector3(5.0f, 3.0f, 10.0f), Vector3::ONE, Vector3::ZERO, 10.0f },
122 });
123
124 Vector3Distribution dist = curve;
125 auto lookupTable = dist.toLookupTable(128);
126
127 for(UINT32 i = 0; i < 10; i++)
128 {
129 const float* left;
130 const float* right;
131 float lerp;
132
133 float t = (i / 9.0f) * 1.0f;
134 lookupTable.evaluate(t, left, right, lerp);
135
136 Vector3* leftVec = (Vector3*)left;
137 Vector3* rightVec = (Vector3*)right;
138
139 Vector3 valueLookup = Vector3::lerp(lerp, *leftVec, *rightVec);
140 Vector3 valueCurve = curve.evaluate(t);
141
142 for(UINT32 j = 0; j < 3; j++)
143 BS_TEST_ASSERT(Math::approxEquals(valueLookup[j], valueCurve[j], EPSILON));
144 }
145 }
146}
147
148using namespace bs;
149
150int main()
151{
152 SPtr<TestSuite> tests = CoreTestSuite::create<CoreTestSuite>();
153
154 ExceptionTestOutput testOutput;
155 tests->run(testOutput);
156
157 return 0;
158}