1 /* Copyright 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 float4x4.h
16         @author Jukka Jyl�nki
17         @brief A 4-by-4 matrix for affine and perspective projection operations in 3D space. */
18 #pragma once
19
20 #include "../MathBuildConfig.h"
21 #include "SSEMath.h"
22 #include "float4.h"
23
24 #ifdef MATH_ENABLE_STL_SUPPORT
25 #include "myassert.h"
26 #endif
27 #include "../MathGeoLibFwd.h"
28 #include "MatrixProxy.h"
29
30 #ifdef MATH_OGRE_INTEROP
31 #include <OgreMatrix4.h>
32 #endif
33 #ifdef MATH_QT_INTEROP
34 #include <QMatrix4x4>
35 #endif
36 #ifdef MATH_URHO3D_INTEROP
37 #include <Urho3D/Math/Matrix4.h>
38 #endif
39
40 MATH_BEGIN_NAMESPACE
41
42 /// A 4-by-4 matrix for affine transformations and perspective projections of 3D geometry.
43 /** This matrix can represent the most generic form of transformations for 3D objects, including perspective
44         projections, which float3x4 cannot store, and translations, which float3x3 cannot represent.
45
46         The elements of this matrix are
47
48                 m_00, m_01, m_02, m_03
49                 m_10, m_11, m_12, m_13
50                 m_20, m_21, m_22, m_23
51                 m_30, m_31, m_32, m_33
52
53         The element m_yx is the value on the row y and column x.
54         You can access m_yx using the double-bracket notation m[y][x], or using the member function m.At(y, x);
55
56         @note The member functions in this class use the convention that transforms are applied to vectors in the form
57         M * v. This means that "float4x4 M, M1, M2; M = M1 * M2;" gives a transformation M that applies M2 first, followed
58         by M1 second, i.e. M * v = M1 * M2 * v = M1 * (M2 * v). This is the convention commonly used with OpenGL. The
59         opposing convention (v * M) is commonly used with Direct3D.
60
61         @note This class uses row-major storage, which means that the elements are packed in memory in order
62          m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], ...
63         The elements for a single row of the matrix hold successive memory addresses. This is the same memory layout as
64          with C++ multidimensional arrays.
65
66         Contrast this with column-major storage, in which the elements are packed in the memory in
67         order m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], ...
68         There the elements for a single column of the matrix hold successive memory addresses.
69         This is exactly opposite from the standard C++ multidimensional arrays, since if you have e.g.
70         int v[10][10], then v[0][9] comes in memory right before v[1][0]. ( [0][0], [0][1], [0][2], ... [1][0], [1][1], ...) */
71 class ALIGN_MAT float4x4
72 {
73 public:
74         /// Specifies the height of this matrix.
75         enum { Rows = 4 };
76
77         /// Specifies the width of this matrix.
78         enum { Cols = 4 };
79
80         /// Stores the data in this matrix in row-major format.
81         /** [noscript] */
82 #if defined(MATH_SIMD)
83         union
84         {
85 #endif
86                 float v[Rows][Cols];
87 #ifdef MATH_AVX
88                 __m256 row2[2];
89 #endif
90 #if defined(MATH_SIMD)
91                 simd4f row[4];
92         };
93 #endif
94
95         /// A constant matrix that has zeroes in all its entries.
96         static const float4x4 zero;
97
98         /// A constant matrix that is the identity.
99         /** The identity matrix looks like the following:
100                    1 0 0 0
101                    0 1 0 0
102                    0 0 1 0
103                    0 0 0 1
104                 Transforming a vector by the identity matrix is like multiplying a number by one, i.e. the vector is not changed. */
105         static const float4x4 identity;
106
107         /// A compile-time constant float4x4 which has NaN in each element.
108         /// For this constant, each element has the value of quiet NaN, or Not-A-Number.
109         /// @note Never compare a float4x4 to this value! Due to how IEEE floats work, "nan == nan" returns false!
110         ///        That is, nothing is equal to NaN, not even NaN itself!
111         static const float4x4 nan;
112
113         /// Creates a new float4x4 with uninitialized member values.
114         /** [opaque-qtscript] */
115         float4x4() {}
116
117 #ifdef MATH_EXPLICIT_COPYCTORS
118         /// The copy-ctor for float4x4 is the trivial copy-ctor, but it is explicitly written to be able to automatically
119         /// pick up this function for QtScript bindings.
120         float4x4(const float4x4 &rhs) { Set(rhs); }
121 #endif
122
123         /// Constructs a new float4x4 by explicitly specifying all the matrix elements.
124         /// The elements are specified in row-major format, i.e. the first row first followed by the second and third row.
125         /// E.g. The element _10 denotes the scalar at second (index 1) row, first (index 0) column.
126         float4x4(float _00, float _01, float _02, float _03,
127                          float _10, float _11, float _12, float _13,
128                          float _20, float _21, float _22, float _23,
129                          float _30, float _31, float _32, float _33);
130
131         /// Constructs this float4x4 to represent the same transformation as the given float3x3.
132         /** This function expands the last row and column of this matrix with the elements from the identity matrix. */
133         float4x4(const float3x3 &other);
134
135         /// Constructs this float4x4 to represent the same transformation as the given float3x4.
136         /** The last row is set to [0 0 0 1]. */
137         float4x4(const float3x4 &other);
138
139         /// Constructs the matrix by explicitly specifying the four column vectors.
140         /** @param col0 The first column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
141                 direction of the local X axis.
142                 @param col1 The second column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
143                 direction of the local Y axis.
144                 @param col2 The third column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
145                 direction of the local Z axis.
146                 @param col3 The fourth column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
147                 position of the local space pivot. */
148         float4x4(const float4 &col0, const float4 &col1, const float4 &col2, const float4 &col3);
149
150         /// Constructs this float4x4 from the given quaternion.
151         explicit float4x4(const Quat &orientation);
152
153         /// Constructs this float4x4 from the given quaternion and translation.
154         /// Logically, the translation occurs after the rotation has been performed.
155         float4x4(const Quat &orientation, const float3 &translation);
156
157         /// Creates a new transformation matrix that translates by the given offset.
158         static TranslateOp Translate(float tx, float ty, float tz);
159         static TranslateOp Translate(const float3 &offset);
160
161         /// Creates a new float4x4 that rotates about one of the principal axes. [indexTitle: RotateX/Y/Z]
162         /** Calling RotateX, RotateY or RotateZ is slightly faster than calling the more generic RotateAxisAngle function.
163                 @param angleRadians The angle to rotate by, in radians. For example, Pi/4.f equals to 45 degrees, Pi/2.f is 90 degrees, and Pi is 180 degrees.
164                 @param pointOnAxis If specified, the rotation is performed about an axis that passes through this point, and not
165                 through the origin. The returned matrix will not be a pure rotation matrix, but will also contain translation.
166                 @see DegToRad(). */
167         static float4x4 RotateX(float angleRadians, const float3 &pointOnAxis);
168         static float4x4 RotateX(float angleRadians);
169         /** [similarOverload: RotateX] [hideIndex] */
170         static float4x4 RotateY(float angleRadians);
171         /** [similarOverload: RotateX] [hideIndex] */
172         static float4x4 RotateY(float angleRadians, const float3 &pointOnAxis);
173         /** [similarOverload: RotateX] [hideIndex] */
174         static float4x4 RotateZ(float angleRadians);
175         /** [similarOverload: RotateX] [hideIndex] */
176         static float4x4 RotateZ(float angleRadians, const float3 &pointOnAxis);
177
178         /// Creates a new float4x4 that rotates about the given axis.
179         /** @param axisDirection The axis to rotate about. This vector must be normalized.
180                 @param angleRadians The angle to rotate by, in radians. Pi/4.f equals to 45 degrees, Pi/2.f is 90 degrees, and Pi is 180 degrees.
181                 @param pointOnAxis If specified, the rotation is performed about an axis that passes through this point, and not
182                 through the origin. The returned matrix will not be a pure rotation matrix, but will also contain translation. */
183         static float4x4 RotateAxisAngle(const float3 &axisDirection, float angleRadians, const float3 &pointOnAxis);
184         static float4x4 RotateAxisAngle(const float3 &axisDirection, float angleRadians);
185
186         /// Creates a new float4x4 that rotates sourceDirection vector to coincide with the targetDirection vector.
187         /** @note There are infinite such rotations - this function returns the rotation that has the shortest angle
188                 (when decomposed to axis-angle notation).
189                 @param sourceDirection The 'from' direction vector. This vector must be normalized.
190                 @param targetDirection The 'to' direction vector. This vector must be normalized.
191                 @param centerPoint If specified, rotation is performed using this point as the coordinate space origin. If omitted,
192                         the rotation is performed about the coordinate system origin (0,0,0).
193                 @return A new rotation matrix R for which R*sourceDirection == targetDirection. */
194         static float4x4 RotateFromTo(const float3 &sourceDirection, const float3 &targetDirection, const float3 &centerPoint);
195         static float4x4 RotateFromTo(const float3 &sourceDirection, const float3 &targetDirection);
196
197         /// Returns a random 4x4 matrix with each entry randomized between the range [minElem, maxElem].
198         /** Warning: The matrices returned by this function do not represent well-formed 3D transformations.
199                 This function is mostly used for testing and debugging purposes only. */
200         static float4x4 RandomGeneral(LCG &lcg, float minElem, float maxElem);
201
202         /// Creates a new float4x4 that rotates one coordinate system to coincide with another.
203         /** This function rotates the sourceDirection vector to coincide with the targetDirection vector, and then
204                         rotates sourceDirection2 (which was transformed by 1.) to targetDirection2, but keeping the constraint that
205                         sourceDirection must look at targetDirection. */
206         /** @param sourceDirection The first 'from' direction. This vector must be normalized.
207                 @param targetDirection The first 'to' direction. This vector must be normalized.
208                 @param sourceDirection2 The second 'from' direction. This vector must be normalized.
209                 @param targetDirection2 The second 'to' direction. This vector must be normalized.
210                 @param centerPoint If specified, rotation is performed using this point as the coordinate space origin.
211                 @return The returned matrix maps sourceDirection to targetDirection. Additionally, the returned matrix
212                         rotates sourceDirection2 to point towards targetDirection2 as closely as possible, under the previous constraint.
213                         The returned matrix is a rotation matrix, i.e. it is orthonormal with a determinant of +1, and optionally
214                         has a translation component if the rotation is not performed w.r.t. the coordinate system origin. */
215         static float4x4 RotateFromTo(const float3 &sourceDirection, const float3 &targetDirection,
216                 const float3 &sourceDirection2, const float3 &targetDirection2, const float3 &centerPoint);
217         static float4x4 RotateFromTo(const float3 &sourceDirection, const float3 &targetDirection,
218                 const float3 &sourceDirection2, const float3 &targetDirection2);
219
220         /// Creates a new float4x4 that performs the rotation expressed by the given quaternion.
221         static float4x4 FromQuat(const Quat &orientation);
222         /** param pointOnAxis If specified, the rotation is performed using this point as the center point. */
223         static float4x4 FromQuat(const Quat &orientation, const float3 &pointOnAxis);
224
225         /// Creates a new float4x4 as a combination of translation, rotation and scale.
226         /** This function creates a new float4x4 M of the form M = T * R * S, where T is a translation matrix, R a
227                 (rotation) matrix and S a scale matrix. Transforming a vector v using this matrix computes the vector
228                 v' == M * v == T*R*S*v == (T * (R * (S * v))), which means that the scale operation is applied to the
229                 vector first, followed by rotation and finally translation. */
230         static float4x4 FromTRS(const float3 &translate, const Quat &rotate, const float3 &scale);
231         static float4x4 FromTRS(const float3 &translate, const float3x3 &rotate, const float3 &scale);
232         static float4x4 FromTRS(const float3 &translate, const float3x4 &rotate, const float3 &scale);
233         static float4x4 FromTRS(const float3 &translate, const float4x4 &rotate, const float3 &scale);
234
235         /// Creates a new float4x4 from the given sequence of Euler rotation angles (in radians).
236         /** The FromEulerABC function returns a matrix M = A(a) * B(b) * C(c). Rotation
237                 C is applied first, followed by B and then A. [indexTitle: FromEuler***] */
238         static float4x4 FromEulerXYX(float x2, float y, float x);
239         static float4x4 FromEulerXZX(float x2, float z, float x); ///< [similarOverload: FromEulerXYX] [hideIndex]
240         static float4x4 FromEulerYXY(float y2, float x, float y); ///< [similarOverload: FromEulerXYX] [hideIndex]
241         static float4x4 FromEulerYZY(float y2, float z, float y); ///< [similarOverload: FromEulerXYX] [hideIndex]
242         static float4x4 FromEulerZXZ(float z2, float x, float z); ///< [similarOverload: FromEulerXYX] [hideIndex]
243         static float4x4 FromEulerZYZ(float z2, float y, float z); ///< [similarOverload: FromEulerXYX] [hideIndex]
244         static float4x4 FromEulerXYZ(float x, float y, float z); ///< [similarOverload: FromEulerXYX] [hideIndex]
245         static float4x4 FromEulerXZY(float x, float z, float y); ///< [similarOverload: FromEulerXYX] [hideIndex]
246         static float4x4 FromEulerYXZ(float y, float x, float z); ///< [similarOverload: FromEulerXYX] [hideIndex]
247         static float4x4 FromEulerYZX(float y, float z, float x); ///< [similarOverload: FromEulerXYX] [hideIndex]
248         static float4x4 FromEulerZXY(float z, float x, float y); ///< [similarOverload: FromEulerXYX] [hideIndex]
249         static float4x4 FromEulerZYX(float z, float y, float x); ///< [similarOverload: FromEulerXYX] [hideIndex]
250
251         /// Creates a new transformation matrix that scales by the given factors.
252         /// This matrix scales with respect to origin.
253         static ScaleOp Scale(float sx, float sy, float sz);
254         static ScaleOp Scale(const float3 &scale);
255
256         /// Creates a new float4x4 that scales with respect to the given center point.
257         /** @param scale The amount of scale to apply to the x, y and z directions.
258                 @param scaleCenter The coordinate system center point for the scaling. If omitted, the origin (0,0,0) will
259                         be used as the origin for the scale operation. */
260         static float4x4 Scale(const float3 &scale, const float3 &scaleCenter);
261
262         /// Creates a new float4x4 that scales points along the given axis.
263         /** @param axis A normalized direction vector that specifies the direction of scaling.
264                 @param scalingFactor The amount of scaling to apply along the specified axis. */
265         /** @param scaleCenter If specified, this point will be used as the origin for the scale operation. */
266         static float4x4 ScaleAlongAxis(const float3 &axis, float scalingFactor, const float3 &scaleCenter);
267         static float4x4 ScaleAlongAxis(const float3 &axis, float scalingFactor);
268
269         /// Creates a new float4x4 that performs uniform scaling by the given amount.
270         static ScaleOp UniformScale(float uniformScale);
271         static float4x4 UniformScale(float uniformScale, const float3 &scaleCenter);
272
273         /// Returns the scaling performed by this matrix. This function assumes that the last row is [0 0 0 1].
274         /// GetScale().x specifies the amount of scaling applied to the local x direction vector when it is transformed by this matrix.
275         /// i.e. GetScale()[i] equals Col(i).Length();
276         float3 GetScale() const;
277
278         /// Produces a matrix that shears along a principal axis.
279         /** The shear matrix offsets the two other axes according to the
280                 position of the point along the shear axis. [indexTitle: ShearX/Y/Z] */
281         static float4x4 ShearX(float yFactor, float zFactor);
282         static float4x4 ShearY(float xFactor, float zFactor); ///< [similarOverload: ShearX] [hideIndex]
283         static float4x4 ShearZ(float xFactor, float yFactor); ///< [similarOverload: ShearX] [hideIndex]
284
285         /// Creates a new matrix that mirrors with respect to the given plane.
286         /** Points lying on one side of the plane will end up at the opposite side of the plane, at the same distance of the plane
287                 they were. */
288         static float4x4 Mirror(const Plane &p);
289
290         /// Identical to D3DXMatrixOrthoLH, except transposed to account for Matrix * vector convention used in MathGeoLib.
291         /// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205346(v=vs.85).aspx
292         /// @note Use the M*v multiplication order to project points with this matrix.
293         static float4x4 D3DOrthoProjLH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
294         /// Identical to D3DXMatrixOrthoRH, except transposed to account for Matrix * vector convention used in MathGeoLib.
295         /// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205349(v=vs.85).aspx
296         /// @note Use the M*v multiplication order to project points with this matrix.
297         static float4x4 D3DOrthoProjRH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
298
299         /// Identical to D3DXMatrixPerspectiveLH, except transposed to account for Matrix * vector convention used in MathGeoLib.
300         /// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205352(v=vs.85).aspx
301         /// @note Use the M*v multiplication order to project points with this matrix.
302         static float4x4 D3DPerspProjLH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
303         /// Identical to D3DXMatrixPerspectiveRH, except transposed to account for Matrix * vector convention used in MathGeoLib.
304         /// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205355(v=vs.85).aspx
305         /// @note Use the M*v multiplication order to project points with this matrix.
306         static float4x4 D3DPerspProjRH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
307
308         /// Computes a left-handled orthographic projection matrix for OpenGL.
309         /// @note Use the M*v multiplication order to project points with this matrix.
310         static float4x4 OpenGLOrthoProjLH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
311         /// Computes a right-handled orthographic projection matrix for OpenGL.
312         /// @note Use the M*v multiplication order to project points with this matrix.
313         static float4x4 OpenGLOrthoProjRH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
314
315         /// Computes a left-handed perspective projection matrix for OpenGL.
316         /// @note Use the M*v multiplication order to project points with this matrix.
317         static float4x4 OpenGLPerspProjLH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
318         /// Identical to http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml , except uses viewport sizes instead of FOV to set up the
319         /// projection matrix.
320         /// @note Use the M*v multiplication order to project points with this matrix.
321         static float4x4 OpenGLPerspProjRH(float nearPlaneDistance, float farPlaneDistance, float horizontalViewportSize, float verticalViewportSize);
322
323         /// Creates a new float4x4 that performs orthographic projection. [indexTitle: OrthographicProjection/YZ/XZ/XY]
324         static float4x4 OrthographicProjection(const Plane &target);
325         static float4x4 OrthographicProjectionYZ(); ///< [similarOverload: OrthographicProjection] [hideIndex]
326         static float4x4 OrthographicProjectionXZ(); ///< [similarOverload: OrthographicProjection] [hideIndex]
327         static float4x4 OrthographicProjectionXY(); ///< [similarOverload: OrthographicProjection] [hideIndex]
328
329         /// Computes the complementary projection of this matrix.
330         /// If P is a matrix that projects from 3D space to 2D, then the complementary projection
331         /// matrix projects from 3D to the normal vector of the 2D projection plane of the matrix P.
332         float4x4 ComplementaryProjection() const;
333
334         /// Returns the given element.
335         /** Returns a reference to the element at m[row][col] (or "m[y][x]").
336                 Remember that zero-based indexing is used, so m[0][0] is the upper-left element of this matrix.
337                 @note You can use the index notation to set elements of the matrix, e.g. m[0][1] = 5.f;
338                 @note MatrixProxy is a temporary helper class. Do not store references to it, but always
339                 directly dereference it with the [] operator.
340                 For example, m[0][3] Returns the last element on the first row, which is the amount
341                 of translation in the x-direction. */
342         MatrixProxy<Cols> &operator[](int row);
343         const MatrixProxy<Cols> &operator[](int row) const;
344
345         /// Returns the given element. [noscript]
346         /** This function returns the element of this matrix at (row, col)==(i, j)==(y, x).
347                 If you have a non-const object, you can set values of this matrix through this
348                 reference, using the notation m.At(row, col) = someValue; */
349         float &At(int row, int col);
350         CONST_WIN32 float At(int row, int col) const;
351
352         /// Returns the given row. [noscript]
353         /** @param row The zero-based index [0, 3] of the row to get. */
354         float4 &Row(int row);
355         const float4 &Row(int row) const;
356         /// Returns the three first entries of the given row. [similarOverload: Row] [hideIndex]
357         float3 &Row3(int row); ///< [noscript]
358         const float3 &Row3(int row) const;
359
360         /// Returns the given column.
361         /** @param col The zero-based index [0, 3] of the column to get. */
362         CONST_WIN32 float4 Col(int col) const;
363         /// Returns the three first entries of the given column. [similarOverload: Column] [hideIndex]
364         CONST_WIN32 float3 Col3(int col) const;
365
366         /// Returns the main diagonal.
367         /** The main diagonal consists of the elements at m[0][0], m[1][1], m[2][2] and m[3][3]. */
368         CONST_WIN32 float4 Diagonal() const;
369         /// Returns the three first entries of the main diagonal. [similarOverload: MainDiagonal] [hideIndex]
370         CONST_WIN32 float3 Diagonal3() const;
371
372         /// Scales the three first elements of the given row by a scalar.
373         void ScaleRow3(int row, float scalar);
374
375         /// Scales the given row by a scalar.
376         void ScaleRow(int row, float scalar);
377
378         /// Scales the three first elements of the given column by a scalar.
379         void ScaleCol3(int col, float scalar);
380
381         /// Scales the given column by a scalar.
382         void ScaleCol(int col, float scalar);
383
384         /// Returns the upper-left 3-by-3 part.
385         CONST_WIN32 float3x3 Float3x3Part() const;
386
387         /// Returns the upper-left 3-by-4 part. [noscript]
388         /// @note The float3x4 and float4x4 are bit-compatible, so this function simply casts.
389         float3x4 &Float3x4Part();
390         const float3x4 &Float3x4Part() const;
391
392         /// Returns the translation part.
393         /** The translation part is stored in the fourth column of this matrix.
394                 This is equivalent to decomposing this matrix in the form M = T * M', i.e. this translation is applied last,
395                 after applying rotation and scale. If this matrix represents a local->world space transformation for an object,
396                 then this gives the world space position of the object.
397                 @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]). */
398         CONST_WIN32 float3 TranslatePart() const;
399
400         /// Returns the top-left 3x3 part of this matrix. This stores the rotation part of this matrix (if this matrix represents a rotation).
401         CONST_WIN32 float3x3 RotatePart() const;
402
403         // Returns the local right axis in the post-transformed coordinate space, according to the given convention.
404         // @note The returned vector might not be normalized if this matrix contains scaling.
405         // @note The basis returned by (Right, Up, Forward) might not be of the same handedness as the
406         //         pre-transformed coordinate system, if the matrix contained reflection.
407 //      template<typename Convention = XposRight_YposUp_ZposForward> float3 Right() const;
408
409         // Returns the local up axis in the post-transformed coordinate space, according to the given convention.
410         // @note The returned vector might not be normalized if this matrix contains scaling.
411         // @note The basis returned by (Right, Up, Forward) might not be of the same handedness as the
412         //         pre-transformed coordinate system, if the matrix contained reflection.
413 //      template<typename Convention = XposRight_YposUp_ZposForward> float3 Up() const;
414
415         // Returns the local forward axis in the post-transformed coordinate space, according to the given convention.
416         // @note The returned vector might not be normalized if this matrix contains scaling.
417         // @note The basis returned by (Right, Up, Forward) might not be of the same handedness as the
418         //         pre-transformed coordinate system, if the matrix contained reflection.
419 //      template<typename Convention = XposRight_YposUp_ZposForward> float3 Forward() const;
420
421         /// Returns the local +X axis in world space.
422         /** This is the same as transforming the vector (1,0,0) by this matrix. [indexTitle: X/Y/Z] */
423         float3 WorldX() const;
424         /// Returns the local +Y axis in world space.
425         /** This is the same as transforming the vector (0,1,0) by this matrix. [similarOverload: X] [hideIndex] */
426         float3 WorldY() const;
427         /// Returns the local +Z axis in world space.
428         /** This is the same as transforming the vector (0,0,1) by this matrix. [similarOverload: X] [hideIndex] */
429         float3 WorldZ() const;
430
431         /// Accesses this structure as a float array.
432         /// @return A pointer to the upper-left element. The data is contiguous in memory.
433         /// ptr[0] gives the element [0][0], ptr[1] is [0][1], ptr[2] is [0][2].
434         /// ptr[4] == [1][0], ptr[5] == [1][1], ..., and finally, ptr[15] == [3][3].
435         FORCE_INLINE float *ptr() { return &v[0][0]; }
436         FORCE_INLINE const float *ptr() const return &v[0][0]; }
437
438         /// Sets the three first elements of the given row. The fourth element is left unchanged.
439         /** @param row The index of the row to set, in the range [0-3].
440                 @param data A pointer to an array of 3 floats that contain the new x, y and z values for the row. */
441         void SetRow3(int row, const float *data);
442         void SetRow3(int row, const float3 &rowVector);
443         void SetRow3(int row, float m_r0, float m_r1, float m_r2);
444
445         /// Sets the values of the given row.
446         /** @param row The index of the row to set, in the range [0-3].
447                 @param data A pointer to an array of 4 floats that contain the new x, y, z and w values for the row. */
448         void SetRow(int row, const float *data);
449         void SetRow(int row, const float3 &rowVector, float m_r3);
450         void SetRow(int row, const float4 &rowVector);
451         void SetRow(int row, float m_r0, float m_r1, float m_r2, float m_r3);
452
453         /// Sets the three first elements of the given column. The fourth element is left unchanged.
454         /** @param column The index of the column to set, in the range [0-3].
455                 @param data A pointer to an array of 3 floats that contain the new x, y and z values for the column. */
456         void SetCol3(int column, const float *data);
457         void SetCol3(int column, const float3 &columnVector);
458         void SetCol3(int column, float m_0c, float m_1c, float m_2c);
459
460         /// Sets the values of the given column.
461         /** @param column The index of the column to set, in the range [0-3].
462                 @param data A pointer to an array of 4 floats that contain the new x, y, z and w values for the column. */
463         void SetCol(int column, const float *data);
464         void SetCol(int column, const float3 &columnVector, float m_3c);
465         void SetCol(int column, const float4 &columnVector);
466         void SetCol(int column, float m_0c, float m_1c, float m_2c, float m_3c);
467
468         /// Sets all values of this matrix.
469         void Set(float _00, float _01, float _02, float _03,
470                          float _10, float _11, float _12, float _13,
471                          float _20, float _21, float _22, float _23,
472                          float _30, float _31, float _32, float _33);
473
474         /// Sets this to be a copy of the matrix rhs.
475         void Set(const float4x4 &rhs);
476
477         /// Sets all values of this matrix.
478         /** @param values The values in this array will be copied over to this matrix. The source must contain 16 floats in row-major order (the same
479                         order as the Set() function above has its input parameters in). */
480         void Set(const float *values);
481
482         /// Sets a single element of this matrix.
483         /** @param row The row index (y-coordinate) of the element to set, in the range [0-3].
484                 @param col The col index (x-coordinate) of the element to set, in the range [0-3].
485                 @param value The new value to set to the cell [row][col]. */
486         void Set(int row, int col, float value);
487
488         void Set3x3Part(const float3x3 &rotation);
489         void Set3x4Part(const float3x4 &rotateTranslate);
490
491         /// Sets this matrix to equal the identity.
492         void SetIdentity();
493
494         /// Swaps two columns.
495         void SwapColumns(int col1, int col2);
496         /// Swaps the xyz-parts of two columns element-by-element. [similarOverload: SwapColumns] [hideIndex]
497         void SwapColumns3(int col1, int col2);
498
499         /// Swaps two rows.
500         void SwapRows(int row1, int row2);
501         /// Swaps the xyz-parts of two rows element-by-element. [similarOverload: SwapRows] [hideIndex]
502         void SwapRows3(int row1, int row2);
503
504         /// Sets the translation part of this matrix.
505         /** This function sets the translation part of this matrix. These are the three first elements of the fourth column.
506                 All other entries are left untouched. */
507         void SetTranslatePart(float tx, float ty, float tz);
508         void SetTranslatePart(const float3 &offset);
509         void SetTranslatePart(const float4 &offset);
510
511         /// Sets the 3-by-3 part of this matrix to perform rotation about the positive X axis which passes through
512         /// the origin. Leaves all other entries of this matrix untouched. [similarOverload: SetRotatePart] [hideIndex]
513         void SetRotatePartX(float angleRadians);
514         /// Sets the 3-by-3 part of this matrix to perform rotation about the positive Y axis. Leaves all other
515         /// entries untouched. [similarOverload: SetRotatePart] [hideIndex]
516         void SetRotatePartY(float angleRadians);
517         /// Sets the 3-by-3 part of this matrix to perform rotation about the positive Z axis. Leaves all other
518         /// entries untouched. [similarOverload: SetRotatePart] [hideIndex]
519         void SetRotatePartZ(float angleRadians);
520
521         /// Sets the 3-by-3 part of this matrix to perform rotation about the given axis and angle (in radians). Leaves all other
522         /// entries of this matrix untouched. [indexTitle: SetRotatePart/X/Y/Z]
523         void SetRotatePart(const float3 &axisDirection, float angleRadians);
524         /// Sets the 3-by-3 part of this matrix to perform the rotation expressed by the given quaternion.
525         /// Leaves all other entries of this matrix untouched.
526         void SetRotatePart(const Quat &orientation);
527
528         /// Sets the 3-by-3 part of this matrix.
529         /// @note This is a convenience function which calls Set3x3Part.
530         /// @note This function erases the previous top-left 3x3 part of this matrix (any previous rotation, scaling and shearing, etc.). Translation is unaffected.
531         void SetRotatePart(const float3x3 &rotation) { Set3x3Part(rotation); }
532
533         /// Creates a LookAt matrix from a look-at direction vector.
534         /** A LookAt matrix is a rotation matrix that orients an object to face towards a specified target direction.
535                 @param localForward Specifies the forward direction in the local space of the object. This is the direction
536                         the model is facing at in its own local/object space, often +X (1,0,0), +Y (0,1,0) or +Z (0,0,1). The
537                         vector to pass in here depends on the conventions you or your modeling software is using, and it is best
538                         pick one convention for all your objects, and be consistent.
539                         This input parameter must be a normalized vector.
540                 @param targetDirection Specifies the desired world space direction the object should look at. This function
541                         will compute a rotation matrix which will rotate the localForward vector to orient towards this targetDirection
542                         vector. This input parameter must be a normalized vector.
543                 @param localUp Specifies the up direction in the local space of the object. This is the up direction the model
544                         was authored in, often +Y (0,1,0) or +Z (0,0,1). The vector to pass in here depends on the conventions you
545                         or your modeling software is using, and it is best to pick one convention for all your objects, and be
546                         consistent. This input parameter must be a normalized vector. This vector must be perpendicular to the
547                         vector localForward, i.e. localForward.Dot(localUp) == 0.
548                 @param worldUp Specifies the global up direction of the scene in world space. Simply rotating one vector to
549                         coincide with another (localForward->targetDirection) would cause the up direction of the resulting
550                         orientation to drift (e.g. the model could be looking at its target its head slanted sideways). To keep
551                         the up direction straight, this function orients the localUp direction of the model to point towards the
552                         specified worldUp direction (as closely as possible). The worldUp and targetDirection vectors cannot be
553                         collinear, but they do not need to be perpendicular either.
554                 @return A matrix that maps the given local space forward direction vector to point towards the given target
555                         direction, and the given local up direction towards the given target world up direction. The returned
556                         matrix M is orthonormal with a determinant of +1. For the matrix M it holds that
557                         M * localForward = targetDirection, and M * localUp lies in the plane spanned by the vectors targetDirection
558                         and worldUp.
559                 @note The position of (the translation performed by) the resulting matrix will be set to (0,0,0), i.e. the object
560                         will be placed to origin. Call SetTranslatePart() on the resulting matrix to set the position of the model.
561                 @see RotateFromTo(). */
562         static float4x4 LookAt(const float3 &localForward, const float3 &targetDirection, const float3 &localUp, const float3 &worldUp);
563
564         /// Creates a LookAt matrix from source and target points.
565         /**     A LookAt matrix is a rotation matrix that orients an object to face towards a specified target direction.
566                 @param eyePos The position the observer is at, i.e. the position of the model.
567                 @param targetPos The target position the model should be looking at. The vectors eyePos and targetPos
568                         cannot be equal, and the direction specified by targetPos - eyePos cannot be collinear to the direction
569                         passed in worldUp.
570                 @param localForward Specifies the forward direction in the local space of the object. This is the direction
571                         the model is facing at in its own local/object space, often +X (1,0,0), +Y (0,1,0) or +Z (0,0,1). The
572                         vector to pass in here depends on the conventions you or your modeling software is using, and it is best
573                         pick one convention for all your objects, and be consistent.
574                         This input parameter must be a normalized vector.
575                 @param localUp Specifies the up direction in the local space of the object. This is the up direction the model
576                         was authored in, often +Y (0,1,0) or +Z (0,0,1). The vector to pass in here depends on the conventions you
577                         or your modeling software is using, and it is best to pick one convention for all your objects, and be
578                         consistent. This input parameter must be a normalized vector. This vector must be perpendicular to the
579                         vector localForward, i.e. localForward.Dot(localUp) == 0.
580                 @param worldUp Specifies the global up direction of the scene in world space. Simply rotating one vector to
581                         coincide with another (localForward->targetDirection) would cause the up direction of the resulting
582                         orientation to drift (e.g. the model could be looking at its target its head slanted sideways). To keep
583                         the up direction straight, this function orients the localUp direction of the model to point towards the
584                         specified worldUp direction (as closely as possible). The worldUp and targetDirection vectors cannot be
585                         collinear, but they do not need to be perpendicular either.
586                 @return A matrix that maps the given local space forward direction vector to point towards the given target
587                         direction, and the given local up direction towards the given target world up direction. The returned
588                         matrix M is orthonormal with a determinant of +1. For the matrix M it holds that
589                         M * localForward = targetDirection, and M * localUp lies in the plane spanned by the vectors targetDirection
590                         and worldUp.
591                 @note The position of (the translation performed by) the resulting matrix will be set to eyePos, i.e. the object
592                         will be placed to the given eye position.
593                 @see RotateFromTo().
594                 @note Be aware that the convention of a 'LookAt' matrix in MathGeoLib differs from e.g. GLM. In MathGeoLib, the returned
595                         matrix is a mapping from local space to world space, meaning that the returned matrix can be used as the 'world transform'
596                         for any 3D object (camera or not). The view space is the local space of the camera, so this function returns the mapping
597                         view->world. In GLM, the LookAt function is tied to cameras only, and it returns the inverse mapping world->view. */
598         static float4x4 LookAt(const float3 &eyePos, const float3 &targetPos, const float3 &localForward,
599                                const float3 &localUp, const float3 &worldUp);
600
601         /// Sets this float4x4 to represent the same transformation as the given float3x3.
602         /// @note The remaining entries of this matrix are set to identity.
603         float4x4 &operator =(const float3x3 &rhs);
604
605         /// Sets this float4x4 to represent the same transformation as the given float3x4.
606         /// @note The remaining entries of this matrix are set to identity.
607         float4x4 &operator =(const float3x4 &rhs);
608
609         float4x4 &operator =(const float4x4 &rhs);
610
611         float4x4 &operator =(const TranslateOp &rhs);
612
613         /// Sets this float4x4 to represent the same rotation as the given Quat.
614         /// @note The remaining entries of this matrix are set to identity.
615         float4x4 &operator =(const Quat &rhs);
616
617         /// Computes the determinant of the upper-left 3x3 submatrix of this matrix.
618         float Determinant3() const;
619
620         /// Computes the determinant of this matrix.
621         /** If the determinant is nonzero, this matrix is invertible.
622                 If the determinant is negative, this matrix performs reflection about some axis.
623                 From http://msdn.microsoft.com/en-us/library/bb204853(VS.85).aspx :
624                 "If the determinant is positive, the basis is said to be "positively" oriented (or right-handed).
625                 If the determinant is negative, the basis is said to be "negatively" oriented (or left-handed)." */
626         float Determinant4() const;
627
628         /// Returns the 3x3 submatrix that results when the row i and column j is removed from this matrix.
629         float3x3 SubMatrix(int i, int j) const;
630
631         /// Returns the determinant of the 3x3 submatrix that results when the row i and column j is removed from this matrix.
632         float Minor(int i, int j) const;
633
634         /// Returns the adjugate of this matrix.
635         float4x4 Adjugate() const;
636
637         /// Computes the Cholesky decomposition of this matrix.
638         /// The returned matrix L satisfies L * transpose(L) = this.
639         /// Returns true on success.
640         bool CholeskyDecompose(float4x4 &outL) const;
641
642         /// Computes the LU decomposition of this matrix.
643         /// This decomposition has the form 'this = L * U'.
644         /// Returns true on success.
645         bool LUDecompose(float4x4 &outLower, float4x4 &outUpper) const;
646
647         /// Inverts this matrix using the generic Gauss's method.
648         /// @return Returns true on success, false otherwise.
649         bool Inverse(float epsilon = 1e-6f);
650
651         /// Returns an inverted copy of this matrix.
652         /// If this matrix does not have an inverse, returns the matrix that was the result of running
653         /// Gauss's method on the matrix.
654         float4x4 Inverted() const;
655
656         /// Inverts a column-orthogonal matrix.
657         /// If a matrix is of form M=T*R*S, where T is an affine translation matrix,
658         /// R is a rotation matrix and S is a diagonal matrix with non-zero but potentially non-uniform scaling
659         /// factors (possibly mirroring), then the matrix M is column-orthogonal and this function can be used to compute the inverse.
660         /// Calling this function is faster than the calling the generic matrix Inverse() function.
661         /// Returns true on success. On failure, the matrix is not modified. This function fails if any of the
662         /// elements of this vector are not finite, or if the matrix contains a zero scaling factor on X, Y or Z.
663         /// This function may not be called if this matrix contains any projection (last row differs from (0 0 0 1)).
664         /// @note The returned matrix will be row-orthogonal, but not column-orthogonal in general.
665         /// The returned matrix will be column-orthogonal iff the original matrix M was row-orthogonal as well.
666         /// (in which case S had uniform scale, InverseOrthogonalUniformScale() could have been used instead)
667         bool InverseColOrthogonal();
668
669         /// Inverts a matrix that is a concatenation of only translate, rotate and uniform scale operations.
670         /// If a matrix is of form M=T*R*S, where T is an affine translation matrix,
671         /// R is a rotation matrix and S is a diagonal matrix with non-zero and uniform scaling factors (possibly mirroring),
672         /// then the matrix M is both column- and row-orthogonal and this function can be used to compute the inverse.
673         /// This function is faster than calling InverseColOrthogonal() or the generic Inverse().
674         /// Returns true on success. On failure, the matrix is not modified. This function fails if any of the
675         /// elements of this vector are not finite, or if the matrix contains a zero scaling factor on X, Y or Z.
676         /// This function may not be called if this matrix contains any shearing or nonuniform scaling.
677         /// This function may not be called if this matrix contains any projection (last row differs from (0 0 0 1)).
678         bool InverseOrthogonalUniformScale();
679
680         /// Inverts a matrix that is a concatenation of only translate and rotate operations.
681         /// If a matrix is of form M=T*R*S, where T is an affine translation matrix, R is a rotation
682         /// matrix and S is either identity or a mirroring matrix, then the matrix M is orthonormal and this function can be used to compute the inverse.
683         /// This function is faster than calling InverseOrthogonalUniformScale(), InverseColOrthogonal() or the
684         /// generic Inverse().
685         /// This function may not be called if this matrix contains any scaling or shearing, but it may contain mirroring.
686         /// This function may not be called if this matrix contains any projection (last row differs from (0 0 0 1)).
687         void InverseOrthonormal();
688
689         /// Transposes this matrix.
690         /// This operation swaps all elements with respect to the diagonal.
691         void Transpose();
692
693         /// Returns a transposed copy of this matrix.
694         float4x4 Transposed() const;
695
696         /// Computes the inverse transpose of this matrix in-place.
697         /** Use the inverse transpose to transform covariant vectors (normal vectors). */
698         bool InverseTranspose();
699
700         /// Returns the inverse transpose of this matrix.
701         /** Use that matrix to transform covariant vectors (normal vectors). */
702         float4x4 InverseTransposed() const;
703
704         /// Returns the sum of the diagonal elements of this matrix.
705         float Trace() const;
706
707         /// Orthogonalizes the basis formed by the column vectors of the 3x3 top-left submatrix of this matrix.
708         /// @param firstColumn The index of the column the direction of which will be preserved, in the range [0-2].
709         /// @param secondColumn The second column to be processed, in the range [0-2].
710         /// @param thirdColumn The third column to be processed, in the range [0-2].
711         /// @note The three integers passed in to this function must be a permutation of the numbers 0, 1 and 2, that is,
712         ///        firstColumn != secondColumn, firstColumn != thirdColumn and secondColumn != thirdColumn.
713         void Orthogonalize3(int firstColumn, int secondColumn, int thirdColumn);
714         void Orthogonalize3() { Orthogonalize3(0, 1, 2); }
715
716         /// Orthonormalizes the basis formed by the column vectors of the 3x3 top-left submatrix of this matrix.
717         /// @param firstColumn The index of the column the direction of which will be preserved, in the range [0-2].
718         /// @param secondColumn The second column to be processed, in the range [0-2].
719         /// @param thirdColumn The third column to be processed, in the range [0-2].
720         /// @note The three integers passed in to this function must be a permutation of the numbers 0, 1 and 2, that is,
721         ///        firstColumn != secondColumn, firstColumn != thirdColumn and secondColumn != thirdColumn.
722         void Orthonormalize3(int firstColumn, int secondColumn, int thirdColumn);
723         void Orthonormalize3() { Orthonormalize3(0, 1, 2); }
724
725         /// Removes the scaling performed by this matrix. That is, decomposes this matrix M into a form M = M' * S, where
726         /// M' has unitary column vectors and S is a diagonal matrix. Then replaces this matrix with M'.
727         /// @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
728         /// @note This function assumes that this matrix has orthogonal basis vectors (row and column vector sets are orthogonal).
729         /// @note This function does not remove reflection (-1 scale along some axis).
730         void RemoveScale();
731
732         /// Reduces this matrix to its row-echelon form.
733         void Pivot();
734
735         /// Transforms the given point vector by this matrix M , i.e. returns M * (x, y, z, 1).
736         /** The suffix "Pos" in this function means that the w component of the input vector is assumed to be 1, i.e. the input
737                 vector represents a point (a position). */
738         float3 TransformPos(const float3 &pointVector) const;
739         float3 TransformPos(float x, float y, float z) const;
740         float4 TransformPos(const float4 &vector) const return Transform(vector); }
741
742         /// Transforms the given direction vector by this matrix M , i.e. returns M * (x, y, z, 0).
743         /** The suffix "Dir" in this function just means that the w component of the input vector is assumed to be 0, i.e. the
744                 input vector represents a direction. The input vector does not need to be normalized. */
745         float3 TransformDir(const float3 &directionVector) const;
746         float3 TransformDir(float x, float y, float z) const;
747         float4 TransformDir(const float4 &vector) const return Transform(vector); }
748
749         /// Transforms the given 4-vector by this matrix M, i.e. returns M * (x, y, z, w).
750         /// Does not perform a perspective divide afterwards, so remember to divide by w afterwards
751         /// at some point, if this matrix contained a projection.
752         float4 Transform(const float4 &vector) const;
753
754         /// Performs a batch transform of the given array of point vectors.
755         /** The suffix "Pos" in this function just means that the w components of each input vector are assumed to be 1, i.e. the
756                 input vectors represent points (positions).
757                 @param strideBytes If specified, represents the distance in bytes between subsequent vector elements. If stride is not
758                         specified, the vectors are assumed to be tightly packed in memory. */
759         void TransformPos(float3 *pointArray, int numPoints) const;
760         void TransformPos(float3 *pointArray, int numPoints, int strideBytes) const;
761
762         /// Performs a batch transform of the given array of direction vectors.
763         /** The suffix "Dir" in this function just means that the w components of each input vector are assumed to be 0, i.e. the
764                 input vectors represent directions. The input vectors do not need to be normalized.
765                 @param strideBytes If specified, represents the distance in bytes between subsequent vector elements. If stride is not
766                         specified, the vectors are assumed to be tightly packed in memory. */
767         void TransformDir(float3 *dirArray, int numVectors) const;
768         void TransformDir(float3 *dirArray, int numVectors, int strideBytes) const;
769
770         /// Performs a batch transform of the given float4 array.
771         /** @param strideBytes If specified, represents the distance in bytes between subsequent vector elements. If stride is not
772                         specified, the vectors are assumed to be tightly packed in memory. */
773         void Transform(float4 *vectorArray, int numVectors) const;
774         void Transform(float4 *vectorArray, int numVectors, int strideBytes) const;
775
776         /// Treats the float3x3 as a 4-by-4 matrix with the last row and column as identity, and multiplies the two matrices.
777         float4x4 operator *(const float3x3 &rhs) const;
778
779         /// Treats the float3x4 as a 4-by-4 matrix with the last row as identity, and multiplies the two matrices.
780         float4x4 operator *(const float3x4 &rhs) const;
781
782         /// Performs standard matrix multiplication.
783         float4x4 operator *(const float4x4 &rhs) const;
784
785         /// Converts the quaternion to a float4x4 and multiplies the two matrices together.
786         float4x4 operator *(const Quat &rhs) const;
787
788         /// Transforms the given vector by this matrix (in the order M * v).
789         float4 operator *(const float4 &rhs) const;
790
791         float4x4 operator *(float scalar) const;
792         float4x4 operator /(float scalar) const;
793         float4x4 operator +(const float4x4 &rhs) const;
794         float4x4 operator -(const float4x4 &rhs) const;
795         float4x4 operator -() const;
796
797         /// Unary operator + allows this structure to be used in an expression '+x'.
798         float4x4 operator +() const return *this; }
799
800         float4x4 &operator *=(float scalar);
801         float4x4 &operator /=(float scalar);
802         float4x4 &operator +=(const float4x4 &rhs);
803         float4x4 &operator -=(const float4x4 &rhs);
804
805         /// Tests if this matrix does not contain any NaNs or infs.
806         /** @return Returns true if the entries of this float4x4 are all finite, and do not contain NaN or infs. */
807         bool IsFinite() const;
808
809         /// Tests if this is the identity matrix.
810         /** @return Returns true if this matrix is the identity matrix, up to the given epsilon. */
811         bool IsIdentity(float epsilon = 1e-3f) const;
812
813         /// Tests if this matrix is in lower triangular form.
814         /** @return Returns true if this matrix is in lower triangular form, up to the given epsilon. */
815         bool IsLowerTriangular(float epsilon = 1e-3f) const;
816
817         /// Tests if this matrix is in upper triangular form.
818         /** @return Returns true if this matrix is in upper triangular form, up to the given epsilon. */
819         bool IsUpperTriangular(float epsilon = 1e-3f) const;
820
821         /// Tests if this matrix has an inverse.
822         /** @return Returns true if this matrix can be inverted, up to the given epsilon. */
823         bool IsInvertible(float epsilon = 1e-3f) const;
824
825         /// Tests if this matrix is symmetric (M == M^T).
826         /** The test compares the elements for equality, up to the given epsilon. A matrix is symmetric if it is its own transpose. */
827         bool IsSymmetric(float epsilon = 1e-3f) const;
828
829         /// Tests if this matrix is skew-symmetric (M == -M^T).
830         /** The test compares the floating point elements of this matrix up to the given epsilon. A matrix M is skew-symmetric
831                 the identity M=-M^T holds. */
832         bool IsSkewSymmetric(float epsilon = 1e-3f) const;
833
834         /// Tests if this matrix is an idempotent matrix.
835         /// An idempotent matrix is one for which the equality M*M=M holds. Projection matrices are commonly idempotent.
836         bool IsIdempotent(float epsilon = 1e-3f) const;
837
838         /// Returns true if this matrix does not perform any scaling.
839         /** A matrix does not do any scaling if the column vectors of this
840                 matrix are normalized in length, compared to the given epsilon. Note that this matrix may still perform
841                 reflection, i.e. it has a -1 scale along some axis.
842                 @note This function only examines the upper 3-by-3 part of this matrix.
843                 @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]). */
844         bool HasUnitaryScale(float epsilon = 1e-3f) const;
845
846         /// Returns true if this matrix performs a reflection along some plane.
847         /** In 3D space, an even number of reflections corresponds to a rotation about some axis, so a matrix consisting of
848                 an odd number of consecutive mirror operations can only reflect about one axis. A matrix that contains reflection reverses
849                 the handedness of the coordinate system. This function tests if this matrix
850                 does perform mirroring. This occurs iff this matrix has a negative determinant. */
851         bool HasNegativeScale() const;
852
853         /// Returns true if this matrix contains only uniform scaling, compared to the given epsilon.
854         /// @note If the matrix does not really do any scaling, this function returns true (scaling uniformly by a factor of 1).
855         /// @note This function only examines the upper 3-by-3 part of this matrix.
856         /// @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
857         bool HasUniformScale(float epsilon = 1e-3f) const;
858
859         /// Returns true if the row vectors of 3x3 top-left submatrix are all perpendicular to each other.
860         bool IsRowOrthogonal3(float epsilon = 1e-3f) const;
861
862         /// Returns true if the column vectors of 3x3 top-left submatrix are all perpendicular to each other.
863         bool IsColOrthogonal3(float epsilon = 1e-3f) const;
864
865         /// Returns true if the column and row vectors of the 3x3 top-left submatrix form an orthonormal set.
866         /// @note In math terms, there does not exist such a thing as 'orthonormal matrix'. In math terms,
867         /// a matrix is orthogonal iff its column and row vectors are orthogonal *unit* vectors.
868         /// In the terms of this library however, a matrix is orthogonal iff its column and row vectors are orthogonal (no need to be unitary),
869         /// and a matrix is orthonormal if the column and row vectors are orthonormal.
870         bool IsOrthonormal3(float epsilon = 1e-3f) const;
871
872         /// Returns true if this float4x4 is equal to the given float4x4, up to given per-element epsilon.
873         bool Equals(const float4x4 &other, float epsilon = 1e-3f) const;
874
875         /// Returns true if this matrix is seen to contain a "projective" part, i.e. whether the last row of this
876         /// matrix differs from [0 0 0 1].
877         bool ContainsProjection(float epsilon = 1e-3f) const;
878
879 #ifdef MATH_ENABLE_STL_SUPPORT
880         /// Returns a string representation of form "(m00, m01, m02, m03; m10, m11, m12, m13; ... )".
881         std::string ToString() const;
882         std::string SerializeToString() const;
883
884         std::string ToString2() const;
885 #endif
886
887         /// Extracts the rotation part of this matrix into Euler rotation angles (in radians). [indexTitle: ToEuler***]
888         /// @note It is better to think about the returned float3 as an array of three floats, and
889         /// not as a triple of xyz, because e.g. the .y component returned by ToEulerYXZ() does
890         /// not return the amount of rotation about the y axis, but contains the amount of rotation
891         /// in the second axis, in this case the x axis.
892         float3 ToEulerXYX() const;
893         float3 ToEulerXZX() const///< [similarOverload: ToEulerXYX] [hideIndex]
894         float3 ToEulerYXY() const///< [similarOverload: ToEulerXYX] [hideIndex]
895         float3 ToEulerYZY() const///< [similarOverload: ToEulerXYX] [hideIndex]
896         float3 ToEulerZXZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
897         float3 ToEulerZYZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
898         float3 ToEulerXYZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
899         float3 ToEulerXZY() const///< [similarOverload: ToEulerXYX] [hideIndex]
900         float3 ToEulerYXZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
901         float3 ToEulerYZX() const///< [similarOverload: ToEulerXYX] [hideIndex]
902         float3 ToEulerZXY() const///< [similarOverload: ToEulerXYX] [hideIndex]
903         float3 ToEulerZYX() const///< [similarOverload: ToEulerXYX] [hideIndex]
904
905         /// Returns the scale components of this matrix.
906         /** This function decomposes this matrix M into a form M = M' * S, where M' has unitary column vectors and S is a diagonal matrix.
907                 @return ExtractScale returns the diagonal entries of S, i.e. the scale of the columns of this matrix . If this matrix
908                 represents a local->world space transformation for an object, then this scale represents a 'local scale', i.e.
909                 scaling that is performed before translating and rotating the object from its local coordinate system to its world
910                 position.
911                 @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
912                 @note This function does not detect and return reflection (-1 scale along some axis). */
913         float3 ExtractScale() const;
914
915         /// Decomposes this matrix to translate, rotate and scale parts.
916         /** This function decomposes this matrix M to a form M = T * R * S, where T is a translation matrix, R a rotation matrix and S a
917                 scale matrix.
918                 @note Remember that in the convention of this class, transforms are applied in the order M * v, so scale is
919                 applied first, then rotation, and finally the translation last.
920                 @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
921                 @param translate [out] This vector receives the translation component this matrix performs. The translation is applied last
922                         after rotation and scaling.
923                 @param rotate [out] This object receives the rotation part of this transform.
924                 @param scale [out] This vector receives the scaling along the local (before transformation by R) X, Y and Z axes
925                         performed by this matrix. */
926         void Decompose(float3 &translate, Quat &rotate, float3 &scale) const;
927         void Decompose(float3 &translate, float3x3 &rotate, float3 &scale) const;
928         void Decompose(float3 &translate, float3x4 &rotate, float3 &scale) const;
929         void Decompose(float3 &translate, float4x4 &rotate, float3 &scale) const;
930
931         /// Computes a new matrix with each element of this matrix replaced with their absolute value.
932         float4x4 Abs() const;
933
934 #ifdef MATH_OGRE_INTEROP
935         float4x4(const Ogre::Matrix4 &m) { Set(&m[0][0]); }
936         operator Ogre::Matrix4() { return Ogre::Matrix4(v[0][0], v[0][1], v[0][2], v[0][3], v[1][0], v[1][1], v[1][2], v[1][3], v[2][0], v[2][1], v[2][2], v[2][3], v[3][0], v[3][1], v[3][2], v[3][3]); }
937 #endif
938 #ifdef MATH_QT_INTEROP
939         float4x4(const QMatrix4x4 &m) { Set(m(0,0), m(0,1), m(0,2), m(0,3), m(1,0), m(1,1), m(1,2), m(1,3), m(2,0), m(2,1), m(2,2), m(2,3), m(3,0), m(3,1), m(3,2), m(3,3)); }
940         operator QMatrix4x4() const return QMatrix4x4(v[0][0], v[0][1], v[0][2], v[0][3], v[1][0], v[1][1], v[1][2], v[1][3], v[2][0], v[2][1], v[2][2], v[2][3], v[3][0], v[3][1], v[3][2], v[3][3]); }
941         operator QString() const return toString(); }
942         QString toString() const return ToString2().c_str(); }
943         QMatrix4x4 ToQMatrix4x4() const return (QMatrix4x4)*this; }
944         static float4x4 FromQMatrix4x4(const QMatrix4x4 &m) { return (float4x4)m; }
945 #endif
946 #ifdef MATH_URHO3D_INTEROP
947         float4x4(const Urho3D::Matrix4 &m) { Set(m.m00_, m.m01_, m.m02_, m.m03_, m.m10_, m.m11_, m.m12_, m.m13_, m.m20_, m.m21_, m.m22_, m.m23_, m.m30_, m.m31_, m.m32_, m.m33_); }
948         operator Urho3D::Matrix4() { return Urho3D::Matrix4(ptr()); }
949 #endif
950
951         float4x4 Mul(const float3x3 &rhs) const;
952         float4x4 Mul(const float3x4 &rhs) const;
953         float4x4 Mul(const float4x4 &rhs) const;
954         float4x4 Mul(const Quat &rhs) const;
955         float3 MulPos(const float3 &pointVector) const;
956         inline float4 MulPos(const float4 &pointVector) const assume(!EqualAbs(pointVector.w, 0.f)); return Mul(pointVector); }
957         float3 MulDir(const float3 &directionVector) const;
958         inline float4 MulDir(const float4 &directionVector) const assume(EqualAbs(directionVector.w, 0.f)); return Mul(directionVector); }
959         float4 Mul(const float4 &vector) const;
960 };
961
962 #ifdef MATH_ENABLE_STL_SUPPORT
963 /// Prints this float4x4 to the given stream.
964 std::ostream &operator <<(std::ostream &out, const float4x4 &rhs);
965 #endif
966
967 /// Multiplies two transforms together.
968 float4x4 operator *(const Quat &lhs, const float4x4 &rhs);
969 float4x4 operator *(const float3x4 &lhs, const float4x4 &rhs);
970 float4x4 operator *(const float3x3 &lhs, const float4x4 &rhs);
971
972 /// Transforms the given vector by the given matrix in the order v * M. Note that this form
973 /// of multiplication is against the convention of this math system. Please use the M * v notation instead.
974 /// (Remember that M * v != v * M in general).
975 float4 operator *(const float4 &lhs, const float4x4 &rhs);
976
977 #ifdef MATH_QT_INTEROP
978 Q_DECLARE_METATYPE(float4x4)
979 Q_DECLARE_METATYPE(float4x4*)
980 #endif
981
982 #ifdef MATH_SIMD
983 template<>
984 inline float4x4 *AlignedNew<float4x4>(size_t numElements) { return AlignedNew<float4x4>(numElements, MAT_ALIGNMENT); }
985 #endif
986
987 MATH_END_NAMESPACE

Go back to previous page