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 float3x3.h
16         @author Jukka Jyl�nki
17         @brief A 3-by-3 matrix for linear operations in 3D space. */
18 #pragma once
19
20 #ifdef MATH_ENABLE_STL_SUPPORT
21 #include <ostream>
22 #include "myassert.h"
23 #endif
24
25 #include "../MathGeoLibFwd.h"
26 #include "MatrixProxy.h"
27 #include "../Math/float3.h"
28
29 #ifdef MATH_OGRE_INTEROP
30 #include <OgreMatrix3.h>
31 #endif
32 #ifdef MATH_BULLET_INTEROP
33 #include <LinearMath/btMatrix3x3.h>
34 #endif
35 #ifdef MATH_URHO3D_INTEROP
36 #include <Urho3D/Math/Matrix3.h>
37 #endif
38
39 MATH_BEGIN_NAMESPACE
40
41 /// A 3-by-3 matrix for linear transformations of 3D geometry.
42 /** This matrix can represent any kind of linear transformations of 3D geometry, which include rotation,
43         scale, shear, mirroring and orthographic projection. A 3x3 matrix cannot represent translation (which requires
44         a 3x4 matrix), or perspective projection (which requires a 4x4 matrix).
45
46         The elements of this matrix are
47
48                 m_00, m_01, m_02
49                 m_10, m_11, m_12
50                 m_20, m_21, m_22
51
52         The element m_yx is the value on the row y and column x.
53         You can access m_yx using the double-bracket notation m[y][x], or using the member function m.At(y, x);
54
55         @note The member functions in this class use the convention that transforms are applied to vectors in the form
56         M * v. This means that "float3x3 M, M1, M2; M = M1 * M2;" gives a transformation M that applies M2 first, followed
57         by M1 second, i.e. M * v = M1 * M2 * v = M1 * (M2 * v). This is the convention commonly used with OpenGL. The
58         opposing convention (v * M) is commonly used with Direct3D.
59
60         @note This class uses row-major storage, which means that the elements are packed in memory in order
61          m[0][0], m[0][1], m[0][2], m[0][3], m[1][0], m[1][1], ...
62         The elements for a single row of the matrix hold successive memory addresses. This is the same memory layout as
63          with C++ multidimensional arrays.
64
65         Contrast this with column-major storage, in which the elements are packed in the memory in
66         order m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], ...
67         There the elements for a single column of the matrix hold successive memory addresses.
68         This is exactly opposite from the standard C++ multidimensional arrays, since if you have e.g.
69         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], ...) */
70 class float3x3
71 {
72 public:
73         /// Specifies the height of this matrix.
74         enum { Rows = 3 };
75
76         /// Specifies the width of this matrix.
77         enum { Cols = 3 };
78
79         /// Stores the data in this matrix in row-major format. [noscript]
80         float v[Rows][Cols];
81
82         /// A constant matrix that has zeroes in all its entries.
83         static const float3x3 zero;
84
85         /// A constant matrix that is the identity.
86         /** The identity matrix looks like the following:
87                    1 0 0
88                    0 1 0
89                    0 0 1
90                 Transforming a vector by the identity matrix is like multiplying a number by one, i.e. the vector is not changed. */
91         static const float3x3 identity;
92
93         /// A compile-time constant float3x3 which has NaN in each element.
94         /// For this constant, each element has the value of quiet NaN, or Not-A-Number.
95         /// @note Never compare a float3x3 to this value! Due to how IEEE floats work, "nan == nan" returns false!
96         ///    That is, nothing is equal to NaN, not even NaN itself!
97         static const float3x3 nan;
98
99         /// Creates a new float3x3 with uninitialized member values.
100         /** [opaque-qtscript] */
101         float3x3() {}
102
103 #ifdef MATH_EXPLICIT_COPYCTORS
104         /// The copy-ctor for float3x3 is the trivial copy-ctor, but it is explicitly written to be able to automatically
105         /// pick up this function for QtScript bindings.
106         float3x3(const float3x3 &rhs) { Set(rhs); }
107 #endif
108
109         /// Constructs a new float3x3 by explicitly specifying all the matrix elements.
110         /// The elements are specified in row-major format, i.e. the first row first followed by the second and third row.
111         /// E.g. The element _10 denotes the scalar at second (index 1) row, first (index 0) column.
112         float3x3(float _00, float _01, float _02,
113                          float _10, float _11, float _12,
114                          float _20, float _21, float _22);
115
116         /// Constructs the matrix by explicitly specifying the four column vectors.
117         /** @param col0 The first column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
118                 direction of the local X axis.
119                 @param col1 The second column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
120                 direction of the local Y axis.
121                 @param col2 The third column. If this matrix represents a change-of-basis transformation, this parameter is the world-space
122                 direction of the local Z axis. */
123         float3x3(const float3 &col0, const float3 &col1, const float3 &col2);
124
125         /// Constructs this float3x3 from the given quaternion.
126         explicit float3x3(const Quat &orientation);
127
128         /// Creates a new float3x3 that rotates about one of the principal axes by the given angle. [indexTitle: RotateX/Y/Z]
129         /** Calling RotateX, RotateY or RotateZ is slightly faster than calling the more generic RotateAxisAngle function. */
130         static float3x3 RotateX(float angleRadians);
131         /** [similarOverload: RotateX] [hideIndex] */
132         static float3x3 RotateY(float angleRadians);
133         /** [similarOverload: RotateX] [hideIndex] */
134         static float3x3 RotateZ(float angleRadians);
135
136         /// Creates a new float3x3 that rotates about the given axis by the given angle.
137         static float3x3 RotateAxisAngle(const float3 &axisDirection, float angleRadians);
138
139         /// Creates a matrix that rotates the sourceDirection vector to coincide with the targetDirection vector.
140         /** Both input direction vectors must be normalized.
141                 @note There are infinite such rotations - this function returns the rotation that has the shortest angle
142                 (when decomposed to axis-angle notation).
143                 @return An orthonormal matrix M with a determinant of +1. For the matrix M it holds that
144                         M * sourceDirection = targetDirection. */
145         static float3x3 RotateFromTo(const float3 &sourceDirection, const float3 &targetDirection);
146
147         /// Creates a LookAt matrix.
148         /** A LookAt matrix is a rotation matrix that orients an object to face towards a specified target direction.
149                 @param localForward Specifies the forward direction in the local space of the object. This is the direction
150                         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
151                         vector to pass in here depends on the conventions you or your modeling software is using, and it is best
152                         pick one convention for all your objects, and be consistent.                    
153                         This input parameter must be a normalized vector.
154                 @param targetDirection Specifies the desired world space direction the object should look at. This function
155                         will compute a rotation matrix which will rotate the localForward vector to orient towards this targetDirection
156                         vector. This input parameter must be a normalized vector.
157                 @param localUp Specifies the up direction in the local space of the object. This is the up direction the model
158                         was authored in, often +Y (0,1,0) or +Z (0,0,1). The vector to pass in here depends on the conventions you
159                         or your modeling software is using, and it is best to pick one convention for all your objects, and be
160                         consistent. This input parameter must be a normalized vector. This vector must be perpendicular to the
161                         vector localForward, i.e. localForward.Dot(localUp) == 0.
162                 @param worldUp Specifies the global up direction of the scene in world space. Simply rotating one vector to
163                         coincide with another (localForward->targetDirection) would cause the up direction of the resulting
164                         orientation to drift (e.g. the model could be looking at its target its head slanted sideways). To keep
165                         the up direction straight, this function orients the localUp direction of the model to point towards the
166                         specified worldUp direction (as closely as possible). The worldUp and targetDirection vectors cannot be
167                         collinear, but they do not need to be perpendicular either.
168                 @return A matrix that maps the given local space forward direction vector to point towards the given target
169                         direction, and the given local up direction towards the given target world up direction. This matrix can be
170                         used as the 'world transform' of an object. The returned matrix M is orthonormal with a determinant of +1. 
171                         For the matrix M it holds that M * localForward = targetDirection, and M * localUp lies in the plane spanned by 
172                         the vectors targetDirection and worldUp.
173                 @see RotateFromTo().
174                 @note Be aware that the convention of a 'LookAt' matrix in MathGeoLib differs from e.g. GLM. In MathGeoLib, the returned
175                         matrix is a mapping from local space to world space, meaning that the returned matrix can be used as the 'world transform'
176                         for any 3D object (camera or not). The view space is the local space of the camera, so this function returns the mapping
177                         view->world. In GLM, the LookAt function is tied to cameras only, and it returns the inverse mapping world->view. */
178         static float3x3 LookAt(const float3 &localForward, const float3 &targetDirection, const float3 &localUp, const float3 &worldUp);
179
180         /// Returns a uniformly random 3x3 matrix that performs only rotation.
181         /** This matrix produces a random orthonormal basis for an orientation of an object. There is no mirroring
182                 or scaling present in the generated matrix. Also, naturally since float3x3 cannot represent translation or projection,
183                 those properties are not present either. */
184         static float3x3 RandomRotation(LCG &lcg);
185
186         /// Returns a random 3x3 matrix with each entry randomized between the range[minElem, maxElem].
187         /** Warning: The matrices returned by this function do not represent well-formed 3D transformations.
188                 This function is mostly used for testing and debugging purposes only. */
189         static float3x3 RandomGeneral(LCG &lcg, float minElem, float maxElem);
190
191         /// Creates a new float3x3 that performs the rotation expressed by the given quaternion.
192         static float3x3 FromQuat(const Quat &orientation);
193
194         /// Converts this rotation matrix to a quaternion.
195         /// This function assumes that the matrix is orthonormal (no shear or scaling) and does not perform any mirroring (determinant > 0).
196         Quat ToQuat() const;
197
198         /// Creates a new float3x3 as a combination of rotation and scale.
199         /** This function creates a new float3x3 M of the form M = R * S, where R is a
200                 rotation matrix and S a scale matrix. Transforming a vector v using this matrix computes the vector
201                 v' == M * v == R*S*v == (R * (S * v)), which means that the scale operation is applied to the
202                 vector first, followed by rotation and finally translation. */
203         static float3x3 FromRS(const Quat &rotate, const float3 &scale);
204         static float3x3 FromRS(const float3x3 &rotate, const float3 &scale);
205
206         /// Creates a new float3x3 from the given sequence of Euler rotation angles (in radians).
207         /** The FromEulerABC function returns a matrix M = A(ea) * B(eb) * C(ec). Rotation
208                 C is applied first, followed by B and then A. [indexTitle: FromEuler***] */
209         static float3x3 FromEulerXYX(float ex, float ey, float ex2);
210         static float3x3 FromEulerXZX(float ex, float ez, float ex2); ///< [similarOverload: FromEulerXYX] [hideIndex]
211         static float3x3 FromEulerYXY(float ey, float ex, float ey2); ///< [similarOverload: FromEulerXYX] [hideIndex]
212         static float3x3 FromEulerYZY(float ey, float ez, float ey2); ///< [similarOverload: FromEulerXYX] [hideIndex]
213         static float3x3 FromEulerZXZ(float ez, float ex, float ez2); ///< [similarOverload: FromEulerXYX] [hideIndex]
214         static float3x3 FromEulerZYZ(float ez, float ey, float ez2); ///< [similarOverload: FromEulerXYX] [hideIndex]
215         static float3x3 FromEulerXYZ(float ex, float ey, float ez); ///< [similarOverload: FromEulerXYX] [hideIndex]
216         static float3x3 FromEulerXZY(float ex, float ez, float ey); ///< [similarOverload: FromEulerXYX] [hideIndex]
217         static float3x3 FromEulerYXZ(float ey, float ex, float ez); ///< [similarOverload: FromEulerXYX] [hideIndex]
218         static float3x3 FromEulerYZX(float ey, float ez, float ex); ///< [similarOverload: FromEulerXYX] [hideIndex]
219         static float3x3 FromEulerZXY(float ez, float ex, float ey); ///< [similarOverload: FromEulerXYX] [hideIndex]
220         static float3x3 FromEulerZYX(float ez, float ey, float ex); ///< [similarOverload: FromEulerXYX] [hideIndex]
221
222         /// Creates a new transformation matrix that scales by the given factors.
223         /// This matrix scales with respect to origin.
224         static ScaleOp Scale(float sx, float sy, float sz);
225         static ScaleOp Scale(const float3 &scale);
226
227         /// Creates a new float3x3 that scales points along the given axis.
228         /** @param axis A normalized direction vector that specifies the direction of scaling.
229                 @param scalingFactor The amount of scaling to apply along the specified axis. */
230         static float3x3 ScaleAlongAxis(const float3 &axis, float scalingFactor);
231
232         /// Creates a new float3x3 that performs uniform scaling by the given amount.
233         static ScaleOp UniformScale(float uniformScale);
234
235         /// Returns the scaling performed by this matrix.
236         /// GetScale().x specifies the amount of scaling applied to the local x direction vector when it is transformed by this matrix.
237         /// i.e. GetScale()[i] equals Col(i).Length();
238         float3 GetScale() const;
239
240         /// Produces a matrix that shears along a principal axis.
241         /** The shear matrix offsets the two other axes according to the
242                 position of the point along the shear axis. [indexTitle: ShearX/Y/Z] */
243         static float3x3 ShearX(float yFactor, float zFactor);
244         static float3x3 ShearY(float xFactor, float zFactor); ///< [similarOverload: ShearX] [hideIndex]
245         static float3x3 ShearZ(float xFactor, float yFactor); ///< [similarOverload: ShearX] [hideIndex]
246
247         /// Creates a new matrix that mirrors with respect to the given plane.
248         /** 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
249                 they were. */
250         static float3x3 Mirror(const Plane &p);
251
252         /// Creates a new float3x3 that performs orthographic projection. [indexTitle: OrthographicProjection/YZ/XZ/XY]
253         static float3x3 OrthographicProjection(const Plane &target);
254         static float3x3 OrthographicProjectionYZ(); ///< [similarOverload: OrthographicProjection] [hideIndex]
255         static float3x3 OrthographicProjectionXZ(); ///< [similarOverload: OrthographicProjection] [hideIndex]
256         static float3x3 OrthographicProjectionXY(); ///< [similarOverload: OrthographicProjection] [hideIndex]
257
258         /// Computes the covariance matrix of the given set of data points.
259 //      static float3x3 CovarianceMatrix(const float3 *pointArray, int numPoints);
260
261         /// Returns the given element. [noscript]
262         /** Returns a reference to the element at m[row][col] (or "m[y][x]").
263                 Remember that zero-based indexing is used, so m[0][0] is the upper-left element of this matrix.
264                 @note You can use the index notation to set elements of the matrix, e.g. m[0][1] = 5.f;
265                 @note MatrixProxy is a temporary helper class. Do not store references to it, but always
266                 directly dereference it with the [] operator.
267                 For example, m[0][2] Returns the last element on the first row. */
268         MatrixProxy<Cols> &operator[](int row);
269         const MatrixProxy<Cols> &operator[](int row) const;
270
271         /// Returns the given element. [noscript]
272         /** This function returns the element of this matrix at (row, col)==(i, j)==(y, x).
273                 If you have a non-const object, you can set values of this matrix through this
274                 reference, using the notation m.At(row, col) = someValue; */
275         float &At(int row, int col);
276         CONST_WIN32 float At(int row, int col) const;
277
278         /// Returns the given row. [noscript]
279         /** @param row The zero-based index [0, 2] of the row to get. */
280         float3 &Row(int row);
281         const float3 &Row(int row) const;
282
283         float3 &Row3(int row) { return Row(row); }
284         const float3 &Row3(int row) const return Row(row); }
285
286         /// Returns the given column.
287         /** @param col The zero-based index [0, 2] of the column to get. */
288         CONST_WIN32 float3 Col(int col) const;
289         CONST_WIN32 float3 Col3(int col) const return Col(col); }
290
291         /// Returns the main diagonal.
292         /** The main diagonal consists of the elements at m[0][0], m[1][1], m[2][2]. */
293         CONST_WIN32 float3 Diagonal() const;
294
295         /// Scales the given row by a scalar.
296         void ScaleRow(int row, float scalar);
297
298         /// Scales the given column by a scalar.
299         void ScaleCol(int col, float scalar);
300
301         // Returns the local right axis in the post-transformed coordinate space, according to the given convention.
302         // @note The returned vector might not be normalized if this matrix contains scaling.
303         // @note The basis returned by (Right, Up, Forward) might not be of the same handedness as the
304         //         pre-transformed coordinate system, if the matrix contained reflection.
305 //      template<typename Convention = XposRight_YposUp_ZposForward> float3 Right() const;
306
307         // Returns the local up axis in the post-transformed coordinate space, according to the given convention.
308         // @note The returned vector might not be normalized if this matrix contains scaling.
309         // @note The basis returned by (Right, Up, Forward) might not be of the same handedness as the
310         //         pre-transformed coordinate system, if the matrix contained reflection.
311 //      template<typename Convention = XposRight_YposUp_ZposForward> float3 Up() const;
312
313         // Returns the local forward axis in the post-transformed coordinate space, according to the given convention.
314         // @note The returned vector might not be normalized if this matrix contains scaling.
315         // @note The basis returned by (Right, Up, Forward) might not be of the same handedness as the
316         //         pre-transformed coordinate system, if the matrix contained reflection.
317 //      template<typename Convention = XposRight_YposUp_ZposForward> float3 Forward() const;
318
319         /// Returns the local +X/+Y/+Z axis in world space.
320         /** This is the same as transforming the vector (1,0,0) by this matrix. [indexTitle: PositiveX/Y/Z] */
321         float3 WorldX() const;
322         /// Returns the local +Y axis in world space.
323         /** This is the same as transforming the vector (0,1,0) by this matrix. [similarOverload: PositiveX] [hideIndex] */
324         float3 WorldY() const;
325         /// Returns the local +Z axis in world space.
326         /** This is the same as transforming the vector (0,0,1) by this matrix. [similarOverload: PositiveX] [hideIndex] */
327         float3 WorldZ() const;
328
329         /// Accesses this structure as a float array.
330         /// @return A pointer to the upper-left element. The data is contiguous in memory.
331         /// ptr[0] gives the element [0][0], ptr[1] is [0][1], ptr[2] is [0][2].
332         /// ptr[4] == [1][0], ptr[5] == [1][1], ..., and finally, ptr[15] == [3][3].
333         FORCE_INLINE float *ptr() { return &v[0][0]; }
334         FORCE_INLINE const float *ptr() const return &v[0][0]; }
335
336         /// Sets the values of the given row.
337         /** @param row The index of the row to set, in the range [0-2].
338                 @param data A pointer to an array of 3 floats that contain the new x, y and z values for the row. */
339         void SetRow(int row, const float *data);
340         void SetRow(int row, float x, float y, float z);
341         void SetRow(int row, const float3 &rowVector);
342
343         /// Sets the values of the given column.
344         /** @param column The index of the column to set, in the range [0-2].
345                 @param data A pointer to an array of 3 floats that contain the new x, y and z values for the column. */
346         void SetCol(int column, const float *data);
347         void SetCol(int column, float x, float y, float z);
348         void SetCol(int column, const float3 &columnVector);
349
350         /// Sets all values of this matrix.
351         void Set(float _00, float _01, float _02,
352                          float _10, float _11, float _12,
353                          float _20, float _21, float _22);
354
355         /// Sets this to be a copy of the matrix rhs.
356         void Set(const float3x3 &rhs);
357
358         /// Sets all values of this matrix.
359         /// @param values The values in this array will be copied over to this matrix. The source must contain 9 floats in row-major order (the same
360         ///             order as the Set() function above has its input parameters in).
361         void Set(const float *values);
362
363         /// Sets a single element of this matrix.
364         /** @param row The row index (y-coordinate) of the element to set, in the range [0-2].
365                 @param col The col index (x-coordinate) of the element to set, in the range [0-2].
366                 @param value The new value to set to the cell [row][col]. */
367         void Set(int row, int col, float value);
368
369         /// Sets this matrix to equal the identity.
370         void SetIdentity();
371
372         /// Swaps two columns.
373         void SwapColumns(int col1, int col2);
374
375         /// Swaps two rows.
376         void SwapRows(int row1, int row2);
377
378         /// Sets this matrix to perform rotation about the positive X axis which passes through
379         /// the origin. [similarOverload: SetRotatePart] [hideIndex]
380         void SetRotatePartX(float angleRadians);
381         /// Sets this matrix to perform rotation about the positive Y axis. [similarOverload: SetRotatePart] [hideIndex]
382         void SetRotatePartY(float angleRadians);
383         /// Sets this matrix to perform rotation about the positive Z axis. [similarOverload: SetRotatePart] [hideIndex]
384         void SetRotatePartZ(float angleRadians);
385
386         /// Sets this matrix to perform rotation about the given axis and angle. [indexTitle: SetRotatePart/X/Y/Z]
387         void SetRotatePart(const float3 &axisDirection, float angleRadians);
388         /// Sets this matrix to perform the rotation expressed by the given quaternion.
389         void SetRotatePart(const Quat &orientation);
390
391         float3x3 &operator =(const Quat &rhs);
392         float3x3 &operator =(const float3x3 &rhs);
393
394         /// Computes the determinant of this matrix.
395         /** If the determinant is nonzero, this matrix is invertible.
396                 If the determinant is negative, this matrix performs reflection about some axis.
397                 From http://msdn.microsoft.com/en-us/library/bb204853(VS.85).aspx :
398                 "If the determinant is positive, the basis is said to be "positively" oriented (or right-handed).
399                 If the determinant is negative, the basis is said to be "negatively" oriented (or left-handed)."
400                 @note This function computes 9 LOADs, 9 MULs and 5 ADDs. */
401         float Determinant() const;
402
403         /// Computes the determinant of a symmetric matrix.
404         /** This function can be used to compute the determinant of a matrix in the case the matrix is known beforehand
405                 to be symmetric. This function is slightly faster than Determinant().
406                 @note This function computes 6 LOADs, 9 MULs and 4 ADDs. */
407         float DeterminantSymmetric() const;
408
409 //      float2x2 SubMatrix(int i, int j) const;
410
411         /// Returns the adjugate of this matrix.
412 //      float3x3 Adjugate() const;
413
414         /// Inverts this matrix using numerically stable Gaussian elimination.
415         /// @return Returns true on success, false otherwise.
416         bool Inverse(float epsilon = 1e-6f);
417
418         /// Inverts this matrix using Cramer's rule.
419         /// @return Returns true on success, false otherwise.
420         bool InverseFast(float epsilon = 1e-6f);
421
422         /// Solves the linear equation Ax=b.
423         /** The matrix A in the equations is this matrix. */
424         bool SolveAxb(float3 b, float3 &x) const;
425
426         /// Returns an inverted copy of this matrix. This function uses the Cramer's rule.
427         /// If this matrix does not have an inverse, returns the matrix that was the result of running
428         /// Gauss's method on the matrix.
429         float3x3 Inverted() const;
430
431         /// Inverts a column-orthogonal matrix.
432         /// If a matrix is of form M=R*S, where
433         /// R is a rotation matrix and S is a diagonal matrix with non-zero but potentially non-uniform scaling
434         /// factors (possibly mirroring), then the matrix M is column-orthogonal and this function can be used to compute the inverse.
435         /// Calling this function is faster than the calling the generic matrix Inverse() function.
436         /// Returns true on success. On failure, the matrix is not modified. This function fails if any of the
437         /// elements of this vector are not finite, or if the matrix contains a zero scaling factor on X, Y or Z.
438         /// @note The returned matrix will be row-orthogonal, but not column-orthogonal in general.
439         /// The returned matrix will be column-orthogonal iff the original matrix M was row-orthogonal as well.
440         /// (in which case S had uniform scale, InverseOrthogonalUniformScale() could have been used instead)
441         bool InverseColOrthogonal();
442
443         /// Inverts a matrix that is a concatenation of only rotate and uniform scale operations.
444         /// If a matrix is of form M=R*S, where
445         /// R is a rotation matrix and S is a diagonal matrix with non-zero and uniform scaling factors (possibly mirroring),
446         /// then the matrix M is both column- and row-orthogonal and this function can be used to compute the inverse.
447         /// This function is faster than calling InverseColOrthogonal() or the generic Inverse().
448         /// Returns true on success. On failure, the matrix is not modified. This function fails if any of the
449         /// elements of this vector are not finite, or if the matrix contains a zero scaling factor on X, Y or Z.
450         /// This function may not be called if this matrix contains any shearing or nonuniform scaling.
451         bool InverseOrthogonalUniformScale();
452
453         /// Inverts a rotation matrix.
454         /// If a matrix is of form M=R*S, where R is a rotation matrix and S is either identity or a mirroring matrix, then
455         /// the matrix M is orthonormal and this function can be used to compute the inverse.
456         /// This function is faster than calling InverseOrthogonalUniformScale(), InverseColOrthogonal() or the
457         /// generic Inverse().
458         /// This function may not be called if this matrix contains any scaling or shearing, but it may contain mirroring.
459         void InverseOrthonormal();
460
461         /// Inverts a symmetric matrix.
462         /** This function is faster than directly calling Inverse().
463                 This function computes 6 LOADs, 9 STOREs, 21 MULs, 1 DIV, 1 CMP and 8 ADDs.
464                 @return True if computing the inverse succeeded, false otherwise (determinant was zero). If this function fails,
465                         the original matrix is not modified.
466                 @note This function operates in-place. */
467         bool InverseSymmetric();
468
469         /// Transposes this matrix.
470         /// This operation swaps all elements with respect to the diagonal.
471         void Transpose();
472
473         /// Returns a transposed copy of this matrix.
474         float3x3 Transposed() const;
475
476         /// Computes the inverse transpose of this matrix in-place.
477         /** Use the inverse transpose to transform covariant vectors (normal vectors). */
478         bool InverseTranspose();
479
480         /// Returns the inverse transpose of this matrix.
481         /** Use that matrix to transform covariant vectors (normal vectors). */
482         float3x3 InverseTransposed() const;
483
484         /// Returns the sum of the diagonal elements of this matrix.
485         float Trace() const;
486
487         /// Orthonormalizes the basis formed by the column vectors of this matrix.
488         void Orthonormalize(int firstColumn, int secondColumn, int thirdColumn);
489
490         /// Removes the scaling performed by this matrix. That is, decomposes this matrix M into a form M = M' * S, where
491         /// M' has unitary column vectors and S is a diagonal matrix. Then replaces this matrix with M'.
492         /// @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
493         /// @note This function does not remove reflection (-1 scale along some axis).
494         void RemoveScale();
495
496         /// Transforms the given 3-vector by this matrix M, i.e. returns M * (x, y, z).
497         float3 Transform(const float3 &vector) const;
498         float3 Transform(float x, float y, float z) const;
499
500         /// Transforms the given 3-vector by this matrix M so that the vector occurs on the left-hand side, i.e.
501         /// computes the product lhs * M. This is against the common convention used by this class when transforming
502         /// geometrical objects, but this operation is still occasionally useful for other purposes.
503         /// (Remember that M * v != v * M in general).
504         float3 TransformLeft(const float3 &lhs) const;
505
506         /// Transforms the given 4-vector by this matrix M, i.e. returns M * (x, y, z, w).
507         /// This function ignores the w component of the given input vector. This component is assumed to be either 0 or 1.
508         float4 Transform(const float4 &vector) const;
509
510         /// Performs a batch transform of the given array.
511         void BatchTransform(float3 *pointArray, int numPoints) const;
512
513         /// Performs a batch transform of the given array.
514         void BatchTransform(float3 *pointArray, int numPoints, int stride) const;
515
516         /// Performs a batch transform of the given array.
517         /// This function ignores the w component of the input vectors. These components are assumed to be either 0 or 1.
518         void BatchTransform(float4 *vectorArray, int numVectors) const;
519
520         /// Performs a batch transform of the given array.
521         /// This function ignores the w component of the input vectors. These components are assumed to be either 0 or 1.
522         void BatchTransform(float4 *vectorArray, int numVectors, int stride) const;
523
524         /// Multiplies the two matrices.
525         float3x3 operator *(const float3x3 &rhs) const;
526
527         /// Converts the quaternion to a float3x3 and multiplies the two matrices together.
528         float3x3 operator *(const Quat &rhs) const;
529
530         /// Transforms the given vector by this matrix (in the order M * v).
531         float3 operator *(const float3 &rhs) const;
532
533         /// Transforms the given vector by this matrix (in the order M * v).
534         /// This function ignores the w component of the given input vector. This component is assumed to be either 0 or 1.
535         float4 operator *(const float4 &rhs) const;
536
537         float3x3 operator *(float scalar) const;
538         float3x3 operator /(float scalar) const;
539         float3x3 operator +(const float3x3 &rhs) const;
540         float3x3 operator -(const float3x3 &rhs) const;
541         float3x3 operator -() const;
542
543         /// Unary operator + allows this structure to be used in an expression '+x'.
544         float3x3 operator +() const return *this; }
545
546         float3x3 &operator *=(float scalar);
547         float3x3 &operator /=(float scalar);
548         float3x3 &operator +=(const float3x3 &rhs);
549         float3x3 &operator -=(const float3x3 &rhs);
550
551         /// Tests if this matrix does not contain any NaNs or infs.
552         /** @return Returns true if the entries of this float3x3 are all finite, and do not contain NaN or infs. */
553         bool IsFinite() const;
554
555         /// Tests if this is the identity matrix.
556         /** @return Returns true if this matrix is the identity matrix, up to the given epsilon. */
557         bool IsIdentity(float epsilon = 1e-3f) const;
558
559         /// Tests if this matrix is in lower triangular form.
560         /** @return Returns true if this matrix is in lower triangular form, up to the given epsilon. */
561         bool IsLowerTriangular(float epsilon = 1e-3f) const;
562
563         /// Tests if this matrix is in upper triangular form.
564         /** @return Returns true if this matrix is in upper triangular form, up to the given epsilon. */
565         bool IsUpperTriangular(float epsilon = 1e-3f) const;
566
567         /// Tests if this matrix has an inverse.
568         /** @return Returns true if this matrix can be inverted, up to the given epsilon. */
569         bool IsInvertible(float epsilon = 1e-3f) const;
570
571         /// Tests if this matrix is symmetric (M == M^T).
572         /** The test compares the elements for equality, up to the given epsilon. A matrix is symmetric if it is its own transpose. */
573         bool IsSymmetric(float epsilon = 1e-3f) const;
574
575         /// Tests if this matrix is skew-symmetric (M == -M^T).
576         /** The test compares the floating point elements of this matrix up to the given epsilon. A matrix M is skew-symmetric
577                 the identity M=-M^T holds. */
578         bool IsSkewSymmetric(float epsilon = 1e-3f) const;
579
580         /// Returns true if this matrix does not perform any scaling.
581         /** A matrix does not do any scaling if the column vectors of this
582                 matrix are normalized in length, compared to the given epsilon. Note that this matrix may still perform
583                 reflection, i.e. it has a -1 scale along some axis.
584                 @note This function only examines the upper 3-by-3 part of this matrix.
585                 @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]). */
586         bool HasUnitaryScale(float epsilonSq = 1e-6f) const;
587
588         /// Returns true if this matrix performs a reflection along some plane.
589         /** In 3D space, an even number of reflections corresponds to a rotation about some axis, so a matrix consisting of
590                 an odd number of consecutive mirror operations can only reflect about one axis. A matrix that contains reflection reverses
591                 the handedness of the coordinate system. This function tests if this matrix
592                 does perform mirroring. This occurs iff this matrix has a negative determinant. */
593         bool HasNegativeScale() const;
594
595         /// Returns true if this matrix contains only uniform scaling, compared to the given epsilon.
596         /// @note If the matrix does not really do any scaling, this function returns true (scaling uniformly by a factor of 1).
597         bool HasUniformScale(float epsilon = 1e-3f) const;
598
599         /// Returns true if the row vectors of this matrix are all perpendicular to each other.
600         bool IsRowOrthogonal(float epsilon = 1e-3f) const;
601
602         /// Returns true if the column vectors of this matrix are all perpendicular to each other.
603         bool IsColOrthogonal(float epsilon = 1e-3f) const;
604         bool IsColOrthogonal3(float epsilon = 1e-3f) const return IsColOrthogonal(epsilon); }
605
606         /// Returns true if the column and row vectors of this matrix form an orthonormal set.
607         /// @note In math terms, there does not exist such a thing as 'orthonormal matrix'. In math terms, a matrix
608         /// is orthogonal iff its column and row vectors are orthogonal *unit* vectors.
609         /// In the terms of this library however, a matrix is orthogonal iff its column and row vectors are orthogonal (no need to be unitary),
610         /// and a matrix is orthonormal if the column and row vectors are orthonormal.
611         bool IsOrthonormal(float epsilon = 1e-3f) const;
612
613         /// Returns true if this float3x3 is equal to the given float3x3, up to given per-element epsilon.
614         bool Equals(const float3x3 &other, float epsilon = 1e-3f) const;
615
616 #ifdef MATH_ENABLE_STL_SUPPORT
617         /// Returns "(m00, m01, m02; m10, m11, m12; m20, m21, m22)".
618         std::string ToString() const;
619         std::string SerializeToString() const;
620
621         std::string ToString2() const;
622 #endif
623
624         /// Extracts the rotation part of this matrix into Euler rotation angles (in radians). [indexTitle: ToEuler***]
625         /// @note It is better to think about the returned float3 as an array of three floats, and
626         /// not as a triple of xyz, because e.g. the .y component returned by ToEulerYXZ() does
627         /// not return the amount of rotation about the y axis, but contains the amount of rotation
628         /// in the second axis, in this case the x axis.
629         float3 ToEulerXYX() const;
630         float3 ToEulerXZX() const///< [similarOverload: ToEulerXYX] [hideIndex]
631         float3 ToEulerYXY() const///< [similarOverload: ToEulerXYX] [hideIndex]
632         float3 ToEulerYZY() const///< [similarOverload: ToEulerXYX] [hideIndex]
633         float3 ToEulerZXZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
634         float3 ToEulerZYZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
635         float3 ToEulerXYZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
636         float3 ToEulerXZY() const///< [similarOverload: ToEulerXYX] [hideIndex]
637         float3 ToEulerYXZ() const///< [similarOverload: ToEulerXYX] [hideIndex]
638         float3 ToEulerYZX() const///< [similarOverload: ToEulerXYX] [hideIndex]
639         float3 ToEulerZXY() const///< [similarOverload: ToEulerXYX] [hideIndex]
640         float3 ToEulerZYX() const///< [similarOverload: ToEulerXYX] [hideIndex]
641
642         /// Returns the scale components of this matrix.
643         /** This function decomposes this matrix M into a form M = M' * S, where M' has unitary column vectors and S is a diagonal matrix.
644                 @return ExtractScale returns the diagonal entries of S, i.e. the scale of the columns of this matrix . If this matrix
645                 represents a local->world space transformation for an object, then this scale represents a 'local scale', i.e.
646                 scaling that is performed before translating and rotating the object from its local coordinate system to its world
647                 position.
648                 @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
649                 @note This function does not detect and return reflection (-1 scale along some axis). */
650         float3 ExtractScale() const;
651
652         /// Decomposes this matrix to rotate and scale parts.
653         /** This function decomposes this matrix M to a form M = R * S, where R a rotation matrix and S a
654                 scale matrix.
655                 @note Remember that in the convention of this class, transforms are applied in the order M * v, so scale is
656                 applied first, then rotation, and finally the translation last.
657                 @note This function assumes that this matrix does not contain projection (the fourth row of this matrix is [0 0 0 1]).
658                 @param rotate [out] This object receives the rotation part of this transform.
659                 @param scale [out] This vector receives the scaling along the local (before transformation by R) X, Y and Z axes
660                         performed by this matrix. */
661         void Decompose(Quat &rotate, float3 &scale) const;
662         void Decompose(float3x3 &rotate, float3 &scale) const;
663
664         float3x3 Mul(const float3x3 &rhs) const;
665         float3x4 Mul(const float3x4 &rhs) const;
666         float4x4 Mul(const float4x4 &rhs) const;
667         float3x3 Mul(const Quat &rhs) const;
668         float3 Mul(const float3 &rhs) const;
669         float4 Mul(const float4 &rhs) const
670         {
671                 return float4(Mul(rhs.xyz()), rhs.w);
672         }
673         float3 MulPos(const float3 &rhs) const return Mul(rhs); }
674         float4 MulPos(const float4 &rhs) const
675         {
676                 assume(!EqualAbs(rhs.w, 0.f));
677                 return Mul(rhs);
678         }
679         float3 MulDir(const float3 &rhs) const return Mul(rhs); }
680         float4 MulDir(const float4 &rhs) const
681         {
682                 assume(EqualAbs(rhs.w, 0.f));
683                 return Mul(rhs);
684         }
685
686 #ifdef MATH_OGRE_INTEROP
687         float3x3(const Ogre::Matrix3 &m) { Set(&m[0][0]); }
688         operator Ogre::Matrix3() { return Ogre::Matrix3(v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2], v[2][0], v[2][1], v[2][2]); }
689 #endif
690 #ifdef MATH_BULLET_INTEROP
691         float3x3(const btMatrix3x3 &m) { Set(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]); }
692         operator btMatrix3x3() { return btMatrix3x3(v[0][0], v[0][1], v[0][2], v[1][0], v[1][1], v[1][2], v[2][0], v[2][1], v[2][2]); }
693 #endif
694 #ifdef MATH_QT_INTEROP
695         operator QString() const return toString(); }
696         QString toString() const return ToString2().c_str(); }
697 #endif
698 #ifdef MATH_URHO3D_INTEROP
699         float3x3(const Urho3D::Matrix3 &m) { Set(m.m00_, m.m01_, m.m02_, m.m10_, m.m11_, m.m12_, m.m20_, m.m21_, m.m22_); }
700         operator Urho3D::Matrix3() { return Urho3D::Matrix3(ptr()); }
701 #endif
702 };
703
704 #ifdef MATH_ENABLE_STL_SUPPORT
705 /// Prints this float3x3 to the given stream.
706 std::ostream &operator <<(std::ostream &out, const float3x3 &rhs);
707 #endif
708
709 /// Multiplies two transforms together.
710 float3x3 operator *(const Quat &lhs, const float3x3 &rhs);
711
712 /// Transforms the given vector by the given matrix in the order v * M. Note that this form
713 /// of multiplication is against the convention of this math system for transforming geometrical objects.
714 /// Please use the M * v notation instead. (Remember that M * v != v * M in general).
715 float3 operator *(const float3 &lhs, const float3x3 &rhs);
716
717 /// Transforms the given vector by the given matrix in the order v * M. Note that this form
718 /// of multiplication is against the convention of this math system. Please use the M * v notation instead.
719 /// (Remember that M * v != v * M in general).
720 /// This function ignores the w component of the given input vector. This component is assumed to be either 0 or 1.
721 float4 operator *(const float4 &lhs, const float3x3 &rhs);
722
723 #ifdef MATH_QT_INTEROP
724 Q_DECLARE_METATYPE(float3x3)
725 Q_DECLARE_METATYPE(float3x3*)
726 #endif
727
728 MATH_END_NAMESPACE

Go back to previous page