1 /* Copyright 2011 Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file float3.h
16         @author Jukka Jyl�nki
17         @brief A 3D (x,y,z) ordered tuple. */
18 #pragma once
19
20 #include "../MathBuildConfig.h"
21
22 #ifdef MATH_ENABLE_STL_SUPPORT
23 #include <string>
24 #endif
25
26 #include "../MathGeoLibFwd.h"
27
28 #ifdef MATH_QT_INTEROP
29 #include <QVector3D>
30 #endif
31 #ifdef MATH_OGRE_INTEROP
32 #include <OgreVector3.h>
33 #endif
34 #ifdef MATH_BULLET_INTEROP
35 #include <LinearMath/btVector3.h>
36 #endif
37 #ifdef MATH_URHO3D_INTEROP
38 #include <Urho3D/Math/Vector3.h>
39 #endif
40 #ifdef MATH_IRRKLANG_INTEROP
41 #include <ik_vec3d.h>
42 #endif
43
44 MATH_BEGIN_NAMESPACE
45
46 /// A vector of form (x,y,z).
47 class float3
48 {
49 public:
50         enum
51         {
52                 /// Specifies the number of elements in this vector.
53                 Size = 3
54         };
55         /// The x component.
56         /** A float3 is 12 bytes in size. This element lies in the memory offsets 0-3 of this class. */
57         float x;
58         /// The y component. [similarOverload: x]
59         /** This element is packed to the memory offsets 4-7 of this class. */
60         float y;
61         /// The z component. [similarOverload: x]
62         /** This element is packed to the memory offsets 8-11 of this class. */
63         float z;
64
65         /// The default constructor does not initialize any members of this class.
66         /** This means that the values of the members x, y and z are all undefined after creating a new float3 using
67                 this default constructor. Remember to assign to them before use.
68                 @see x, y, z. */
69         float3() {}
70
71 #ifdef MATH_EXPLICIT_COPYCTORS
72         /// The float3 copy constructor.
73         /** The copy constructor is a standard default copy-ctor, but it is explicitly written to be able to automatically pick up
74                 this function for script bindings. */
75         float3(const float3 &rhs) { x = rhs.xy = rhs.yz = rhs.z; }
76 #endif
77
78         /// Constructs a new float3 with the value (x, y, z).
79         /** @see x, y, z. */
80         float3(float xfloat yfloat z);
81
82         /// Constructs a new float3 with the value (scalar, scalar, scalar).
83         /** @see x, y, z. */
84         explicit float3(float scalar);
85
86         /// Constructs a new float3 with the value (xy.x, xy.y, z).
87         float3(const float2 &xyfloat z);
88
89         /// Constructs this float3 from a C array, to the value (data[0], data[1], data[2]).
90         /** @param data An array containing three elements for x, y and z. This pointer may not be null. */
91         explicit float3(const float *data);
92
93         /// Casts this float3 to a C array.
94         /** This function does not allocate new memory or make a copy of this float3. This function simply
95                 returns a C pointer view to this data structure. Use ptr()[0] to access the x component of this float3,
96                 ptr()[1] to access y, and ptr()[2] to access the z component of this float3.
97                 @note Since the returned pointer points to this class, do not dereference the pointer after this
98                         float3 has been deleted. You should never store a copy of the returned pointer.
99                 @note This function is provided for compatibility with other APIs which require raw C pointer access
100                         to vectors. Avoid using this function in general, and instead always use the operator [] or
101                         the At() function to access the elements of this vector by index.
102                 @return A pointer to the first float element of this class. The data is contiguous in memory.
103                 @see operator [](), At(). */
104         FORCE_INLINE float *ptr() { return &x; }
105         FORCE_INLINE const float *ptr() const return &x; }
106
107         /// Accesses an element of this vector using array notation.
108         /** @param index The element to get. Pass in 0 for x, 1 for y and 2 for z.
109                 @note If you have a non-const instance of this class, you can use this notation to set the elements of
110                         this vector as well, e.g. vec[1] = 10.f; would set the y-component of this vector.
111                 @see ptr(), At(). */
112         float &operator [](int index) { return At(index); }
113         CONST_WIN32 float operator [](int index) const return At(index); }
114
115         /// Accesses an element of this vector.
116         /** @param index The element to get. Pass in 0 for x, 1 for y, and 2 for z.
117                 @note If you have a non-const instance of this class, you can use this notation to set the elements of
118                         this vector as well, e.g. vec.At(1) = 10.f; would set the y-component of this vector.
119                 @see ptr(), operator [](). */
120         float &At(int index);
121         CONST_WIN32 float At(int index) const;
122
123         /// Adds two vectors. [indexTitle: operators +,-,*,/]
124         /** This function is identical to the member function Add().
125                 @return float3(x + v.x, y + v.y, z + v.z); */
126         float3 operator +(const float3 &v) const;
127         /// Performs an unary negation of this vector. [similarOverload: operator+] [hideIndex]
128         /** This function is identical to the member function Neg().
129                 @return float3(-x, -y, -z). */
130         float3 operator -() const;
131         /// Subtracts the given vector from this vector. [similarOverload: operator+] [hideIndex]
132         /** This function is identical to the member function Sub().
133                 @return float3(x - v.x, y - v.y, z - v.z); */
134         float3 operator -(const float3 &v) const;
135         /// Multiplies this vector by a scalar. [similarOverload: operator+] [hideIndex]
136         /** This function is identical to the member function Mul().
137                 @return float3(x * scalar, y * scalar, z * scalar); */
138         float3 operator *(float scalar) const;
139         /// Divides this vector by a scalar. [similarOverload: operator+] [hideIndex]
140         /** This function is identical to the member function Div().
141                 @return float3(x / scalar, y / scalar, z / scalar); */
142         float3 operator /(float scalar) const;
143         /// Unary operator + allows this structure to be used in an expression '+x'.
144         float3 operator +() const return *this; }
145
146         /// Adds a vector to this vector, in-place. [indexTitle: operators +=,-=,*=,/=]
147         /** @return A reference to this. */
148         float3 &operator +=(const float3 &v);
149         /// Subtracts a vector from this vector, in-place. [similarOverload: operator+=] [hideIndex]
150         /** @return A reference to this. */
151         float3 &operator -=(const float3 &v);
152         /// Multiplies this vector by a scalar, in-place. [similarOverload: operator+=] [hideIndex]
153         /** @return A reference to this. */
154         float3 &operator *=(float scalar);
155         /// Divides this vector by a scalar, in-place. [similarOverload: operator+=] [hideIndex]
156         /** @return A reference to this. */
157         float3 &operator /=(float scalar);
158
159 #ifdef MATH_ENABLE_UNCOMMON_OPERATIONS
160         // In math textbooks, pointwise multiplication of vectors is not defined within a linear space.
161         // However, in programming it is often useful for e.g. modulating colors via pointwise multiplication.
162         // If you #define MATH_ENABLE_UNCOMMON_OPERATIONS, you'll get these operations upgraded to handy
163         // operator * and / notation and can use vec * vec and vec / vec. Otherwise, use the notation
164         // vec.Mul(vec) and vec.Div(vec) for pointwise notation. MATH_ENABLE_UNCOMMON_OPERATIONS also enables
165         // the operation scalar / vec.
166         float3 operator *(const float3 &vector) const return this->Mul(vector); }
167         float3 operator /(const float3 &vector) const return this->Div(vector); }
168         float3 &operator *=(const float3 &vector) { *this = this->Mul(vector); return *this; }
169         float3 &operator /=(const float3 &vector) { *this = this->Div(vector); return *this; }
170 #endif
171
172         /// Adds a vector to this vector. [IndexTitle: Add/Sub/Mul/Div]
173         /// @return (x+v.x, y+v.y, z+v.z).
174         float3 Add(const float3 &v) const return *this + v; }
175
176         /// Adds the vector (s,s,s) to this vector.
177         /// @note Mathematically, the addition of a vector and scalar is not defined in linear space structures,
178         ///      but this function is provided here for syntactical convenience.
179         /// @return (x+s, y+s, z+s).
180         float3 Add(float s) const;
181
182         /// Subtracts a vector from this vector. [similarOverload: Add] [hideIndex]
183         /// @return (x-v.x, y-v.y, z-v.z).
184         float3 Sub(const float3 &v) const return *this - v; }
185
186         /// Subtracts the vector (s,s,s) from this vector. [similarOverload: Add] [hideIndex]
187         /// @note Mathematically, the subtraction of a vector by a scalar is not defined in linear space structures,
188         ///      but this function is provided here for syntactical convenience.
189         /// @return (x-s, y-s, z-s).
190         float3 Sub(float s) const;
191
192         /// Subtracts this vector from the vector (s,s,s). [similarOverload: Add] [hideIndex]
193         /// @note Mathematically, the subtraction of a scalar by a vector is not defined in linear space structures,
194         ///      but this function is provided here for syntactical convenience.
195         /// @return (s-x, s-y, s-z).
196         float3 SubLeft(float s) const;
197
198         /// Multiplies this vector by a vector, element-wise. [similarOverload: Add] [hideIndex]
199         /// @note Mathematically, the multiplication of two vectors is not defined in linear space structures,
200         ///      but this function is provided here for syntactical convenience.
201         /// @return (x*v.x, y*v.y, z*v.z).
202         float3 Mul(const float3 &v) const;
203
204         /// Multiplies this vector by a scalar. [similarOverload: Add] [hideIndex]
205         /// @return (x*s, y*s, z*s).
206         float3 Mul(float s) const return *this * s; }
207
208         /// Divides this vector by a vector, element-wise. [similarOverload: Add] [hideIndex]
209         /// @note Mathematically, the division of two vectors is not defined in linear space structures,
210         ///      but this function is provided here for syntactical convenience.
211         /// @return (x/v.x, y/v.y, z/v.z).
212         float3 Div(const float3 &v) const;
213
214         /// Divides this vector by a scalar. [similarOverload: Add] [hideIndex]
215         /// @return (x/s, y/s, z/s).
216         float3 Div(float s) const return *this / s; }
217         
218         /// Divides the vector (s,s,s) by this vector, element-wise. [similarOverload: Add] [hideIndex]
219         /// @note Mathematically, the division of a scalar by a vector is not defined in linear space structures,
220         ///      but this function is provided here for syntactical convenience.
221         /// @return (s/x, s/y, s/z).
222         float3 DivLeft(float s) const;
223
224         /// Performs a 2D swizzled access to this vector. [indexTitle: xx/xy/xz/..]
225         /** The xy(), yz(), etc.. functions return a float2 which is a permuted selection of two elements of this float3.
226                 The xx(), yy(), zz() functions return a float2 which have the same scalar for both elements. */
227         float2 xx() const;
228         float2 xy() const///< [similarOverload: xx] [hideIndex]
229         float2 xz() const///< [similarOverload: xx] [hideIndex]
230         float2 yx() const///< [similarOverload: xx] [hideIndex]
231         float2 yy() const///< [similarOverload: xx] [hideIndex]
232         float2 yz() const///< [similarOverload: xx] [hideIndex]
233         float2 zx() const///< [similarOverload: xx] [hideIndex]
234         float2 zy() const///< [similarOverload: xx] [hideIndex]
235         float2 zz() const///< [similarOverload: xx] [hideIndex]
236
237         /// Performs a 3D swizzled access to this vector. [indexTitle: xyz/xzy/yzx/..]
238         /** Use these functions to permute or replace elements of this vector with others.
239                 @return The function abc() returns float3(a,b,c). */
240         float3 xxx() const return float3(x,x,x); }
241         float3 xxy() const return float3(x,x,y); } ///< [similarOverload: xxx] [hideIndex]
242         float3 xxz() const return float3(x,x,z); } ///< [similarOverload: xxx] [hideIndex]
243         float3 xyx() const return float3(x,y,x); } ///< [similarOverload: xxx] [hideIndex]
244         float3 xyy() const return float3(x,y,y); } ///< [similarOverload: xxx] [hideIndex]
245         float3 xyz() const return float3(x,y,z); } ///< [similarOverload: xxx] [hideIndex]
246         float3 xzx() const return float3(x,z,x); } ///< [similarOverload: xxx] [hideIndex]
247         float3 xzy() const return float3(x,z,y); } ///< [similarOverload: xxx] [hideIndex]
248         float3 xzz() const return float3(x,z,z); } ///< [similarOverload: xxx] [hideIndex]
249
250         float3 yxx() const return float3(y,x,x); } ///< [similarOverload: xxx] [hideIndex]
251         float3 yxy() const return float3(y,x,y); } ///< [similarOverload: xxx] [hideIndex]
252         float3 yxz() const return float3(y,x,z); } ///< [similarOverload: xxx] [hideIndex]
253         float3 yyx() const return float3(y,y,x); } ///< [similarOverload: xxx] [hideIndex]
254         float3 yyy() const return float3(y,y,y); } ///< [similarOverload: xxx] [hideIndex]
255         float3 yyz() const return float3(y,y,z); } ///< [similarOverload: xxx] [hideIndex]
256         float3 yzx() const return float3(y,z,x); } ///< [similarOverload: xxx] [hideIndex]
257         float3 yzy() const return float3(y,z,y); } ///< [similarOverload: xxx] [hideIndex]
258         float3 yzz() const return float3(y,z,z); } ///< [similarOverload: xxx] [hideIndex]
259
260         float3 zxx() const return float3(z,x,x); } ///< [similarOverload: xxx] [hideIndex]
261         float3 zxy() const return float3(z,x,y); } ///< [similarOverload: xxx] [hideIndex]
262         float3 zxz() const return float3(z,x,z); } ///< [similarOverload: xxx] [hideIndex]
263         float3 zyx() const return float3(z,y,x); } ///< [similarOverload: xxx] [hideIndex]
264         float3 zyy() const return float3(z,y,y); } ///< [similarOverload: xxx] [hideIndex]
265         float3 zyz() const return float3(z,y,z); } ///< [similarOverload: xxx] [hideIndex]
266         float3 zzx() const return float3(z,z,x); } ///< [similarOverload: xxx] [hideIndex]
267         float3 zzy() const return float3(z,z,y); } ///< [similarOverload: xxx] [hideIndex]
268         float3 zzz() const return float3(z,z,z); } ///< [similarOverload: xxx] [hideIndex]
269
270         /// Performs a swizzled access to this vector.
271         /** For example, Swizzled(2,1,0) return float3(z,y,x). Swizzled(2,2,2,2) returns float4(z,z,z,z).
272                 @param i Chooses the element of this vector to pick for the x value of the returned vector, in the range [0, 2].
273                 @param j Chooses the element of this vector to pick for the y value of the returned vector, in the range [0, 2].
274                 @param k Chooses the element of this vector to pick for the z value of the returned vector, in the range [0, 2].
275                 @param l Chooses the element of this vector to pick for the w value of the returned vector, in the range [0, 2]. */
276         float4 Swizzled(int i, int j, int k, int l) const;
277         float3 Swizzled(int i, int j, int k) const;
278         float2 Swizzled(int i, int j) const;
279
280         /// Generates a new float3 by filling its entries by the given scalar.
281         /** @see float3::float3(float scalar), SetFromScalar(). */
282         static MUST_USE_RESULT float3 FromScalar(float scalar);
283
284         /// Fills each entry of this float3 by the given scalar.
285         /** @see float3::float3(float scalar), FromScalar(). */
286         void SetFromScalar(float scalar);
287
288         /// Sets all elements of this vector.
289         /** @see x, y, z, At(). */
290         void Set(float xfloat yfloat z);
291
292         /// Converts the given vector represented in spherical coordinates to an euclidean float3 (x,y,z) triplet.
293         /** @param azimuth The direction, or yaw, of the vector. This function uses the convention that the X-Z plane is
294                         the 2D horizontal "map" plane, with the vector (0,0,radius) corresponding to the vector in the direction azimuth=0 and inclination=0.
295                         This value is typically in the range [-pi, pi] (, or [0, 2pi]).
296                 @param inclination The elevation, or pitch, of the vector. This function uses the convention that the +Y axis
297                         points towards up, i.e. +Y is the "Zenith direction". This value is typically in the range [-pi/2, pi/2].
298                 @param radius The magnitude of the vector. This is usually >= 0, although passing in the zero vector as radius returns (0,0,0), and passing
299                         in a negative radius mirrors the coordinate along the origin.
300                 @see FromSphericalCoordinates, ToSphericalCoordinates, ToSphericalCoordinatesNormalized. */
301         void SetFromSphericalCoordinates(float azimuth, float inclination, float radius);
302         void SetFromSphericalCoordinates(const float3 &spherical) { SetFromSphericalCoordinates(spherical.x, spherical.y, spherical.z); }
303         static MUST_USE_RESULT float3 FromSphericalCoordinates(float azimuth, float inclination, float radius);
304         static MUST_USE_RESULT float3 FromSphericalCoordinates(const float3 &spherical) { return FromSphericalCoordinates(spherical.x, spherical.y, spherical.z); }
305
306         /// Identical to SetFromSphericalCoordinates(azimuth, inclination, radius), except this function sets radius == 1 to generate a normalized
307         /// vector on the unit sphere.
308         /** @see FromSphericalCoordinates, ToSphericalCoordinates, ToSphericalCoordinatesNormalized. */
309         void SetFromSphericalCoordinates(float azimuth, float inclination);
310         static MUST_USE_RESULT float3 FromSphericalCoordinates(float azimuth, float inclination);
311
312         /// @return float4(x,y,z,1).
313         /** @see x, y, z, class float4, ToDir4(). */
314         float4 ToPos4() const;
315
316         /// @return float4(x,y,z,0). [similarOverload: ToPos4]
317         /** @see x, y, z, class float4, ToPos4(). */
318         float4 ToDir4() const;
319
320         /// Converts this euclidean (x,y,z) float3 to spherical coordinates representation in the form (azimuth, inclination, radius).
321         /** @note This corresponds to the matrix operation R_y * R_x * (0,0,radius), where R_y is a rotation about the y-axis by azimuth,
322                         and R_x is a rotation about the x-axis by inclination.
323                 @note It is valid for the magnitude of this vector to be (very close to) zero, in which case the return value is the zero vector.
324                 @see FromSphericalCoordinates, SetFromSphericalCoordinates, ToSphericalCoordinatesNormalized. */
325         float3 ToSphericalCoordinates() const;
326
327         /// Converts this normalized euclidean (x,y,z) float3 to spherical coordinates representation in the form (azimuth, inclination)
328         /** @note This function requires that this float3 is normalized. This function is identical to ToSphericalCoordinates, but is slightly
329                         faster in the case this vector is known to be normalized in advance.
330                 @note This corresponsds to the matrix operation R_y * R_x * (0,0,radius), where R_y is a rotation about the y-axis by azimuth,
331                         and R_x is a rotation about the x-axis by inclination.
332                 @see ToSphericalCoordinates, FromSphericalCoordinates, SetFromSphericalCoordinates. */
333         float2 ToSphericalCoordinatesNormalized() const;
334
335         /// Computes the length of this vector.
336         /** @return Sqrt(x*x + y*y + z*z).
337                 @see LengthSq(), Distance(), DistanceSq(). */
338         float Length() const;
339
340         /// Computes the squared length of this vector.
341         /** Calling this function is faster than calling Length(), since this function avoids computing a square root.
342                 If you only need to compare lengths to each other, but are not interested in the actual length values,
343                 you can compare by using LengthSq(), instead of Length(), since Sqrt() is an order-preserving
344                 (monotonous and non-decreasing) function.
345                 @return x*x + y*y + z*z.
346                 @see LengthSq(), Distance(), DistanceSq(). */
347         float LengthSq() const;
348
349         /// Normalizes this float3.
350         /** In the case of failure, this vector is set to (1, 0, 0), so calling this function will never result in an
351                 unnormalized vector.
352                 @note If this function fails to normalize the vector, no error message is printed, the vector is set to (1,0,0) and
353                         an error code 0 is returned. This is different than the behavior of the Normalized() function, which prints an
354                         error if normalization fails.
355                 @note This function operates in-place.
356                 @return The old length of this vector, or 0 if normalization failed.
357                 @see Normalized(). */
358         float Normalize();
359
360         /// Returns a normalized copy of this vector.
361         /** @note If the vector is zero and cannot be normalized, the vector (1, 0, 0) is returned, and an error message is printed.
362                         If you do not want to generate an error message on failure, but want to handle the failure yourself, use the
363                         Normalize() function instead.
364                 @see Normalize(). */
365         float3 Normalized() const;
366
367         /// Scales this vector so that its new length is as given.
368         /** Calling this function is effectively the same as normalizing the vector first and then multiplying by newLength.
369                 In the case of failure, this vector is set to (newLength, 0, 0), so calling this function will never result in an
370                 unnormalized vector.
371                 @note This function operates in-place.
372                 @return The old length of this vector. If this function returns 0, the scaling failed, and this vector is arbitrarily
373                         reset to (newLength, 0, 0). In case of failure, no error message is generated. You are expected to handle the failure
374                         yourself.
375                 @see ScaledToLength(). */
376         float ScaleToLength(float newLength);
377
378         /// Returns a scaled copy of this vector which has its new length as given.
379         /** This function assumes the length of this vector is not zero. In the case of failure, an error message is printed,
380                 and the vector (newLength, 0, 0) is returned.
381                 @see ScaleToLength(). */
382         float3 ScaledToLength(float newLength) const;
383
384         /// Tests if the length of this vector is one, up to the given epsilon.
385         /** @see IsZero(), IsFinite(), IsPerpendicular(). */
386         bool IsNormalized(float epsilonSq = 1e-5f) const;
387
388         /// Tests if this is the null vector, up to the given epsilon.
389         /** @see IsNormalized(), IsFinite(), IsPerpendicular(). */
390         bool IsZero(float epsilonSq = 1e-7f) const;
391
392         /// Tests if this vector contains valid finite elements.
393         /** @see IsNormalized(), IsZero(), IsPerpendicular(). */
394         bool IsFinite() const;
395
396         /// Tests if two vectors are perpendicular to each other.
397         /** @see IsNormalized(), IsZero(), IsPerpendicular(), Equals(). */
398         bool IsPerpendicular(const float3 &other, float epsilonSq = 1e-8f) const;
399
400         /// Tests if the points p1, p2 and p3 lie on a straight line, up to the given epsilon.
401         /** @see AreOrthogonal(), AreOrthonormal(), Line::AreCollinear(). */
402         static MUST_USE_RESULT bool AreCollinear(const float3 &p1, const float3 &p2, const float3 &p3, float epsilonSq = 1e-7f);
403
404         /// Tests if two vectors are equal, up to the given epsilon.
405         /** @see IsPerpendicular(). */
406         bool Equals(const float3 &other, float epsilon = 1e-3f) const;
407         bool Equals(float xfloat yfloat zfloat epsilon = 1e-3f) const;
408
409         /// Compares whether this float3 and the given float3 are identical bit-by-bit in the underlying representation.
410         /** @note Prefer using this over e.g. memcmp, since there can be SSE-related padding in the structures. */
411         bool BitEquals(const float3 &other) const;
412
413 #ifdef MATH_ENABLE_STL_SUPPORT
414         /// Returns "(x, y, z)".
415         std::string ToString() const;
416
417         /// Returns "x,y,z". This is the preferred format for the float3 if it has to be serialized to a string for machine transfer.
418         std::string SerializeToString() const;
419
420         /// Returns a string of C++ code that can be used to construct this object. Useful for generating test cases from badly behaving objects.
421         std::string SerializeToCodeString() const;
422 #endif
423
424         /// Parses a string that is of form "x,y,z" or "(x,y,z)" or "(x;y;z)" or "x y z" to a new float3.
425         static MUST_USE_RESULT float3 FromString(const char *str, const char **outEndStr = 0);
426 #ifdef MATH_ENABLE_STL_SUPPORT
427         static MUST_USE_RESULT float3 FromString(const std::string &str) { return FromString(str.c_str()); }
428 #endif
429
430         /// @return x + y + z.
431         float SumOfElements() const;
432         /// @return x * y * z.
433         float ProductOfElements() const;
434         /// @return (x+y+z)/3.
435         float AverageOfElements() const;
436         /// @return Min(x, y, z).
437         /** @see MinElementIndex(). */
438         float MinElement() const;
439         /// Returns the index that has the smallest value in this vector.
440         /** @see MinElement(). */
441         int MinElementIndex() const;
442         /// @return Max(x, y, z).
443         /** @see MaxElementIndex(). */
444         float MaxElement() const;
445         /// Returns the index that has the smallest value in this vector.
446         /** @see MaxElement(). */
447         int MaxElementIndex() const;
448         /// Takes the element-wise absolute value of this vector.
449         /** @return float3(|x|, |y|, |z|).
450                 @see Neg(). */
451         float3 Abs() const;
452         /// Returns a copy of this vector with each element negated.
453         /** This function returns a new vector where each element x of the original vector is replaced by the value -x.
454                 @return float3(-x, -y, -z).
455                 @see Abs(). */
456         float3 Neg() const;
457         /// Computes the element-wise reciprocal of this vector.
458         /** This function returns a new vector where each element x of the original vector is replaced by the value 1/x.
459                 @return float3(1/x, 1/y, 1/z). */
460         float3 Recip() const;
461         /// Returns an element-wise minimum of this and the vector (ceil, ceil, ceil).
462         /** Each element that is larger than ceil is replaced by ceil. */
463         float3 Min(float ceil) const;
464         /// Returns an element-wise minimum of this and the given vector.
465         /** Each element that is larger than ceil is replaced by ceil.
466                 @see Max(), Clamp(). */
467         float3 Min(const float3 &ceil) const;
468         /// Returns an element-wise maximum of this and the vector (floor, floor, floor).
469         /** Each element that is smaller than floor is replaced by floor. */
470         float3 Max(float floor) const;
471         /// Returns an element-wise maximum of this and the given vector.
472         /** Each element that is smaller than floor is replaced by floor.
473                 @see Min(), Clamp(). */
474         float3 Max(const float3 &floor) const;
475         /// Returns a vector that has floor <= this[i] <= ceil for each element.
476         float3 Clamp(float floor, float ceil) const;
477         /// Limits each element of this vector between the corresponding elements in floor and ceil.
478         /** @see Min(), Max(), Clamp01(), ClampLength(). */
479         float3 Clamp(const float3 &floor, const float3 &ceil) const;
480         /// Limits each element of this vector in the range [0, 1].
481         /** @see Min(), Max(), Clamp(), ClampLength(). */
482         float3 Clamp01() const;
483
484         /// Returns a copy of this vector, with its length scaled down to maxLength.
485         /** @see Clamp(). */
486         float3 ClampLength(float maxLength) const;
487         /// Returns a copy of this vector, with its length scaled between minLength and maxLength.
488         /** @see Clamp(). */
489         float3 ClampLength(float minLength, float maxLength) const;
490                                 
491         /// Computes the distance between this point and the given object.
492         /** This function finds the nearest point to this point on the given object, and computes its distance
493                 to this point.
494                 If this point lies inside the given object, a distance of 0 is returned.
495                 @todo Add float3::Distance(Polygon/Circle/Disc/Frustum/Polyhedron).
496                 @see DistanceSq(), Length(), LengthSq(). */
497         float Distance(const float3 &point) const;
498         float Distance(const Line &line) const;
499         float Distance(const Ray &ray) const;
500         float Distance(const LineSegment &lineSegment) const;
501         float Distance(const Plane &plane) const;
502         float Distance(const Triangle &triangle) const;
503         float Distance(const AABB &aabb) const;
504         float Distance(const OBB &obb) const;
505         float Distance(const Sphere &sphere) const;
506         float Distance(const Capsule &capsule) const;
507
508         /// Computes the squared distance between this and the given point.
509         /** Calling this function is faster than calling Distance(), since this function avoids computing a square root.
510                 If you only need to compare distances to each other, but are not interested in the actual distance values,
511                 you can compare by using DistanceSq(), instead of Distance(), since Sqrt() is an order-preserving
512                 (monotonous and non-decreasing) function.
513                 @see Distance(), Length(), LengthSq(). */
514         float DistanceSq(const float3 &point) const;
515
516         /// Computes the dot product of this and the given vector.
517         /** The dot product has a geometric interpretation of measuring how close two direction vectors are to pointing
518                 in the same direction, computing angles between vectors, or the length of a projection of one vector to another.
519                 @return x*v.x + y*v.y + z*v.z.
520                 @see AngleBetween(), ProjectTo(), ProjectToNorm(), Cross(), OuterProduct(), ScalarTripleProduct(). */
521         float Dot(const float3 &v) const;
522
523         /// Computes the cross product of this and the given vector.
524         /** Unless this vector and the given vector are linearly dependent, the cross product returns a vector that is perpendicular
525                 to both vectors.
526                 @return float3(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x).
527                 @see Dot(), OuterProduct(), Perpendicular(), AnotherPerpendicular(), ScalarTripleProduct(). */
528         float3 Cross(const float3 &v) const;
529
530         /// Computes the outer product of this and the given vector.
531         /** @see Dot(), Cross(). */
532         float3x3 OuterProduct(const float3 &rhs) const;
533
534         /// Computes a new normalized direction vector that is perpendicular to this vector and the specified hint vector.
535         /** If this vector points toward the hint vector, the vector hint2 is returned instead.
536                 @see AnotherPerpendicular(), Cross(). */
537         float3 Perpendicular(const float3 &hint = float3(0,1,0), const float3 &hint2 = float3(0,0,1)) const;
538
539         /// Returns another vector that is perpendicular to this vector and the vector returned by Perpendicular().
540         /** The set (this, Perpendicular(), AnotherPerpendicular()) forms a right-handed normalized 3D basis.
541                 @see Perpendicular(), Cross(). */
542         float3 AnotherPerpendicular(const float3 &hint = float3(0,1,0), const float3 &hint2 = float3(0,0,1)) const;
543
544         // Completes this vector to generate a perpendicular basis.
545         /** This function computes two new vectors b and c which are both orthogonal to this vector and to each other.
546                 That is, the set { this, b, c} is an orthogonal set. The vectors b and c that are outputted are also normalized.
547                 @param outB [out] Receives vector b.
548                 @param outC [out] Receives vector c.
549                 @note When calling this function, this vector should not be zero! */
550         void PerpendicularBasis(float3 &outB, float3 &outC) const;
551
552         /// Generates a random vector that is perpendicular to this vector.
553         /** The distribution is uniformly random. */
554         float3 RandomPerpendicular(LCG &rng) const;
555
556         /// Computes the scalar triple product of the given three vectors.
557         /** @return [u v w] = (u x v) . w = u . (v x w)
558                 @see Dot(), Cross(). */
559         static MUST_USE_RESULT float ScalarTripleProduct(const float3 &u, const float3 &v, const float3 &w);
560
561         /// Returns this vector reflected about a plane with the given normal.
562         /** By convention, both this and the reflected vector point away from the plane with the given normal
563                 @see Refract(). */
564         float3 Reflect(const float3 &normal) const;
565
566         /// Refracts this vector about a plane with the given normal.
567         /** By convention, the this vector points towards the plane, and the returned vector points away from the plane.
568                 When the ray is going from a denser material to a lighter one, total internal reflection can occur.
569                 In this case, this function will just return a reflected vector from a call to Reflect().
570                 @param normal Specifies the plane normal direction
571                 @param negativeSideRefractionIndex The refraction index of the material we are exiting.
572                 @param positiveSideRefractionIndex The refraction index of the material we are entering.
573                 @see Reflect(). */
574         float3 Refract(const float3 &normal, float negativeSideRefractionIndex, float positiveSideRefractionIndex) const;
575
576         /// Projects this vector onto the given unnormalized direction vector.
577         /** @param direction The direction vector to project this vector onto. This function will normalize this
578                         vector, so you can pass in an unnormalized vector.
579                 @see ProjectToNorm(). */
580         float3 ProjectTo(const float3 &direction) const;
581
582         /// Projects this vector onto the given normalized direction vector.
583         /** @param direction The vector to project onto. This vector must be normalized.
584                 @see ProjectTo(). */
585         float3 ProjectToNorm(const float3 &direction) const;
586
587         /// Returns the angle between this vector and the specified vector, in radians.
588         /** @note This function takes into account that this vector or the other vector can be unnormalized, and normalizes the computations.
589                         If you are computing the angle between two normalized vectors, it is better to use AngleBetweenNorm().
590                 @see AngleBetweenNorm(). */             
591         float AngleBetween(const float3 &other) const;
592
593         /// Returns the angle between this vector and the specified normalized vector, in radians.
594         /** @param normalizedVector The direction vector to compute the angle against. This vector must be normalized.
595                 @note This vector must be normalized to call this function.
596                 @see AngleBetween(). */
597         float AngleBetweenNorm(const float3 &normalizedVector) const;
598
599         /// Breaks this vector down into parallel and perpendicular components with respect to the given direction.
600         /** @param direction The direction the decomposition is to be computed. This vector must be normalized.
601                 @param outParallel [out] Receives the part of this vector that is parallel to the given direction vector.
602                 @param outPerpendicular [out] Receives the part of this vector that is perpendicular to the given direction vector. */
603         void Decompose(const float3 &direction, float3 &outParallel, float3 &outPerpendicular) const;
604
605         /// Linearly interpolates between this and the vector b.
606         /** @param b The target endpoint to lerp towards to.
607                 @param t The interpolation weight, in the range [0, 1].
608                 @return Lerp(b, 0) returns this vector, Lerp(b, 1) returns the vector b.
609                         Lerp(b, 0.5) returns the vector half-way in between the two vectors, and so on.
610                         Lerp(b, t) returns (1-t)*this + t*b. */
611         float3 Lerp(const float3 &b, float t) const;
612         /// This function is the same as calling a.Lerp(b, t).
613         static MUST_USE_RESULT float3 Lerp(const float3 &a, const float3 &b, float t);
614
615         /// Makes the given vectors linearly independent.
616         /** This function directly follows the Gram-Schmidt procedure on the input vectors.
617                 The vector a is kept unmodified, and vector b is modified to be perpendicular to a.
618                 Finally, if specified, the vector c is adjusted to be perpendicular to a and b.
619                 @note If any of the input vectors is zero, then the resulting set of vectors cannot be made orthogonal.
620                 @see AreOrthogonal(), Orthonormalize(), AreOrthonormal(). */
621         static void Orthogonalize(const float3 &a, float3 &b);
622         static void Orthogonalize(const float3 &a, float3 &b, float3 &c);
623
624         /// Returns true if the given vectors are orthogonal to each other.
625         /** @see Orthogonalize(), Orthonormalize(), AreOrthonormal(), AreCollinear(). */
626         static MUST_USE_RESULT bool AreOrthogonal(const float3 &a, const float3 &b, float epsilon = 1e-3f);
627         static MUST_USE_RESULT bool AreOrthogonal(const float3 &a, const float3 &b, const float3 &c, float epsilon = 1e-3f);
628
629         /// Makes the given vectors linearly independent and normalized in length.
630         /** This function directly follows the Gram-Schmidt procedure on the input vectors.
631                 The vector a is first normalized, and vector b is modified to be perpendicular to a, and also normalized.
632                 Finally, if specified, the vector c is adjusted to be perpendicular to a and b, and normalized.
633                 @note If any of the input vectors is zero, then the resulting set of vectors cannot be made orthonormal.
634                 @see Orthogonalize(), AreOrthogonal(), AreOrthonormal(). */
635         static void Orthonormalize(float3 &a, float3 &b);
636         static void Orthonormalize(float3 &a, float3 &b, float3 &c);
637
638         /// Returns true if the given vectors are orthogonal to each other and all of length 1.
639         /** @see Orthogonalize(), AreOrthogonal(), Orthonormalize(), AreCollinear(). */
640         static MUST_USE_RESULT bool AreOrthonormal(const float3 &a, const float3 &b, float epsilon = 1e-3f);
641         static MUST_USE_RESULT bool AreOrthonormal(const float3 &a, const float3 &b, const float3 &c, float epsilon = 1e-3f);
642
643         /// Generates a direction vector of the given length.
644         /** The returned vector points at a uniformly random direction.
645                 @see RandomSphere(), RandomBox(). */
646         static MUST_USE_RESULT float3 RandomDir(LCG &lcg, float length = 1.f);
647         /// Generates a random point inside a sphere.
648         /** The returned point is generated uniformly inside the sphere.
649                 @see RandomDir(), RandomBox(). */
650         static MUST_USE_RESULT float3 RandomSphere(LCG &lcg, const float3 &center, float radius);
651         /// Generates a random point inside an axis-aligned box.
652         /** The returned point is generated uniformly inside the box.
653                 @see RandomDir(), RandomSphere(). */
654         static MUST_USE_RESULT float3 RandomBox(LCG &lcg, float xmin, float xmax, float ymin, float ymax, float zmin, float zmax);
655         static MUST_USE_RESULT float3 RandomBox(LCG &lcg, const float3 &minValues, const float3 &maxValues);
656
657         /// Returns a random float3 with each entry randomized between the range [minElem, maxElem].
658         static MUST_USE_RESULT float3 RandomBox(LCG &lcg, float minElem, float maxElem);
659
660         // Identical to RandomBox, but provided for generic API between float3 and float4 in templates.
661         static inline float3 RandomGeneral(LCG &lcg, float minElem, float maxElem) { return RandomBox(lcg, minElem, maxElem); }
662
663         /// Specifies a compile-time constant float3 with value (0, 0, 0).
664         /** @note Due to static data initialization order being undefined in C++, do NOT use this
665                         member to initialize other static data in other compilation units! */
666         static const float3 zero;
667         /// Specifies a compile-time constant float3 with value (1, 1, 1). [similarOverload: zero]
668         /** @note Due to static data initialization order being undefined in C++, do NOT use this
669                         member to initialize other static data in other compilation units! */
670         static const float3 one;
671         /// Specifies a compile-time constant float3 with value (1, 0, 0).
672         /** @note Due to static data initialization order being undefined in C++, do NOT use this
673                         member to initialize other static data in other compilation units! */
674         static const float3 unitX;
675         /// Specifies a compile-time constant float3 with value (0, 1, 0). [similarOverload: unitX]
676         /** @note Due to static data initialization order being undefined in C++, do NOT use this
677                         member to initialize other static data in other compilation units! */
678         static const float3 unitY;
679         /// Specifies a compile-time constant float3 with value (0, 0, 1). [similarOverload: unitX]
680         /** @note Due to static data initialization order being undefined in C++, do NOT use this
681                         member to initialize other static data in other compilation units! */
682         static const float3 unitZ;
683         /// A compile-time constant float3 with value (NaN, NaN, NaN).
684         /** For this constant, each element has the value of quiet NaN, or Not-A-Number.
685                 @note Never compare a float3 to this value! Due to how IEEE floats work, "nan == nan" returns false!
686                           That is, nothing is equal to NaN, not even NaN itself!
687                 @note Due to static data initialization order being undefined in C++, do NOT use this
688                         member to initialize other static data in other compilation units! */
689         static const float3 nan;
690         /// A compile-time constant float3 with value (+infinity, +infinity, +infinity). [similarOverload: nan]
691         /** @note Due to static data initialization order being undefined in C++, do NOT use this
692                         member to initialize other static data in other compilation units! */
693         static const float3 inf;
694
695 #ifdef MATH_OGRE_INTEROP
696         float3(const Ogre::Vector3 &other):x(other.x), y(other.y), z(other.z) {}
697         operator Ogre::Vector3() const return Ogre::Vector3(xyz); }
698 #endif
699 #ifdef MATH_QT_INTEROP
700         float3(const QVector3D &other):x(other.x()), y(other.y()), z(other.z()) {}
701         operator QVector3D() const return QVector3D(xyz); }
702         operator QString() const return "float3(" + QString::number(x) + "," + QString::number(y) + "," + QString::number(z) + ")"; }
703         QString toString() const return (QString)*this; }
704         QVector3D ToQVector3D() const return QVector3D(xyz); }
705         static float3 FromQVector3D(const QVector3D &v) { return (float3)v; }
706         static float3 FromString(const QString &str) { return FromString(str.toStdString()); }
707 #endif
708 #ifdef MATH_BULLET_INTEROP
709         float3(const btVector3 &other):x(other.x()), y(other.y()), z(other.z()) {}
710         operator btVector3() const return btVector3(xyz); }
711 #endif
712 #ifdef MATH_URHO3D_INTEROP
713         float3(const Urho3D::Vector3 &other) : x(other.x_), y(other.y_), z(other.z_) {}
714         operator Urho3D::Vector3() const return Urho3D::Vector3(xyz); }
715 #endif
716 #ifdef MATH_IRRKLANG_INTEROP
717     float3(const irrklang::vec3df &other) : x(other.X), y(other.Y), z(other.Z) {}
718     operator irrklang::vec3df() const return irrklang::vec3df(xyz); }
719 #endif
720 };
721
722 /// Prints this float3 to the given stream.
723 #ifdef MATH_ENABLE_STL_SUPPORT
724 std::ostream &operator <<(std::ostream &out, const float3 &rhs);
725 #endif
726
727 float3 operator *(float scalar, const float3 &rhs);
728
729 #ifdef MATH_ENABLE_UNCOMMON_OPERATIONS
730 inline float3 operator /(float scalar, const float3 &rhs) { return float3::FromScalar(scalar) / rhs; }
731 #endif
732
733 inline float Dot(const float3 &a, const float3 &b) { return a.Dot(b); }
734 inline float3 Cross(const float3 &a, const float3 &b) { return a.Cross(b); }
735 inline float3 Abs(const float3 &a) { return a.Abs(); }
736 inline float Length(const float3 &a) { return a.Length(); }
737 inline float Distance(const float3 &a, const float3 &b) { return a.Distance(b); }
738 inline float3 Min(const float3 &a, const float3 &b) { return a.Min(b); }
739 inline float3 Max(const float3 &a, const float3 &b) { return a.Max(b); }
740 inline float3 Clamp(const float3 &a, float floor, float ceil) { return a.Clamp(floor, ceil); }
741 inline float3 Clamp(const float3 &a, const float3 &floor, const float3 &ceil) { return a.Clamp(floor, ceil); }
742 inline float3 Clamp01(const float3 &a) { return a.Clamp01(); }
743 inline float3 Lerp(const float3 &a, const float3 &b, float t) { return a.Lerp(b, t); }
744
745 #ifdef MATH_QT_INTEROP
746 Q_DECLARE_METATYPE(float3)
747 Q_DECLARE_METATYPE(float3*)
748 #endif
749
750 MATH_END_NAMESPACE
751
752 #include "float4.h"
753 #include "MathFunc.h"
754
755 MATH_BEGIN_NAMESPACE
756
757 #ifdef MATH_AUTOMATIC_SSE
758 bool EqualAbs(float a, float b, float epsilon);
759
760 #define POINT_VEC(...) float4(__VA_ARGS__, 1.f)
761 #define DIR_VEC(...) float4(__VA_ARGS__, 0.f)
762
763 #define POINT_VEC_SCALAR(s) float4(pos_from_scalar_ps(s))
764 #define DIR_VEC_SCALAR(s) float4(dir_from_scalar_ps(s))
765
766 #define POINT_TO_FLOAT3(v) (v).xyz()
767 #define DIR_TO_FLOAT3(v) (v).xyz()
768
769 #define POINT_TO_FLOAT4(v) (v)
770 #define DIR_TO_FLOAT4(v) (v)
771
772 #define FLOAT4_TO_POINT(v) (v)
773 #define FLOAT4_TO_DIR(v) (v)
774
775 /* /// TODO: Enable this:
776 inline float3 POINT_TO_FLOAT3(const vec &v)
777 {
778         assume(EqualAbs(v.w, 1.f, 1e-4f));
779         return v.xyz();
780 }
781 inline float3 DIR_TO_FLOAT3(const vec &v)
782 {
783         assume(EqualAbs(v.w, 0.f, 1e-4f));
784         return v.xyz();
785 }
786 */
787 #else
788 #define POINT_VEC(...) float3(__VA_ARGS__)
789 #define DIR_VEC(...) float3(__VA_ARGS__)
790 #define POINT_TO_FLOAT3(x) x
791 #define DIR_TO_FLOAT3(x) x
792 #define POINT_VEC_SCALAR(s) float3::FromScalar(s)
793 #define DIR_VEC_SCALAR(s) float3::FromScalar(s)
794 #define POINT_TO_FLOAT4(v) float4(v, 1.f)
795 #define DIR_TO_FLOAT4(v) float4(v, 0.f)
796 #define FLOAT4_TO_POINT(v) (v).xyz()
797 #define FLOAT4_TO_DIR(v) (v).xyz()
798
799 #endif
800
801 vec PointVecFromString(const char *str, const char **outEndStr = 0);
802 vec DirVecFromString(const char *str, const char **outEndStr = 0);
803
804 MATH_END_NAMESPACE

Go back to previous page