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

Go back to previous page