aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/include/vector3d.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/include/vector3d.h')
-rw-r--r--src/others/irrlicht-1.8.1/include/vector3d.h458
1 files changed, 458 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/include/vector3d.h b/src/others/irrlicht-1.8.1/include/vector3d.h
new file mode 100644
index 0000000..fd6c50d
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/include/vector3d.h
@@ -0,0 +1,458 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#ifndef __IRR_POINT_3D_H_INCLUDED__
6#define __IRR_POINT_3D_H_INCLUDED__
7
8#include "irrMath.h"
9
10namespace irr
11{
12namespace core
13{
14
15 //! 3d vector template class with lots of operators and methods.
16 /** The vector3d class is used in Irrlicht for three main purposes:
17 1) As a direction vector (most of the methods assume this).
18 2) As a position in 3d space (which is synonymous with a direction vector from the origin to this position).
19 3) To hold three Euler rotations, where X is pitch, Y is yaw and Z is roll.
20 */
21 template <class T>
22 class vector3d
23 {
24 public:
25 //! Default constructor (null vector).
26 vector3d() : X(0), Y(0), Z(0) {}
27 //! Constructor with three different values
28 vector3d(T nx, T ny, T nz) : X(nx), Y(ny), Z(nz) {}
29 //! Constructor with the same value for all elements
30 explicit vector3d(T n) : X(n), Y(n), Z(n) {}
31 //! Copy constructor
32 vector3d(const vector3d<T>& other) : X(other.X), Y(other.Y), Z(other.Z) {}
33
34 // operators
35
36 vector3d<T> operator-() const { return vector3d<T>(-X, -Y, -Z); }
37
38 vector3d<T>& operator=(const vector3d<T>& other) { X = other.X; Y = other.Y; Z = other.Z; return *this; }
39
40 vector3d<T> operator+(const vector3d<T>& other) const { return vector3d<T>(X + other.X, Y + other.Y, Z + other.Z); }
41 vector3d<T>& operator+=(const vector3d<T>& other) { X+=other.X; Y+=other.Y; Z+=other.Z; return *this; }
42 vector3d<T> operator+(const T val) const { return vector3d<T>(X + val, Y + val, Z + val); }
43 vector3d<T>& operator+=(const T val) { X+=val; Y+=val; Z+=val; return *this; }
44
45 vector3d<T> operator-(const vector3d<T>& other) const { return vector3d<T>(X - other.X, Y - other.Y, Z - other.Z); }
46 vector3d<T>& operator-=(const vector3d<T>& other) { X-=other.X; Y-=other.Y; Z-=other.Z; return *this; }
47 vector3d<T> operator-(const T val) const { return vector3d<T>(X - val, Y - val, Z - val); }
48 vector3d<T>& operator-=(const T val) { X-=val; Y-=val; Z-=val; return *this; }
49
50 vector3d<T> operator*(const vector3d<T>& other) const { return vector3d<T>(X * other.X, Y * other.Y, Z * other.Z); }
51 vector3d<T>& operator*=(const vector3d<T>& other) { X*=other.X; Y*=other.Y; Z*=other.Z; return *this; }
52 vector3d<T> operator*(const T v) const { return vector3d<T>(X * v, Y * v, Z * v); }
53 vector3d<T>& operator*=(const T v) { X*=v; Y*=v; Z*=v; return *this; }
54
55 vector3d<T> operator/(const vector3d<T>& other) const { return vector3d<T>(X / other.X, Y / other.Y, Z / other.Z); }
56 vector3d<T>& operator/=(const vector3d<T>& other) { X/=other.X; Y/=other.Y; Z/=other.Z; return *this; }
57 vector3d<T> operator/(const T v) const { T i=(T)1.0/v; return vector3d<T>(X * i, Y * i, Z * i); }
58 vector3d<T>& operator/=(const T v) { T i=(T)1.0/v; X*=i; Y*=i; Z*=i; return *this; }
59
60 //! sort in order X, Y, Z. Equality with rounding tolerance.
61 bool operator<=(const vector3d<T>&other) const
62 {
63 return (X<other.X || core::equals(X, other.X)) ||
64 (core::equals(X, other.X) && (Y<other.Y || core::equals(Y, other.Y))) ||
65 (core::equals(X, other.X) && core::equals(Y, other.Y) && (Z<other.Z || core::equals(Z, other.Z)));
66 }
67
68 //! sort in order X, Y, Z. Equality with rounding tolerance.
69 bool operator>=(const vector3d<T>&other) const
70 {
71 return (X>other.X || core::equals(X, other.X)) ||
72 (core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))) ||
73 (core::equals(X, other.X) && core::equals(Y, other.Y) && (Z>other.Z || core::equals(Z, other.Z)));
74 }
75
76 //! sort in order X, Y, Z. Difference must be above rounding tolerance.
77 bool operator<(const vector3d<T>&other) const
78 {
79 return (X<other.X && !core::equals(X, other.X)) ||
80 (core::equals(X, other.X) && Y<other.Y && !core::equals(Y, other.Y)) ||
81 (core::equals(X, other.X) && core::equals(Y, other.Y) && Z<other.Z && !core::equals(Z, other.Z));
82 }
83
84 //! sort in order X, Y, Z. Difference must be above rounding tolerance.
85 bool operator>(const vector3d<T>&other) const
86 {
87 return (X>other.X && !core::equals(X, other.X)) ||
88 (core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)) ||
89 (core::equals(X, other.X) && core::equals(Y, other.Y) && Z>other.Z && !core::equals(Z, other.Z));
90 }
91
92 //! use weak float compare
93 bool operator==(const vector3d<T>& other) const
94 {
95 return this->equals(other);
96 }
97
98 bool operator!=(const vector3d<T>& other) const
99 {
100 return !this->equals(other);
101 }
102
103 // functions
104
105 //! returns if this vector equals the other one, taking floating point rounding errors into account
106 bool equals(const vector3d<T>& other, const T tolerance = (T)ROUNDING_ERROR_f32 ) const
107 {
108 return core::equals(X, other.X, tolerance) &&
109 core::equals(Y, other.Y, tolerance) &&
110 core::equals(Z, other.Z, tolerance);
111 }
112
113 vector3d<T>& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;}
114 vector3d<T>& set(const vector3d<T>& p) {X=p.X; Y=p.Y; Z=p.Z;return *this;}
115
116 //! Get length of the vector.
117 T getLength() const { return core::squareroot( X*X + Y*Y + Z*Z ); }
118
119 //! Get squared length of the vector.
120 /** This is useful because it is much faster than getLength().
121 \return Squared length of the vector. */
122 T getLengthSQ() const { return X*X + Y*Y + Z*Z; }
123
124 //! Get the dot product with another vector.
125 T dotProduct(const vector3d<T>& other) const
126 {
127 return X*other.X + Y*other.Y + Z*other.Z;
128 }
129
130 //! Get distance from another point.
131 /** Here, the vector is interpreted as point in 3 dimensional space. */
132 T getDistanceFrom(const vector3d<T>& other) const
133 {
134 return vector3d<T>(X - other.X, Y - other.Y, Z - other.Z).getLength();
135 }
136
137 //! Returns squared distance from another point.
138 /** Here, the vector is interpreted as point in 3 dimensional space. */
139 T getDistanceFromSQ(const vector3d<T>& other) const
140 {
141 return vector3d<T>(X - other.X, Y - other.Y, Z - other.Z).getLengthSQ();
142 }
143
144 //! Calculates the cross product with another vector.
145 /** \param p Vector to multiply with.
146 \return Crossproduct of this vector with p. */
147 vector3d<T> crossProduct(const vector3d<T>& p) const
148 {
149 return vector3d<T>(Y * p.Z - Z * p.Y, Z * p.X - X * p.Z, X * p.Y - Y * p.X);
150 }
151
152 //! Returns if this vector interpreted as a point is on a line between two other points.
153 /** It is assumed that the point is on the line.
154 \param begin Beginning vector to compare between.
155 \param end Ending vector to compare between.
156 \return True if this vector is between begin and end, false if not. */
157 bool isBetweenPoints(const vector3d<T>& begin, const vector3d<T>& end) const
158 {
159 const T f = (end - begin).getLengthSQ();
160 return getDistanceFromSQ(begin) <= f &&
161 getDistanceFromSQ(end) <= f;
162 }
163
164 //! Normalizes the vector.
165 /** In case of the 0 vector the result is still 0, otherwise
166 the length of the vector will be 1.
167 \return Reference to this vector after normalization. */
168 vector3d<T>& normalize()
169 {
170 f64 length = X*X + Y*Y + Z*Z;
171 if (length == 0 ) // this check isn't an optimization but prevents getting NAN in the sqrt.
172 return *this;
173 length = core::reciprocal_squareroot(length);
174
175 X = (T)(X * length);
176 Y = (T)(Y * length);
177 Z = (T)(Z * length);
178 return *this;
179 }
180
181 //! Sets the length of the vector to a new value
182 vector3d<T>& setLength(T newlength)
183 {
184 normalize();
185 return (*this *= newlength);
186 }
187
188 //! Inverts the vector.
189 vector3d<T>& invert()
190 {
191 X *= -1;
192 Y *= -1;
193 Z *= -1;
194 return *this;
195 }
196
197 //! Rotates the vector by a specified number of degrees around the Y axis and the specified center.
198 /** \param degrees Number of degrees to rotate around the Y axis.
199 \param center The center of the rotation. */
200 void rotateXZBy(f64 degrees, const vector3d<T>& center=vector3d<T>())
201 {
202 degrees *= DEGTORAD64;
203 f64 cs = cos(degrees);
204 f64 sn = sin(degrees);
205 X -= center.X;
206 Z -= center.Z;
207 set((T)(X*cs - Z*sn), Y, (T)(X*sn + Z*cs));
208 X += center.X;
209 Z += center.Z;
210 }
211
212 //! Rotates the vector by a specified number of degrees around the Z axis and the specified center.
213 /** \param degrees: Number of degrees to rotate around the Z axis.
214 \param center: The center of the rotation. */
215 void rotateXYBy(f64 degrees, const vector3d<T>& center=vector3d<T>())
216 {
217 degrees *= DEGTORAD64;
218 f64 cs = cos(degrees);
219 f64 sn = sin(degrees);
220 X -= center.X;
221 Y -= center.Y;
222 set((T)(X*cs - Y*sn), (T)(X*sn + Y*cs), Z);
223 X += center.X;
224 Y += center.Y;
225 }
226
227 //! Rotates the vector by a specified number of degrees around the X axis and the specified center.
228 /** \param degrees: Number of degrees to rotate around the X axis.
229 \param center: The center of the rotation. */
230 void rotateYZBy(f64 degrees, const vector3d<T>& center=vector3d<T>())
231 {
232 degrees *= DEGTORAD64;
233 f64 cs = cos(degrees);
234 f64 sn = sin(degrees);
235 Z -= center.Z;
236 Y -= center.Y;
237 set(X, (T)(Y*cs - Z*sn), (T)(Y*sn + Z*cs));
238 Z += center.Z;
239 Y += center.Y;
240 }
241
242 //! Creates an interpolated vector between this vector and another vector.
243 /** \param other The other vector to interpolate with.
244 \param d Interpolation value between 0.0f (all the other vector) and 1.0f (all this vector).
245 Note that this is the opposite direction of interpolation to getInterpolated_quadratic()
246 \return An interpolated vector. This vector is not modified. */
247 vector3d<T> getInterpolated(const vector3d<T>& other, f64 d) const
248 {
249 const f64 inv = 1.0 - d;
250 return vector3d<T>((T)(other.X*inv + X*d), (T)(other.Y*inv + Y*d), (T)(other.Z*inv + Z*d));
251 }
252
253 //! Creates a quadratically interpolated vector between this and two other vectors.
254 /** \param v2 Second vector to interpolate with.
255 \param v3 Third vector to interpolate with (maximum at 1.0f)
256 \param d Interpolation value between 0.0f (all this vector) and 1.0f (all the 3rd vector).
257 Note that this is the opposite direction of interpolation to getInterpolated() and interpolate()
258 \return An interpolated vector. This vector is not modified. */
259 vector3d<T> getInterpolated_quadratic(const vector3d<T>& v2, const vector3d<T>& v3, f64 d) const
260 {
261 // this*(1-d)*(1-d) + 2 * v2 * (1-d) + v3 * d * d;
262 const f64 inv = (T) 1.0 - d;
263 const f64 mul0 = inv * inv;
264 const f64 mul1 = (T) 2.0 * d * inv;
265 const f64 mul2 = d * d;
266
267 return vector3d<T> ((T)(X * mul0 + v2.X * mul1 + v3.X * mul2),
268 (T)(Y * mul0 + v2.Y * mul1 + v3.Y * mul2),
269 (T)(Z * mul0 + v2.Z * mul1 + v3.Z * mul2));
270 }
271
272 //! Sets this vector to the linearly interpolated vector between a and b.
273 /** \param a first vector to interpolate with, maximum at 1.0f
274 \param b second vector to interpolate with, maximum at 0.0f
275 \param d Interpolation value between 0.0f (all vector b) and 1.0f (all vector a)
276 Note that this is the opposite direction of interpolation to getInterpolated_quadratic()
277 */
278 vector3d<T>& interpolate(const vector3d<T>& a, const vector3d<T>& b, f64 d)
279 {
280 X = (T)((f64)b.X + ( ( a.X - b.X ) * d ));
281 Y = (T)((f64)b.Y + ( ( a.Y - b.Y ) * d ));
282 Z = (T)((f64)b.Z + ( ( a.Z - b.Z ) * d ));
283 return *this;
284 }
285
286
287 //! Get the rotations that would make a (0,0,1) direction vector point in the same direction as this direction vector.
288 /** Thanks to Arras on the Irrlicht forums for this method. This utility method is very useful for
289 orienting scene nodes towards specific targets. For example, if this vector represents the difference
290 between two scene nodes, then applying the result of getHorizontalAngle() to one scene node will point
291 it at the other one.
292 Example code:
293 // Where target and seeker are of type ISceneNode*
294 const vector3df toTarget(target->getAbsolutePosition() - seeker->getAbsolutePosition());
295 const vector3df requiredRotation = toTarget.getHorizontalAngle();
296 seeker->setRotation(requiredRotation);
297
298 \return A rotation vector containing the X (pitch) and Y (raw) rotations (in degrees) that when applied to a
299 +Z (e.g. 0, 0, 1) direction vector would make it point in the same direction as this vector. The Z (roll) rotation
300 is always 0, since two Euler rotations are sufficient to point in any given direction. */
301 vector3d<T> getHorizontalAngle() const
302 {
303 vector3d<T> angle;
304
305 const f64 tmp = (atan2((f64)X, (f64)Z) * RADTODEG64);
306 angle.Y = (T)tmp;
307
308 if (angle.Y < 0)
309 angle.Y += 360;
310 if (angle.Y >= 360)
311 angle.Y -= 360;
312
313 const f64 z1 = core::squareroot(X*X + Z*Z);
314
315 angle.X = (T)(atan2((f64)z1, (f64)Y) * RADTODEG64 - 90.0);
316
317 if (angle.X < 0)
318 angle.X += 360;
319 if (angle.X >= 360)
320 angle.X -= 360;
321
322 return angle;
323 }
324
325 //! Get the spherical coordinate angles
326 /** This returns Euler degrees for the point represented by
327 this vector. The calculation assumes the pole at (0,1,0) and
328 returns the angles in X and Y.
329 */
330 vector3d<T> getSphericalCoordinateAngles() const
331 {
332 vector3d<T> angle;
333 const f64 length = X*X + Y*Y + Z*Z;
334
335 if (length)
336 {
337 if (X!=0)
338 {
339 angle.Y = (T)(atan2((f64)Z,(f64)X) * RADTODEG64);
340 }
341 else if (Z<0)
342 angle.Y=180;
343
344 angle.X = (T)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64);
345 }
346 return angle;
347 }
348
349 //! Builds a direction vector from (this) rotation vector.
350 /** This vector is assumed to be a rotation vector composed of 3 Euler angle rotations, in degrees.
351 The implementation performs the same calculations as using a matrix to do the rotation.
352
353 \param[in] forwards The direction representing "forwards" which will be rotated by this vector.
354 If you do not provide a direction, then the +Z axis (0, 0, 1) will be assumed to be forwards.
355 \return A direction vector calculated by rotating the forwards direction by the 3 Euler angles
356 (in degrees) represented by this vector. */
357 vector3d<T> rotationToDirection(const vector3d<T> & forwards = vector3d<T>(0, 0, 1)) const
358 {
359 const f64 cr = cos( core::DEGTORAD64 * X );
360 const f64 sr = sin( core::DEGTORAD64 * X );
361 const f64 cp = cos( core::DEGTORAD64 * Y );
362 const f64 sp = sin( core::DEGTORAD64 * Y );
363 const f64 cy = cos( core::DEGTORAD64 * Z );
364 const f64 sy = sin( core::DEGTORAD64 * Z );
365
366 const f64 srsp = sr*sp;
367 const f64 crsp = cr*sp;
368
369 const f64 pseudoMatrix[] = {
370 ( cp*cy ), ( cp*sy ), ( -sp ),
371 ( srsp*cy-cr*sy ), ( srsp*sy+cr*cy ), ( sr*cp ),
372 ( crsp*cy+sr*sy ), ( crsp*sy-sr*cy ), ( cr*cp )};
373
374 return vector3d<T>(
375 (T)(forwards.X * pseudoMatrix[0] +
376 forwards.Y * pseudoMatrix[3] +
377 forwards.Z * pseudoMatrix[6]),
378 (T)(forwards.X * pseudoMatrix[1] +
379 forwards.Y * pseudoMatrix[4] +
380 forwards.Z * pseudoMatrix[7]),
381 (T)(forwards.X * pseudoMatrix[2] +
382 forwards.Y * pseudoMatrix[5] +
383 forwards.Z * pseudoMatrix[8]));
384 }
385
386 //! Fills an array of 4 values with the vector data (usually floats).
387 /** Useful for setting in shader constants for example. The fourth value
388 will always be 0. */
389 void getAs4Values(T* array) const
390 {
391 array[0] = X;
392 array[1] = Y;
393 array[2] = Z;
394 array[3] = 0;
395 }
396
397 //! Fills an array of 3 values with the vector data (usually floats).
398 /** Useful for setting in shader constants for example.*/
399 void getAs3Values(T* array) const
400 {
401 array[0] = X;
402 array[1] = Y;
403 array[2] = Z;
404 }
405
406
407 //! X coordinate of the vector
408 T X;
409
410 //! Y coordinate of the vector
411 T Y;
412
413 //! Z coordinate of the vector
414 T Z;
415 };
416
417 //! partial specialization for integer vectors
418 // Implementor note: inline keyword needed due to template specialization for s32. Otherwise put specialization into a .cpp
419 template <>
420 inline vector3d<s32> vector3d<s32>::operator /(s32 val) const {return core::vector3d<s32>(X/val,Y/val,Z/val);}
421 template <>
422 inline vector3d<s32>& vector3d<s32>::operator /=(s32 val) {X/=val;Y/=val;Z/=val; return *this;}
423
424 template <>
425 inline vector3d<s32> vector3d<s32>::getSphericalCoordinateAngles() const
426 {
427 vector3d<s32> angle;
428 const f64 length = X*X + Y*Y + Z*Z;
429
430 if (length)
431 {
432 if (X!=0)
433 {
434 angle.Y = round32((f32)(atan2((f64)Z,(f64)X) * RADTODEG64));
435 }
436 else if (Z<0)
437 angle.Y=180;
438
439 angle.X = round32((f32)(acos(Y * core::reciprocal_squareroot(length)) * RADTODEG64));
440 }
441 return angle;
442 }
443
444 //! Typedef for a f32 3d vector.
445 typedef vector3d<f32> vector3df;
446
447 //! Typedef for an integer 3d vector.
448 typedef vector3d<s32> vector3di;
449
450 //! Function multiplying a scalar and a vector component-wise.
451 template<class S, class T>
452 vector3d<T> operator*(const S scalar, const vector3d<T>& vector) { return vector*scalar; }
453
454} // end namespace core
455} // end namespace irr
456
457#endif
458