Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Spline.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Spline.h"
7#include <G3D/Matrix4.h>
8#include <sstream>
9
10namespace Movement
11{
13 {
17 (EvaluationMethtod)&SplineBase::UninitializedSpline,
18 };
19
21 {
25 (EvaluationMethtod)&SplineBase::UninitializedSpline,
26 };
27
29 {
33 (SegLenghtMethtod)&SplineBase::UninitializedSpline,
34 };
35
37 {
38 //&SplineBase::InitLinear,
39 &SplineBase::InitCatmullRom, // we should use catmullrom initializer even for linear mode! (client's internal structure limitation)
43 };
44
46
47 using G3D::Matrix4;
48 static const Matrix4 s_catmullRomCoeffs(
49 -0.5f, 1.5f, -1.5f, 0.5f,
50 1.f, -2.5f, 2.f, -0.5f,
51 -0.5f, 0.f, 0.5f, 0.f,
52 0.f, 1.f, 0.f, 0.f);
53
54 static const Matrix4 s_Bezier3Coeffs(
55 -1.f, 3.f, -3.f, 1.f,
56 3.f, -6.f, 3.f, 0.f,
57 -3.f, 3.f, 0.f, 0.f,
58 1.f, 0.f, 0.f, 0.f);
59
60 /* classic view:
61 inline void C_Evaluate(const Vector3 *vertice, float t, const float (&matrix)[4][4], Vector3 &position)
62 {
63 Vector3 tvec(t*t*t, t*t, t);
64 int i = 0;
65 double c;
66 double x = 0, y = 0, z = 0;
67 while ( i < 4 )
68 {
69 c = matrix[0][i]*tvec.x + matrix[1][i]*tvec.y + matrix[2][i]*tvec.z + matrix[3][i];
70
71 x += c * vertice->x;
72 y += c * vertice->y;
73 z += c * vertice->z;
74
75 ++i;
76 ++vertice;
77 }
78
79 position.x = x;
80 position.y = y;
81 position.z = z;
82 }*/
83
84 inline void C_Evaluate(const Vector3* vertice, float t, const Matrix4& matr, Vector3& result)
85 {
86 Vector4 tvec(t * t * t, t * t, t, 1.f);
87 Vector4 weights(tvec * matr);
88
89 result = vertice[0] * weights[0] + vertice[1] * weights[1]
90 + vertice[2] * weights[2] + vertice[3] * weights[3];
91 }
92
93 inline void C_Evaluate_Derivative(const Vector3* vertice, float t, const Matrix4& matr, Vector3& result)
94 {
95 Vector4 tvec(3.f * t * t, 2.f * t, 1.f, 0.f);
96 Vector4 weights(tvec * matr);
97
98 result = vertice[0] * weights[0] + vertice[1] * weights[1]
99 + vertice[2] * weights[2] + vertice[3] * weights[3];
100 }
101
102 void SplineBase::EvaluateLinear(index_type index, float u, Vector3& result) const
103 {
104 ASSERT(index >= index_lo && index < index_hi);
105 result = points[index] + (points[index + 1] - points[index]) * u;
106 }
107
108 void SplineBase::EvaluateCatmullRom(index_type index, float t, Vector3& result) const
109 {
110 ASSERT(index >= index_lo && index < index_hi);
111 C_Evaluate(&points[index - 1], t, s_catmullRomCoeffs, result);
112 }
113
114 void SplineBase::EvaluateBezier3(index_type index, float t, Vector3& result) const
115 {
116 index *= 3u;
117 ASSERT(index >= index_lo && index < index_hi);
118 C_Evaluate(&points[index], t, s_Bezier3Coeffs, result);
119 }
120
121 void SplineBase::EvaluateDerivativeLinear(index_type index, float, Vector3& result) const
122 {
123 ASSERT(index >= index_lo && index < index_hi);
124 result = points[index + 1] - points[index];
125 }
126
127 void SplineBase::EvaluateDerivativeCatmullRom(index_type index, float t, Vector3& result) const
128 {
129 ASSERT(index >= index_lo && index < index_hi);
130 C_Evaluate_Derivative(&points[index - 1], t, s_catmullRomCoeffs, result);
131 }
132
133 void SplineBase::EvaluateDerivativeBezier3(index_type index, float t, Vector3& result) const
134 {
135 index *= 3u;
136 ASSERT(index >= index_lo && index < index_hi);
137 C_Evaluate_Derivative(&points[index], t, s_Bezier3Coeffs, result);
138 }
139
141 {
142 ASSERT(index >= index_lo && index < index_hi);
143 return (points[index] - points[index + 1]).length();
144 }
145
147 {
148 ASSERT(index >= index_lo && index < index_hi);
149
150 Vector3 curPos, nextPos;
151 const Vector3* p = &points[index - 1];
152 curPos = nextPos = p[1];
153
154 index_type i = 1;
155 double length = 0;
156 while (i <= STEPS_PER_SEGMENT)
157 {
158 C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_catmullRomCoeffs, nextPos);
159 length += (nextPos - curPos).length();
160 curPos = nextPos;
161 ++i;
162 }
163 return length;
164 }
165
167 {
168 index *= 3u;
169 ASSERT(index >= index_lo && index < index_hi);
170
171 Vector3 curPos, nextPos;
172 const Vector3* p = &points[index];
173
174 C_Evaluate(p, 0.f, s_Bezier3Coeffs, nextPos);
175 curPos = nextPos;
176
177 index_type i = 1;
178 double length = 0;
179 while (i <= STEPS_PER_SEGMENT)
180 {
181 C_Evaluate(p, float(i) / float(STEPS_PER_SEGMENT), s_Bezier3Coeffs, nextPos);
182 length += (nextPos - curPos).length();
183 curPos = nextPos;
184 ++i;
185 }
186 return length;
187 }
188
189 void SplineBase::init_spline(const Vector3* controls, index_type count, EvaluationMode m)
190 {
191 m_mode = m;
192 cyclic = false;
193
194 (this->*initializers[m_mode])(controls, count, cyclic, 0);
195 }
196
197 void SplineBase::init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point)
198 {
199 m_mode = m;
200 cyclic = true;
201
202 (this->*initializers[m_mode])(controls, count, cyclic, cyclic_point);
203 }
204
205 void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
206 {
207 ASSERT(count >= 2);
208 const int real_size = count + 1;
209
210 points.resize(real_size);
211
212 memcpy(&points[0], controls, sizeof(Vector3) * count);
213
214 // first and last two indexes are space for special 'virtual points'
215 // these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
216 if (cyclic)
217 points[count] = controls[cyclic_point];
218 else
219 points[count] = controls[count - 1];
220
221 index_lo = 0;
222 index_hi = cyclic ? count : (count - 1);
223 }
224
225 void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
226 {
227 const int real_size = count + (cyclic ? (1 + 2) : (1 + 1));
228
229 points.resize(real_size);
230
231 int lo_index = 1;
232 int high_index = lo_index + count - 1;
233
234 memcpy(&points[lo_index], controls, sizeof(Vector3) * count);
235
236 // first and last two indexes are space for special 'virtual points'
237 // these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
238 if (cyclic)
239 {
240 if (cyclic_point == 0)
241 points[0] = controls[count - 1];
242 else
243 points[0] = controls[0].lerp(controls[1], -1);
244
245 points[high_index + 1] = controls[cyclic_point];
246 points[high_index + 2] = controls[cyclic_point + 1];
247 }
248 else
249 {
250 points[0] = controls[0].lerp(controls[1], -1);
251 points[high_index + 1] = controls[count - 1];
252 }
253
254 index_lo = lo_index;
255 index_hi = high_index + (cyclic ? 1 : 0);
256 }
257
258 void SplineBase::InitBezier3(const Vector3* controls, index_type count, bool /*cyclic*/, index_type /*cyclic_point*/)
259 {
260 index_type c = count / 3u * 3u;
261 index_type t = c / 3u;
262
263 points.resize(c);
264 memcpy(&points[0], controls, sizeof(Vector3) * c);
265
266 index_lo = 0;
267 index_hi = t - 1;
268 //mov_assert(points.size() % 3 == 0);
269 }
270
272 {
273 index_lo = 0;
274 index_hi = 0;
275 points.clear();
276 }
277
278 std::string SplineBase::ToString() const
279 {
280 std::stringstream str;
281 const char* mode_str[ModesEnd] = { "Linear", "CatmullRom", "Bezier3", "Uninitialized" };
282
283 index_type count = this->points.size();
284 str << "mode: " << mode_str[mode()] << std::endl;
285 str << "points count: " << count << std::endl;
286 for (index_type i = 0; i < count; ++i)
287 str << "point " << i << " : " << points[i].toString() << std::endl;
288
289 return str.str();
290 }
291
292}
#define ASSERT
Definition Errors.h:29
float SegLengthLinear(index_type) const
Definition Spline.cpp:140
void UninitializedSpline() const
Definition Spline.h:72
static InitMethtod initializers[ModesEnd]
Definition Spline.h:70
ControlArray points
Definition Spline.h:31
void EvaluateCatmullRom(index_type, float, Vector3 &) const
Definition Spline.cpp:108
void EvaluateDerivativeCatmullRom(index_type, float, Vector3 &) const
Definition Spline.cpp:127
void EvaluateBezier3(index_type, float, Vector3 &) const
Definition Spline.cpp:114
void(SplineBase::* InitMethtod)(const Vector3 *, index_type, bool, index_type)
Definition Spline.h:69
float SegLengthBezier3(index_type) const
Definition Spline.cpp:166
float SegLengthCatmullRom(index_type) const
Definition Spline.cpp:146
void InitLinear(const Vector3 *, index_type, bool, index_type)
Definition Spline.cpp:205
void EvaluateDerivativeBezier3(index_type, float, Vector3 &) const
Definition Spline.cpp:133
void EvaluateDerivativeLinear(index_type, float, Vector3 &) const
Definition Spline.cpp:121
void init_spline(const Vector3 *controls, index_type count, EvaluationMode m)
Definition Spline.cpp:189
void(SplineBase::* EvaluationMethtod)(index_type, float, Vector3 &) const
Definition Spline.h:52
void EvaluateLinear(index_type, float, Vector3 &) const
Definition Spline.cpp:102
index_type index_hi
Definition Spline.h:34
std::string ToString() const
Definition Spline.cpp:278
void InitBezier3(const Vector3 *, index_type, bool, index_type)
Definition Spline.cpp:258
float(SplineBase::* SegLenghtMethtod)(index_type) const
Definition Spline.h:63
void init_cyclic_spline(const Vector3 *controls, index_type count, EvaluationMode m, index_type cyclic_point)
Definition Spline.cpp:197
void InitCatmullRom(const Vector3 *, index_type, bool, index_type)
Definition Spline.cpp:225
static EvaluationMethtod derivative_evaluators[ModesEnd]
Definition Spline.h:58
static SegLenghtMethtod seglengths[ModesEnd]
Definition Spline.h:64
index_type index_lo
Definition Spline.h:33
static EvaluationMethtod evaluators[ModesEnd]
Definition Spline.h:53
EvaluationMode mode() const
Definition Spline.h:94
void C_Evaluate_Derivative(const Vector3 *vertice, float t, const Matrix4 &matr, Vector3 &result)
Definition Spline.cpp:93
void C_Evaluate(const Vector3 *vertice, float t, const Matrix4 &matr, Vector3 &result)
Definition Spline.cpp:84
static const Matrix4 s_Bezier3Coeffs(-1.f, 3.f, -3.f, 1.f, 3.f, -6.f, 3.f, 0.f, -3.f, 3.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f)
static const Matrix4 s_catmullRomCoeffs(-0.5f, 1.5f, -1.5f, 0.5f, 1.f, -2.5f, 2.f, -0.5f, -0.5f, 0.f, 0.5f, 0.f, 0.f, 1.f, 0.f, 0.f)