diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/include/vector3d.h | 458 |
1 files changed, 0 insertions, 458 deletions
diff --git a/libraries/irrlicht-1.8/include/vector3d.h b/libraries/irrlicht-1.8/include/vector3d.h deleted file mode 100644 index d582978..0000000 --- a/libraries/irrlicht-1.8/include/vector3d.h +++ /dev/null | |||
@@ -1,458 +0,0 @@ | |||
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 | |||
10 | namespace irr | ||
11 | { | ||
12 | namespace 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 | |||