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 float4.h
16         @author Jukka Jyl�nki
17         @brief A 4D (x,y,z,w) homogeneous vector. */
18 #pragma once
19
20 #ifdef MATH_ENABLE_STL_SUPPORT
21 #include <string>
22 #endif
23 #include "Math/MathFwd.h"
24 #include "Math/float3.h"
25
26 #ifdef MATH_QT_INTEROP
27 #include <QVector4D>
28 #endif
29
30 #ifdef MATH_OGRE_INTEROP
31 #include <OgreVector4.h>
32 #endif
33
34 MATH_BEGIN_NAMESPACE
35
36 /// A 3D vector of form (x,y,z,w) in a 4D homogeneous coordinate space.
37 /** This class has two sets of member functions. The functions ending in a suffix '3' operate only on the
38         (x, y, z) part, ignoring the w component (or assuming a value of 0 or 1, where expectable). The functions
39         without the '3' suffix operate on all four elements of the vector. */
40 class float4
41 {
42 public:
43         enum
44         {
45                 /// Specifies the number of elements in this vector.
46                 Size = 4
47         };
48
49         /// The x component.
50         /** A float4 is 16 bytes in size. This element lies in the memory offsets 0-3 of this class. */
51         float x;
52         /// The y component. [similarOverload: x]
53         /** This element is packed to the memory offsets 4-7 of this class. */
54         float y;
55         /// The z component. [similarOverload: x]
56         /** This element is packed to the memory offsets 8-11 of this class. */
57         float z;
58         /// The w component. [similarOverload: x]
59         /** This element is packed to the memory offsets 12-15 of this class. */
60         float w;
61
62         /// The default constructor does not initialize any members of this class.
63         /** This means that the values of the members x, y, z and w are all undefined after creating a new float4 using 
64                 this default constructor. Remember to assign to them before use.
65                 @see x, y, z, w. */
66         float4() {}
67
68         /// The float4 copy constructor.
69         /** The copy constructor is a standard default copy-ctor, but it is explicitly written to be able to automatically pick up 
70                 this function for script bindings. */
71         float4(const float4 &rhs) { x = rhs.xy = rhs.yz = rhs.zw = rhs.w; }
72
73         /// Constructs a new float4 with the value (x, y, z, w).
74         /** @see x, y, z, w. */
75         float4(float xfloat yfloat zfloat w);
76
77         /// Constructs a new float3 with the value (xyz.x, xyz.y, xyz.z, w).
78         /** @see x, y, z, w. */
79         float4(const float3 &xyzfloat w);
80
81         /// Constructs a new float3 with the value (xy.x, xy.y, z, w).
82         /** @see x, y, z, w. */
83         float4(const float2 &xy, float zfloat w);
84
85         /// Constructs this float4 from a C array, to the value (data[0], data[1], data[2], data[3]).
86         /** @param data An array containing four elements for x, y, z and w. This pointer may not be null. */
87         explicit float4(const float *data);
88
89         /// Casts this float4 to a C array. 
90         /** This function does not allocate new memory or make a copy of this float4. This function simply
91                 returns a C pointer view to this data structure. Use ptr()[0] to access the x component of this float4,
92                 ptr()[1] to access y, ptr()[2] to access z, and ptr()[3] to access the w component of this float4.
93                 @note Since the returned pointer points to this class, do not dereference the pointer after this
94                         float3 has been deleted. You should never store a copy of the returned pointer.
95                 @note This function is provided for compatibility with other APIs which require raw C pointer access
96                         to vectors. Avoid using this function in general, and instead always use the operator [] of this 
97                         class to access the elements of this vector by index.
98                 @return A pointer to the first float element of this class. The data is contiguous in memory.
99                 @see operator [](). */
100         float *ptr();
101         const float *ptr() const;
102
103         /// Accesses an element of this vector using array notation.
104         /** @param index The element to get. Pass in 0 for x, 1 for y, 2 for z and 3 for w.
105                 @note If you have a non-const instance of this class, you can use this notation to set the elements of 
106                         this vector as well, e.g. vec[1] = 10.f; would set the y-component of this vector. */
107         float &operator [](int index) { return At(index); }
108         CONST_WIN32 float operator [](int index) const return At(index); }
109
110         /// Accesses an element of this vector.
111         /** @param index The element to get. Pass in 0 for x, 1 for y, 2 for z and 3 for w.
112                 @note If you have a non-const instance of this class, you can use this notation to set the elements of 
113                         this vector as well, e.g. vec.At(1) = 10.f; would set the y-component of this vector. */
114         float &At(int index);
115         CONST_WIN32 float At(int index) const;
116
117         /// Adds two vectors. [indexTitle: operators +,-,*,/]
118         /** This function is identical to the member function Add().
119                 @return float4(x + v.x, y + v.y, z + v.z, w + v.w); */
120         float4 operator +(const float4 &v) const;
121
122         /// Performs an unary negation of this vector. [similarOverload: operator+] [hideIndex]
123         /** This function is identical to the member function Neg().
124                 @return float4(-x, -y, -z, -w). */
125         float4 operator -() const;
126
127         /// Subtracts the given vector from this vector. [similarOverload: operator+] [hideIndex]
128         /** This function is identical to the member function Sub().
129                 @return float4(x - v.x, y - v.y, z - v.z, w - v.w); */
130         float4 operator -(const float4 &v) const;
131
132         /// Multiplies this vector by a scalar. [similarOverload: operator+] [hideIndex]
133         /** This function is identical to the member function Mul().
134                 @return float4(x * scalar, y * scalar, z * scalar, w * scalar); */
135         float4 operator *(float scalar) const;
136
137         /// Divides this vector by a scalar. [similarOverload: operator+] [hideIndex]
138         /** This function is identical to the member function Div().
139                 @return float4(x / scalar, y / scalar, z / scalar, w * scalar); */
140         float4 operator /(float scalar) const;
141
142         /// Adds a vector to this vector, in-place. [indexTitle: operators +=,-=,*=,/=]
143         /** @return A reference to this. */
144         float4 &operator +=(const float4 &v);
145
146         /// Subtracts a vector from this vector, in-place. [similarOverload: operator+=] [hideIndex]
147         /** @return A reference to this. */
148         float4 &operator -=(const float4 &v);
149
150         /// Multiplies this vector by a scalar, in-place. [similarOverload: operator+=] [hideIndex]
151         /** @note If w != 0, multiplying by a scalar does <b>not</b> have the effect of scaling the length of this 3D vector.
152                 @return A reference to this. */
153         float4 &operator *=(float scalar);
154
155         /// Divides this vector by a scalar, in-place. [similarOverload: operator+=] [hideIndex]
156         /** @return A reference to this. */
157         float4 &operator /=(float scalar);
158
159 #ifdef MATH_ENABLE_UNCOMMON_OPERATIONS
160         float4 operator *(const float4 &vector) const return this->Mul(vector); }
161         float4 operator /(const float4 &vector) const return this->Div(vector); }
162         float4 &operator *=(const float4 &vector) { *this = this->Mul(vector); return *this; }
163         float4 &operator /=(const float4 &vector) { *this = this->Div(vector); return *this; }
164 #endif
165
166         /// Adds a vector to this vector. [IndexTitle: Add/Sub/Mul/Div]
167         /// @return (x+v.x, y+v.y, z+v.z, w+v.w).
168         float4 Add(const float4 &v) const return *this + v; }
169
170         /// Adds the vector (s,s,s,s) to this vector.
171         /// @note Mathematically, the addition of a vector and scalar is not defined in linear space structures, 
172         ///      but this function is provided here for syntactical convenience.
173         /// @return (x+s, y+s, z+s, w+s).
174         float4 Add(float s) const;
175
176         /// Subtracts a vector from this vector. [similarOverload: Add] [hideIndex]
177         /// @return (x-v.x, y-v.y, z-v.z, w-v.w).
178         float4 Sub(const float4 &v) const return *this - v; }
179
180         /// Subtracts the vector (s,s,s,s) from this vector. [similarOverload: Add] [hideIndex]
181         /// @note Mathematically, the subtraction of a vector by a scalar is not defined in linear space structures, 
182         ///      but this function is provided here for syntactical convenience.
183         /// @return (x-s, y-s, z-s, w-s).
184         float4 Sub(float s) const;
185
186         /// Subtracts this vector from the vector (s,s,s,s). [similarOverload: Add] [hideIndex]
187         /// @note Mathematically, the subtraction of a scalar by a vector is not defined in linear space structures, 
188         ///      but this function is provided here for syntactical convenience.
189         /// @return (s-x, s-y, s-z, s-w).
190         float4 SubLeft(float s) const;
191
192         /// Multiplies this vector by a vector, element-wise. [similarOverload: Add] [hideIndex]
193         /// @note Mathematically, the multiplication of two vectors is not defined in linear space structures, 
194         ///      but this function is provided here for syntactical convenience.
195         /// @return (x*v.x, y*v.y, z*v.z, w*v.w).
196         float4 Mul(const float4 &v) const;
197
198         /// Multiplies this vector by a scalar. [similarOverload: Add] [hideIndex]
199         /// @note If w != 0, multiplying by a scalar does <b>not</b> have the effect of scaling the length of this 3D vector.
200         /// @return (x*s, y*s, z*s, w*s).
201         float4 Mul(float s) const return *this * s; }
202
203         /// Divides this vector by a vector, element-wise. [similarOverload: Add] [hideIndex]
204         /// @note Mathematically, the division of two vectors is not defined in linear space structures, 
205         ///      but this function is provided here for syntactical convenience.
206         /// @return (x/v.x, y/v.y, z/v.z, w/v.w).
207         float4 Div(const float4 &v) const;
208
209         /// Divides this vector by a scalar. [similarOverload: Add] [hideIndex]
210         /// @return (x/s, y/s, z/s, w/s).
211         float4 Div(float s) const return *this / s; }
212         
213         /// Divides the vector (s,s,s,s) by this vector, element-wise. [similarOverload: Add] [hideIndex]
214         /// @note Mathematically, the division of a scalar by a vector is not defined in linear space structures, 
215         ///      but this function is provided here for syntactical convenience.
216         /// @return (s/x, s/y, s/z, s/w).
217         float4 DivLeft(float s) const;
218
219         /// Returns the (x, y, z) part of this vector.
220         float3 xyz() const;
221
222         /// Performs a swizzled access to this vector.
223         /** For example, Swizzled(2,1,0) return float3(z,y,x). Swizzled(3,3,3,3) returns float4(w,w,w,w).
224                 @param i Chooses the element of this vector to pick for the x value of the returned vector, in the range [0, 3].
225                 @param j Chooses the element of this vector to pick for the y value of the returned vector, in the range [0, 3].
226                 @param k Chooses the element of this vector to pick for the z value of the returned vector, in the range [0, 3].
227                 @param l Chooses the element of this vector to pick for the w value of the returned vector, in the range [0, 3].
228                 @see xyz(). */
229         float2 Swizzled(int i, int j) const;
230         float3 Swizzled(int i, int j, int k) const;
231         float4 Swizzled(int i, int j, int k, int l) const;
232
233         /// Returns float4(scalar, scalar, scalar, scalar).
234         /** @see float4::float4(float scalar), SetFromScalar(). */
235         static float4 FromScalar(float scalar);
236
237         /// Returns float4(scalar, scalar, scalar, w).
238         static float4 FromScalar(float scalar, float w);
239
240         /// Sets this float4 to (scalar, scalar, scalar, scalar).
241         /** @see float4::float4(float scalar), FromScalar(). */
242         void SetFromScalar(float scalar);
243
244         /// Sets this float4 to (scalar, scalar, scalar, w).
245         void SetFromScalar(float scalar, float w);
246
247         /// Sets all elements of this vector.
248         /** @see x, y, z, w, At(). */
249         void Set(float xfloat yfloat zfloat w);
250
251         /// Computes the squared length of the (x, y, z) part of this vector.
252         /** Calling this function is faster than calling Length3(), since this function avoids computing a square root.
253                 If you only need to compare lengths to each other, but are not interested in the actual length values, 
254                 you can compare by using LengthSq3(), instead of Length3(), since Sqrt() is an order-preserving
255                 (monotonous and non-decreasing) function.
256                 @note This function ignores the w component of this vector.
257                 @return x*x + y*y + z*z.
258                 @see Length3(), LengthSq4(), Length4(), Normalize3(), Normalize4(). */
259         float LengthSq3() const;
260
261         /// Computes the length of the (x, y, z) part of this vector.
262         /** @note This function ignores the w component of this vector.
263                 @return Sqrt(x*x + y*y + z*z).
264                 @see LengthSq3(), LengthSq4(), Length4(), Normalize3(), Normalize4(). */
265         float Length3() const;
266
267         /// Computes the squared length of this vector.
268         /** Calling this function is faster than calling Length4(), since this function avoids computing a square root.
269                 If you only need to compare lengths to each other, but are not interested in the actual length values, 
270                 you can compare by using LengthSq4(), instead of Length4(), since Sqrt() is an order-preserving
271                 (monotonous and non-decreasing) function.
272                 @return x*x + y*y + z*z + w*w.
273                 @see Length3(), LengthSq3(), Length4(), Normalize3(), Normalize4(). */
274         float LengthSq4() const;
275
276         /// Computes the length of this vector.
277         /** @return Sqrt(x*x + y*y + z*z + w*w).
278                 @see LengthSq3(), Length3(), LengthSq4(), Normalize3(), Normalize4(). */
279         float Length4() const;
280
281         /// Normalizes the (x, y, z) part of this vector.
282         /** @note This function ignores the w component of this vector, retaining whatever value was set there.
283                 @note This function fails silently. If you expect to receive an error message in case the normalization
284                         fails, use the Normalized3() function.
285                 @note This function operates in-place.
286                 @return The old length of this vector, or 0 if normalization failed. In the case of failure,
287                         this vector is set to (1, 0, 0, oldW), so that Normalize() function will never result in an unnormalized vector.
288                 @see Length3(), Length4(), Normalized3(), Normalize4(), Normalized4(). */
289         float Normalize3();
290
291         /// Normalizes this vector.
292         /** @note This function fails silently. If you expect to receive an error message in case the normalization
293                         fails, use the Normalized3() function.
294                 @note This function operates in-place.
295                 @return The old length of this vector, or 0 if normalization failed. In the case of failure,
296                 this vector is set to (1, 0, 0, 0), so that Normalize() function will never result in an unnormalized vector.
297                 @see Length3(), Length4(), Normalize3(), Normalized3(), Normalized4(). */
298         float Normalize4();
299
300         /// Returns a copy of this vector with the (x, y, z) part normalized.
301         /** The w component of this vector is carried over unchanged.
302                 @return A copy of this vector that has the (x, y, z) part normalized, and w set to the same value as in this vector. 
303                         If the normalization fails, an error message is printed and the vector (1, 0, 0, oldW) is returned.
304                 @see Length3(), Length4(), Normalize3(), Normalize4(), Normalized4(). */
305         float4 Normalized3() const;
306
307         /// Returns a normalized copy of this vector.
308         /** @return A copy of this vector that has the (x, y, z) part normalized, and w set to the same value as in this vector. 
309                         If the normalization fails, an error message is printed and the vector (1, 0, 0, oldW) is returned.
310                 @see Length3(), Length4(), Normalize3(), Normalize4(), Normalized3(). */
311         float4 Normalized4() const;
312
313         /// Divides each element by w to produce a float4 of form (x, y, z, 1).
314         /** This function performs the <b>perspective divide</b> or the <b>homogeneous divide</b> on this vector, which is the
315                 process of dividing each element of this vector by w.
316                 @note This function operates in-place.
317                 @return True if w != 0 for this vector, and the normalization of w succeeded. If this function succeeds, w == 1
318                         for the resulting float4. If normalization fails, no error message is printed and false is returned.
319                 @see IsWZeroOrOne(). */         
320         bool NormalizeW();
321
322         /// Returns true if the w component of this float4 is either 0 or 1.
323         /** This is a required condition for several functions to work correctly.
324                 @see NormalizeW(), IsZero3(), IsZero4(), IsNormalized3(), IsNormalized4(). */
325         bool IsWZeroOrOne(float epsilon = 1e-3f) const;
326
327         /// Tests if the (x, y, z) part of this vector is equal to (0,0,0), up to the given epsilon.
328         /** @see NormalizeW(), IsWZeroOrOne(), IsZero4(), IsNormalized3(), IsNormalized4(). */
329         bool IsZero3(float epsilonSq = 1e-6f) const;
330
331         /// Returns true if this vector is equal to (0,0,0,0), up to the given epsilon.
332         /** @see NormalizeW(), IsWZeroOrOne(), IsZero3(), IsNormalized3(), IsNormalized4(). */
333         bool IsZero4(float epsilonSq = 1e-6f) const;
334
335         /// Tests if the length of the (x, y, z) part of this vector is one, up to the given epsilon.
336         /** @see NormalizeW(), IsWZeroOrOne(), IsZero3(), IsZero4(), IsNormalized4(). */
337         bool IsNormalized3(float epsilonSq = 1e-6f) const;
338
339         /// Returns true if the length of this vector is 1, up to the given epsilon.
340         /** This function takes into account all the four components of this vector when calculating the norm.
341                 @see NormalizeW(), IsWZeroOrOne(), IsZero3(), IsZero4(), IsNormalized3(). */
342         bool IsNormalized4(float epsilonSq = 1e-6f) const;
343
344         /// Multiplies the (x, y, z) part of this vector by the given scalar.
345         /** Sets this vector to (x*scalar, y*scalar, z*scalar, w).
346                 @note This function operates in-place.
347                 @see Length3(), Mul(), ScaleToLength3(), ScaledToLength3(). */
348         void Scale3(float scalar);
349
350         /// Scales the (x, y, z) part of this vector so that its new length is as given.
351         /** This is effectively the same as normalizing the vector first and then multiplying by newLength.
352                 @return False if the length of this vector is zero, and the vector could not be scaled to the specified length.
353                 @see Length3(), Mul(), Scale3(), ScaledToLength3(). */
354         float ScaleToLength3(float newLength);
355
356         /// Returns a scaled copy of this vector which has its new length as given.
357         /** This function assumes the length of this vector is not zero.
358                 @see Length3(), Mul(), Scale3(), ScaleToLength3(). */
359         float4 ScaledToLength3(float newLength) const;
360
361         /// Tests if this vector contains valid finite elements.
362         bool IsFinite() const;
363
364         /// Tests if the (x, y, z) parts of two vectors are perpendicular to each other.
365         bool IsPerpendicular3(const float4 &other, float epsilon = 1e-6f) const;
366
367 #ifdef MATH_ENABLE_STL_SUPPORT
368         /// Returns "(x, y, z, w)".
369         std::string ToString() const;
370         /// Returns "x y z w". This is the preferred format for the float4 if it has to be serialized to a string for machine transfer.
371         std::string SerializeToString() const;
372 #endif
373
374         /// Parses a string that is of form "x,y,z,w" or "(x,y,z,w)" or "(x;y;z;w)" or "x y z w" to a new float4.
375         static float4 FromString(const char *str);
376 #ifdef MATH_ENABLE_STL_SUPPORT
377         static float4 FromString(const std::string &str) { return FromString(str.c_str()); }
378 #endif
379
380         /// @return x + y + z + w.
381         float SumOfElements() const;
382
383         /// @return x * y * z * w.
384         float ProductOfElements() const;
385
386         /// @return (x+y+z+w)/4.
387         float AverageOfElements() const;
388
389         /// @return Min(x, y, z, w).
390         /** @see MinElementIndex(). */
391         float MinElement() const;
392
393         /// Returns the index that has the smallest value in this vector.
394         /** @see MinElement(). */
395         int MinElementIndex() const;
396
397         /// @return Max(x, y, z, w).
398         /** @see MaxElementIndex(). */
399         float MaxElement() const;
400
401         /// Returns the index that has the smallest value in this vector.
402         /** @see MaxElement(). */
403         int MaxElementIndex() const;
404
405         /// Takes the element-wise absolute value of this vector.
406         /** @return float4(|x|, |y|, |z|, |w|).
407                 @see Neg3(), Neg4(). */
408         float4 Abs() const;
409
410         /// Returns a copy of this vector with the x, y and z elements negated.
411         /** @return float4(-x, -y, -z, w).
412                 @see Abs(), Neg4(). */
413         float4 Neg3() const;
414
415         /// Returns a copy of this vector with each element negated.
416         /** @return float4(-x, -y, -z, -w).
417                 @see Abs(), Neg3(). */
418         float4 Neg4() const;
419
420         /// Computes the element-wise reciprocal of the three first elements of this vector.
421         /** This function returns a new vector where the x, y and z elements of the original vector are replaced by 
422                 the values 1/x, 1/y and 1/z.
423                 @return float4(1/x, 1/y, 1/z, w). */
424         float4 Recip3() const;
425
426         /// Computes the element-wise reciprocal of this vector.
427         /** This function returns a new vector where each element x of the original vector is replaced by the value 1/x. 
428                 This function operates on all four elements of this vector.
429                 @return float4(1/x, 1/y, 1/z, 1/w). */
430         float4 Recip4() const;
431
432         /// Returns an element-wise minimum of this and the vector (ceil, ceil, ceil, ceil).
433         /** Each element that is larger than ceil is replaced by ceil. */
434         float4 Min(float ceil) const;
435
436         /// Returns an element-wise minimum of this and the given vector.
437         /** Each element that is larger than ceil is replaced by ceil.
438                 @see Max(), Clamp(). */
439         float4 Min(const float4 &ceil) const;
440
441         /// Returns an element-wise maximum of this and the vector (floor, floor, floor, floor).
442         /** Each element that is smaller than floor is replaced by floor. */
443         float4 Max(float floor) const;
444
445         /// Returns an element-wise maximum of this and the given vector.
446         /** Each element that is smaller than floor is replaced by floor.
447                 @see Min(), Clamp(). */
448         float4 Max(const float4 &floor) const;
449
450         /// Returns a vector that has floor <= this[i] <= ceil for each element.
451         float4 Clamp(float floor, float ceil) const;
452
453         /// Limits each element of this vector between the corresponding elements in floor and ceil.
454         /** @see Min(), Max(), Clamp01(). */
455         float4 Clamp(const float4 &floor, const float4 &ceil) const;
456
457         /// Limits each element of this vector in the range [0, 1].
458         /** @see Min(), Max(), Clamp(). */
459         float4 Clamp01() const;
460
461         /// Linearly interpolates between this and the vector b.
462         /** This function assumes that the w components of this and the other vector are equal.
463                 @param t The interpolation weight, in the range [0, 1].
464                 Lerp(b, 0) returns this vector, Lerp(b, 1) returns the vector b.
465                 Lerp(b, 0.5) returns the vector half-way in between the two vectors, and so on. */
466         float4 Lerp(const float4 &b, float t) const;
467         static float4 Lerp(const float4 &a, const float4 &b, float t);
468
469         /// Computes the squared distance between the (x, y, z) parts of this and the given float4. 
470         /** @note This function ignores the w component of this and rhs vector (assumes w=0 or w=1 are the same for both vectors).
471                 @see Distance3(), Length3Sq(), Length3(). */
472         float Distance3Sq(const float4 &rhs) const;
473
474         /// Computes the distance between the (x, y, z) parts of this and the given float4. 
475         /** @note This function ignores the w component of this and rhs vector (assumes w=0 or w=1 are the same for both vectors).
476                 @see Distance3Sq(), Length3Sq(), Length3(). */
477         float Distance3(const float4 &rhs) const;
478
479         /// Computes the dot product of the (x, y, z) parts of this and the given float4.
480         /** @note This function ignores the w component of this vector (assumes w=0).
481                 @see Dot4(), Cross3(). */
482         float Dot3(const float3 &rhs) const;
483         float Dot3(const float4 &rhs) const;
484
485         /// Computes the dot product of this and the given float4, taking into account the w component.
486         /** @see Dot3(), Cross3(). */
487         float Dot4(const float4 &rhs) const;
488
489         /// Computes the cross product of the (x, y, z) parts of this and the given vector. Returns a vector with w=0.
490         /** @see Dot3(), Dot4(). */
491         float4 Cross3(const float3 &rhs) const;
492         float4 Cross3(const float4 &rhs) const;
493
494         /// Computes the outer product of this and the given vector.
495         float4x4 OuterProduct(const float4 &rhs) const;
496
497         /// Returns a new normalized direction vector that points as close as possible towards the given hint vector.
498         float4 Perpendicular3(const float3 &hint = float3(0,1,0), const float3 &hint2 = float3(0,0,1)) const;
499
500         /// Returns another vector that is perpendicular to this vector and the vector returned by Perpendicular3(hint).
501         /** @todo Enforce that (x: this, y: Perpendicular3(), z: AnotherPerpendicular3) form a right-handed basis.
502                 @see Perpendicular3(). */
503         float4 AnotherPerpendicular3(const float3 &hint = float3(0,1,0), const float3 &hint2 = float3(0,0,1)) const;
504
505         /// Returns this vector reflected about a plane with the given normal.
506         /** By convention, both this and the reflected vector point away from the plane with the given normal.
507                 @note This function ignores the w component of this vector (assumes w=0). */
508         float4 Reflect3(const float3 &normal) const;
509
510         /// Returns the angle between this vector and the specified vector, in radians.
511         /** @note This function takes into account that this vector or the other vector can be unnormalized, and 
512                         normalizes the computations.
513                 @note This function ignores the w component of this vector (assumes w=0).
514                 @see Dot3(), AngleBetweenNorm3(), AngleBetween4(), AngleBetweenNorm4(). */
515         float AngleBetween3(const float4 &other) const;
516
517         /// Returns the angle between this vector and the specified normalized vector, in radians.
518         /** @note This vector must be normalized to call this function.
519                 @note This function ignores the w component of this vector (assumes w=0).
520                 @see Dot3(), AngleBetween3(), AngleBetween4(), AngleBetweenNorm4(). */
521         float AngleBetweenNorm3(const float4 &normalizedVector) const;
522
523         /// Returns the angle between this vector and the specified vector, in radians.
524         /** @note This function takes into account that this vector or the other vector can be unnormalized, and normalizes the computations.
525                 @see Dot3(), AngleBetween3(), AngleBetweenNorm3(), AngleBetweenNorm4(). */
526         float AngleBetween4(const float4 &other) const;
527
528         /// Returns the angle between this vector and the specified normalized vector, in radians.
529         /** @note This vector must be normalized to call this function.
530                 @see Dot3(), AngleBetween3(), AngleBetweenNorm3(), AngleBetween4(). */
531         float AngleBetweenNorm4(const float4 &normalizedVector) const;
532
533         /// Projects this vector onto the given vector.
534         /** @note This function treats this and target vector as direction vectors.
535                 @note This function ignores the w component of this vector (assumes w=0 or 1) and returns it unmodified.
536                 @see ProjectToNorm3(). */
537         float4 ProjectTo3(const float3 &target) const;
538
539         /// Projects this vector onto the given vector.
540         /** @param target The direction vector to project onto. This vector must be normalized.
541                 @note This function treats this and target vector as direction vectors.
542                 @note This function ignores the w component of this vector (assumes w=0 or 1) and returns it unmodified.
543                 @see ProjectTo3(). */
544         float4 ProjectToNorm3(const float3 &target) const;
545
546         /// Returns true if this vector is equal to the given vector, up to given per-element epsilon.
547         bool Equals(const float4 &other, float epsilon = 1e-3f) const;
548         bool Equals(float xfloat yfloat zfloat wfloat epsilon = 1e-3f) const;
549
550         /// Generates a direction vector of the given length pointing at a uniformly random direction.
551         /// The w-component for the returned vector is 0.
552         static float4 RandomDir(LCG &lcg, float length = 1.f);
553
554 #ifdef MATH_ENABLE_UNCOMMON_OPERATIONS
555         float4 operator *(const float4 &rhs) const return this->Mul(rhs); }
556         float4 operator /(const float4 &rhs) const return this->Div(rhs); }
557         float4 &operator *=(const float4 &rhs) { *this = this->Mul(rhs); return *this; }
558         float4 &operator /=(const float4 &rhs) { *this = this->Div(rhs); return *this; }
559 #endif
560
561         /// Specifies a compile-time constant float4 with value (0, 0, 0, 0).
562         /** @note Due to static data initialization order being undefined in C++, do NOT use this
563                         member to initialize other static data in other compilation units! */
564         static const float4 zero;
565
566         /// Specifies a compile-time constant float4 with value (1, 1, 1, 1). [similarOverload: zero]
567         /** @note Due to static data initialization order being undefined in C++, do NOT use this
568                         member to initialize other static data in other compilation units! */
569         static const float4 one;
570
571         /// Specifies a compile-time constant float4 with value (1, 0, 0, 0).
572         /** @note Due to static data initialization order being undefined in C++, do NOT use this
573                         member to initialize other static data in other compilation units! */
574         static const float4 unitX;
575
576         /// Specifies a compile-time constant float4 with value (0, 1, 0, 0). [similarOverload: unitX]
577         /** @note Due to static data initialization order being undefined in C++, do NOT use this
578                         member to initialize other static data in other compilation units! */
579         static const float4 unitY;
580
581         /// Specifies a compile-time constant float4 with value (0, 0, 1, 0). [similarOverload: unitX]
582         /** @note Due to static data initialization order being undefined in C++, do NOT use this
583                         member to initialize other static data in other compilation units! */
584         static const float4 unitZ;
585
586         /// Specifies a compile-time constant float4 with value (0, 0, 0, 1). [similarOverload: unitX]
587         /** @note Due to static data initialization order being undefined in C++, do NOT use this
588                         member to initialize other static data in other compilation units! */
589         static const float4 unitW;
590
591         /// A compile-time constant float4 with value (NaN, NaN, NaN, NaN).
592         /** For this constant, each element has the value of quiet NaN, or Not-A-Number.
593                 @note Never compare a float4 to this value! Due to how IEEE floats work, for each float x, both expressions "x == nan" and "x != nan" return false!
594                           That is, nothing is equal to NaN, not even NaN itself!
595                 @note Due to static data initialization order being undefined in C++, do NOT use this
596                         member to initialize other static data in other compilation units! */
597         static const float4 nan;
598
599         /// A compile-time constant float4 with value (+infinity, +infinity, +infinity, +infinity). [similarOverload: nan]
600         /** @note Due to static data initialization order being undefined in C++, do NOT use this
601                         member to initialize other static data in other compilation units! */
602         static const float4 inf;
603
604 #ifdef MATH_OGRE_INTEROP
605         float4(const Ogre::Vector4 &other) { x = other.x; y = other.y; z = other.z; w = other.w; }
606         float4 &operator =(const Ogre::Vector4 &other) { x = other.x; y = other.y; z = other.z; w = other.w; return *this; }
607         operator Ogre::Vector4() const return Ogre::Vector4(xyzw); }
608 #endif
609 #ifdef MATH_QT_INTEROP
610         float4(const QVector4D &other) { x = other.x(); y = other.y(); z = other.z(); w = other.w(); }
611         operator QVector4D() const return QVector4D(xyzw); }
612         operator QString() const return "float4(" + QString::number(x) + "," + QString::number(y) + "," + QString::number(z) + "," + QString::number(w) + ")"; }
613         QString toString() const return (QString)*this; }
614         QVector4D ToQVector4D() const return QVector4D(xyzw); }
615         static float4 FromQVector4D(const QVector4D &v) { return (float4)v; }
616         static float4 FromString(const QString &str) { return FromString(str.toStdString()); }
617 #endif
618 #ifdef MATH_BULLET_INTEROP
619         // Bullet uses the same btVector3 class for both 3- and 4 -tuples (due to SSE).
620         float4(const btVector3 &other) { x = other.x(); y = other.y(); z = other.z(); w = other.w(); }
621         operator btVector3() const { btVector3 v(xyz); v.setW(w); return v; }
622 #endif
623 };
624
625 #ifdef MATH_ENABLE_STL_SUPPORT
626 /// Prints this float4 to the given stream.
627 std::ostream &operator <<(std::ostream &out, const float4 &rhs);
628 #endif
629
630 /// Multiplies the x, y, z and w components of the vector by the given scalar. Note that if w != 0, 
631 /// this does NOT scale the length of the homogeneous 3D vector.
632 float4 operator *(float scalar, const float4 &rhs);
633
634 #ifdef MATH_ENABLE_UNCOMMON_OPERATIONS
635 inline float4 operator /(float scalar, const float4 &rhs) { return float4::FromScalar(scalar) / rhs; }
636 #endif
637
638 inline float Dot3(const float4 &a, const float4 &b) { return a.Dot3(b); }
639 inline float Dot4(const float4 &a, const float4 &b) { return a.Dot4(b); }
640 inline float4 Cross3(const float4 &a, const float4 &b) { return a.Cross3(b); }
641 inline float4 Abs(const float4 &a) { return a.Abs(); }
642 inline float4 Min(const float4 &a, const float4 &b) { return a.Min(b); }
643 inline float4 Max(const float4 &a, const float4 &b) { return a.Max(b); }
644 inline float4 Clamp(const float4 &a, float floor, float ceil) { return a.Clamp(floor, ceil); }
645 inline float4 Clamp(const float4 &a, const float4 &floor, const float4 &ceil) { return a.Clamp(floor, ceil); }
646 inline float4 Clamp01(const float4 &a) { return a.Clamp01(); }
647 inline float4 Lerp(const float4 &a, const float4 &b, float t) { return a.Lerp(b, t); }
648
649 MATH_END_NAMESPACE
650
651 #ifdef MATH_QT_INTEROP
652 Q_DECLARE_METATYPE(float4)
653 Q_DECLARE_METATYPE(float4*)
654 #endif

Go back to previous page