TrinityCore
Spline.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Spline.h"
19#include <sstream>
20#include <G3D/Matrix4.h>
21
22namespace Movement{
23
25{
30};
31
33{
38};
39
41{
46};
47
49{
50 //&SplineBase::InitLinear,
51 &SplineBase::InitCatmullRom, // we should use catmullrom initializer even for linear mode! (client's internal structure limitation)
55};
56
58
59using G3D::Matrix4;
60static const Matrix4 s_catmullRomCoeffs(
61 -0.5f, 1.5f, -1.5f, 0.5f,
62 1.f, -2.5f, 2.f, -0.5f,
63 -0.5f, 0.f, 0.5f, 0.f,
64 0.f, 1.f, 0.f, 0.f);
65
66static const Matrix4 s_Bezier3Coeffs(
67 -1.f, 3.f, -3.f, 1.f,
68 3.f, -6.f, 3.f, 0.f,
69 -3.f, 3.f, 0.f, 0.f,
70 1.f, 0.f, 0.f, 0.f);
71
72/* classic view:
73inline void C_Evaluate(const Vector3 *vertice, float t, const float (&matrix)[4][4], Vector3 &position)
74{
75 Vector3 tvec(t*t*t, t*t, t);
76 int i = 0;
77 double c;
78 double x = 0, y = 0, z = 0;
79 while ( i < 4 )
80 {
81 c = matrix[0][i]*tvec.x + matrix[1][i]*tvec.y + matrix[2][i]*tvec.z + matrix[3][i];
82
83 x += c * vertice->x;
84 y += c * vertice->y;
85 z += c * vertice->z;
86
87 ++i;
88 ++vertice;
89 }
90
91 position.x = x;
92 position.y = y;
93 position.z = z;
94}*/
95
96inline void C_Evaluate(Vector3 const* vertice, float t, Matrix4 const& matr, Vector3 &result)
97{
98 Vector4 tvec(t*t*t, t*t, t, 1.f);
99 Vector4 weights(tvec * matr);
100
101 result = vertice[0] * weights[0] + vertice[1] * weights[1]
102 + vertice[2] * weights[2] + vertice[3] * weights[3];
103}
104
105inline void C_Evaluate_Derivative(Vector3 const* vertice, float t, Matrix4 const& matr, Vector3 &result)
106{
107 Vector4 tvec(3.f*t*t, 2.f*t, 1.f, 0.f);
108 Vector4 weights(tvec * matr);
109
110 result = vertice[0] * weights[0] + vertice[1] * weights[1]
111 + vertice[2] * weights[2] + vertice[3] * weights[3];
112}
113
114void SplineBase::EvaluateLinear(index_type index, float u, Vector3& result) const
115{
116 ASSERT(index >= index_lo && index < index_hi);
117 result = points[index] + (points[index+1] - points[index]) * u;
118}
119
120void SplineBase::EvaluateCatmullRom( index_type index, float t, Vector3& result) const
121{
122 ASSERT(index >= index_lo && index < index_hi);
123 C_Evaluate(&points[index - 1], t, s_catmullRomCoeffs, result);
124}
125
126void SplineBase::EvaluateBezier3(index_type index, float t, Vector3& result) const
127{
128 index *= 3u;
129 ASSERT(index >= index_lo && index < index_hi);
130 C_Evaluate(&points[index], t, s_Bezier3Coeffs, result);
131}
132
133void SplineBase::EvaluateDerivativeLinear(index_type index, float, Vector3& result) const
134{
135 ASSERT(index >= index_lo && index < index_hi);
136 result = points[index+1] - points[index];
137}
138
139void SplineBase::EvaluateDerivativeCatmullRom(index_type index, float t, Vector3& result) const
140{
141 ASSERT(index >= index_lo && index < index_hi);
142 C_Evaluate_Derivative(&points[index - 1], t, s_catmullRomCoeffs, result);
143}
144
145void SplineBase::EvaluateDerivativeBezier3(index_type index, float t, Vector3& result) const
146{
147 index *= 3u;
148 ASSERT(index >= index_lo && index < index_hi);
149 C_Evaluate_Derivative(&points[index], t, s_Bezier3Coeffs, result);
150}
151
153{
154 ASSERT(index >= index_lo && index < index_hi);
155 return (points[index] - points[index+1]).length();
156}
157
159{
160 ASSERT(index >= index_lo && index < index_hi);
161
162 Vector3 curPos, nextPos;
163 const Vector3 * p = &points[index - 1];
164 curPos = nextPos = p[1];
165
166 index_type i = 1;
167 float length = 0;
168 while (i <= stepsPerSegment)
169 {
170 C_Evaluate(p, float(i) / float(stepsPerSegment), s_catmullRomCoeffs, nextPos);
171 length += (nextPos - curPos).length();
172 curPos = nextPos;
173 ++i;
174 }
175 return length;
176}
177
179{
180 index *= 3u;
181 ASSERT(index >= index_lo && index < index_hi);
182
183 Vector3 curPos, nextPos;
184 const Vector3 * p = &points[index];
185
186 C_Evaluate(p, 0.f, s_Bezier3Coeffs, nextPos);
187 curPos = nextPos;
188
189 index_type i = 1;
190 float length = 0;
191 while (i <= stepsPerSegment)
192 {
193 C_Evaluate(p, float(i) / float(stepsPerSegment), s_Bezier3Coeffs, nextPos);
194 length += (nextPos - curPos).length();
195 curPos = nextPos;
196 ++i;
197 }
198 return length;
199}
200
201void SplineBase::init_spline(const Vector3 * controls, index_type count, EvaluationMode m, float orientation)
202{
203 m_mode = m;
204 cyclic = false;
205 initialOrientation = orientation;
206
207 (this->*initializers[m_mode])(controls, count, 0);
208}
209
210void SplineBase::init_cyclic_spline(const Vector3 * controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation)
211{
212 m_mode = m;
213 cyclic = true;
214 initialOrientation = orientation;
215
216 (this->*initializers[m_mode])(controls, count, cyclic_point);
217}
218
219void SplineBase::InitLinear(Vector3 const* controls, index_type count, index_type cyclic_point)
220{
221 ASSERT(count >= 2);
222 const int real_size = count + 1;
223
224 points.resize(real_size);
225
226 memcpy(&points[0], controls, sizeof(Vector3) * count);
227
228 // first and last two indexes are space for special 'virtual points'
229 // these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
230 if (cyclic)
231 points[count] = controls[cyclic_point];
232 else
233 points[count] = controls[count-1];
234
235 index_lo = 0;
236 index_hi = cyclic ? count : (count - 1);
237}
238
239void SplineBase::InitCatmullRom(Vector3 const* controls, index_type count, index_type cyclic_point)
240{
241 const int real_size = count + (cyclic ? (1+2) : (1+1));
242
243 points.resize(real_size);
244
245 int lo_index = 1;
246 int high_index = lo_index + count - 1;
247
248 memcpy(&points[lo_index], controls, sizeof(Vector3) * count);
249
250 // first and last two indexes are space for special 'virtual points'
251 // these points are required for proper C_Evaluate and C_Evaluate_Derivative methtod work
252 if (cyclic)
253 {
254 if (cyclic_point == 0)
255 points[0] = controls[count-1];
256 else
257 points[0] = controls[0] - G3D::Vector3{ std::cos(initialOrientation), std::sin(initialOrientation), 0.0f };
258
259 points[high_index+1] = controls[cyclic_point];
260 points[high_index+2] = controls[cyclic_point+1];
261 }
262 else
263 {
264 points[0] = controls[0] - G3D::Vector3{ std::cos(initialOrientation), std::sin(initialOrientation), 0.0f };
265 points[high_index+1] = controls[count-1];
266 }
267
268 index_lo = lo_index;
269 index_hi = high_index + (cyclic ? 1 : 0);
270}
271
272void SplineBase::InitBezier3(Vector3 const* controls, index_type count, index_type /*cyclic_point*/)
273{
274 index_type c = count / 3u * 3u;
275 index_type t = c / 3u;
276
277 points.resize(c);
278 memcpy(&points[0], controls, sizeof(Vector3) * c);
279
280 index_lo = 0;
281 index_hi = t-1;
282 //mov_assert(points.size() % 3 == 0);
283}
284
285SplineBase::SplineBase(): index_lo(0), index_hi(0), m_mode(UninitializedMode), cyclic(false), initialOrientation(0.f)
286{
287}
288
289SplineBase::~SplineBase() = default;
290
292{
293 index_lo = 0;
294 index_hi = 0;
295 points.clear();
296}
297
298std::string SplineBase::ToString() const
299{
300 std::stringstream str;
301 const char * mode_str[ModesEnd] = {"Linear", "CatmullRom", "Bezier3", "Uninitialized"};
302
303 index_type count = this->points.size();
304 str << "mode: " << mode_str[mode()] << std::endl;
305 str << "points count: " << count << std::endl;
306 for (index_type i = 0; i < count; ++i)
307 str << "point " << i << " : " << points[i].toString() << std::endl;
308
309 return str.str();
310}
311
312}
#define ASSERT
Definition: Errors.h:68
float SegLengthLinear(index_type) const
Definition: Spline.cpp:152
static InitMethtod initializers[ModesEnd]
Definition: Spline.h:82
ControlArray points
Definition: Spline.h:45
void EvaluateCatmullRom(index_type, float, Vector3 &) const
Definition: Spline.cpp:120
virtual void clear()
Definition: Spline.cpp:291
void EvaluateDerivativeCatmullRom(index_type, float, Vector3 &) const
Definition: Spline.cpp:139
void EvaluateBezier3(index_type, float, Vector3 &) const
Definition: Spline.cpp:126
float SegLengthBezier3(index_type) const
Definition: Spline.cpp:178
float UninitializedSplineSegLenghtMethod(index_type) const
Definition: Spline.h:85
float SegLengthCatmullRom(index_type) const
Definition: Spline.cpp:158
float initialOrientation
Definition: Spline.h:52
void UninitializedSplineInitMethod(Vector3 const *, index_type, index_type)
Definition: Spline.h:86
void EvaluateDerivativeBezier3(index_type, float, Vector3 &) const
Definition: Spline.cpp:145
void EvaluateDerivativeLinear(index_type, float, Vector3 &) const
Definition: Spline.cpp:133
void init_cyclic_spline(const Vector3 *controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation=0.0f)
Definition: Spline.cpp:210
void init_spline(const Vector3 *controls, index_type count, EvaluationMode m, float orientation=0.0f)
Definition: Spline.cpp:201
void InitBezier3(Vector3 const *, index_type, index_type)
Definition: Spline.cpp:272
void(SplineBase::* EvaluationMethtod)(index_type, float, Vector3 &) const
Definition: Spline.h:64
void(SplineBase::* InitMethtod)(Vector3 const *, index_type, index_type)
Definition: Spline.h:81
index_type stepsPerSegment
Definition: Spline.h:58
void EvaluateLinear(index_type, float, Vector3 &) const
Definition: Spline.cpp:114
void InitLinear(Vector3 const *, index_type, index_type)
Definition: Spline.cpp:219
index_type index_hi
Definition: Spline.h:48
std::string ToString() const
Definition: Spline.cpp:298
float(SplineBase::* SegLenghtMethtod)(index_type) const
Definition: Spline.h:75
static EvaluationMethtod derivative_evaluators[ModesEnd]
Definition: Spline.h:70
static SegLenghtMethtod seglengths[ModesEnd]
Definition: Spline.h:76
void UninitializedSplineEvaluationMethod(index_type, float, Vector3 &) const
Definition: Spline.h:84
index_type index_lo
Definition: Spline.h:47
static EvaluationMethtod evaluators[ModesEnd]
Definition: Spline.h:65
EvaluationMode mode() const
Definition: Spline.h:114
void InitCatmullRom(Vector3 const *, index_type, index_type)
Definition: Spline.cpp:239
void C_Evaluate_Derivative(Vector3 const *vertice, float t, Matrix4 const &matr, Vector3 &result)
Definition: Spline.cpp:105
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)
void C_Evaluate(Vector3 const *vertice, float t, Matrix4 const &matr, Vector3 &result)
Definition: Spline.cpp:96
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)