MathFu
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Friends Groups Pages
matrix.h
Go to the documentation of this file.
1 /*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #ifndef MATHFU_MATRIX_H_
17 #define MATHFU_MATRIX_H_
18 
19 #include "mathfu/utilities.h"
20 #include "mathfu/vector.h"
21 
22 #include <cmath>
23 
24 #include <assert.h>
25 
26 /// @file mathfu/matrix.h
27 /// @brief Matrix class and functions.
28 /// @addtogroup mathfu_matrix
29 ///
30 /// MathFu provides a generic Matrix implementation which is specialized
31 /// for 4x4 matrices to take advantage of optimization opportunities using
32 /// SIMD instructions.
33 
34 #ifdef _MSC_VER
35 #pragma warning(push)
36 // The following disables warnings for MATHFU_MAT_OPERATION.
37 // The buffer overrun warning must be disabled as MSVC doesn't treat
38 // "columns" as constant and therefore assumes that it's possible
39 // to overrun arrays indexed by "i".
40 // The conditional expression is constant warning is disabled since
41 // MSVC decides that "columns" *is* constant when unrolling the operation
42 // loop.
43 #pragma warning(disable : 4127) // conditional expression is constant
44 #pragma warning(disable : 4789) // buffer overrun
45 #if _MSC_VER >= 1900 // MSVC 2015
46 #pragma warning(disable : 4456) // allow shadowing in unrolled loops
47 #pragma warning(disable : 4723) // suppress "potential divide by 0" warning
48 #endif // _MSC_VER >= 1900
49 #endif // _MSC_VER
50 
51 /// @cond MATHFU_INTERNAL
52 /// The stride of a vector (e.g Vector<T, 3>) when cast as an array of floats.
53 #define MATHFU_VECTOR_STRIDE_FLOATS(vector) (sizeof(vector) / sizeof(float))
54 /// @endcond
55 
56 /// @cond MATHFU_INTERNAL
57 /// This will unroll loops for matrices with <= 4 columns
58 #define MATHFU_MAT_OPERATION(OP) MATHFU_UNROLLED_LOOP(i, columns, OP)
59 /// @endcond
60 
61 /// @cond MATHFU_INTERNAL
62 /// This will perform a given OP on each matrix column and return the result
63 #define MATHFU_MAT_OPERATOR(OP) \
64  { \
65  Matrix<T, rows, columns> result; \
66  MATHFU_MAT_OPERATION(result.data_[i] = (OP)); \
67  return result; \
68  }
69 /// @endcond
70 
71 /// @cond MATHFU_INTERNAL
72 /// This will perform a given OP on each matrix column
73 #define MATHFU_MAT_SELF_OPERATOR(OP) \
74  { \
75  MATHFU_MAT_OPERATION(OP); \
76  return *this; \
77  }
78 /// @endcond
79 
80 /// @cond MATHFU_INTERNAL
81 /// This macro will take the dot product for a row from data1 and a column from
82 /// data2.
83 #define MATHFU_MATRIX_4X4_DOT(data1, data2, r) \
84  ((data1)[r] * (data2)[0] + (data1)[(r) + 4] * (data2)[1] + \
85  (data1)[(r) + 8] * (data2)[2] + (data1)[(r) + 12] * (data2)[3])
86 /// @endcond
87 
88 /// @cond MATHFU_INTERNAL
89 #define MATHFU_MATRIX_3X3_DOT(data1, data2, r, size) \
90  ((data1)[r] * (data2)[0] + (data1)[(r) + (size)] * (data2)[1] + \
91  (data1)[(r) + 2 * (size)] * (data2)[2])
92 /// @endcond
93 
94 namespace mathfu {
95 
96 /// @cond MATHFU_INTERNAL
97 template <class T, int rows, int columns = rows>
98 class Matrix;
99 template <class T, int rows, int columns>
100 inline Matrix<T, rows, columns> IdentityHelper();
101 template <bool check_invertible, class T, int rows, int columns>
102 inline bool InverseHelper(const Matrix<T, rows, columns>& m,
103  Matrix<T, rows, columns>* const inverse);
104 template <class T, int rows, int columns>
105 inline void TimesHelper(const Matrix<T, rows, columns>& m1,
106  const Matrix<T, rows, columns>& m2,
107  Matrix<T, rows, columns>* out_m);
108 template <class T, int rows, int columns>
109 static inline Matrix<T, rows, columns> OuterProductHelper(
110  const Vector<T, rows>& v1, const Vector<T, columns>& v2);
111 template <class T>
112 inline Matrix<T, 4, 4> PerspectiveHelper(T fovy, T aspect, T znear, T zfar,
113  T handedness);
114 template <class T>
115 static inline Matrix<T, 4, 4> OrthoHelper(T left, T right, T bottom, T top,
116  T znear, T zfar, T handedness);
117 template <class T>
118 static inline Matrix<T, 4, 4> LookAtHelper(const Vector<T, 3>& at,
119  const Vector<T, 3>& eye,
120  const Vector<T, 3>& up,
121  T handedness);
122 template <class T>
123 static inline bool UnProjectHelper(const Vector<T, 3>& window_coord,
124  const Matrix<T, 4, 4>& model_view,
125  const Matrix<T, 4, 4>& projection,
126  const float window_width,
127  const float window_height,
128  Vector<T, 3>& result);
129 
130 template <typename T, int rows, int columns, typename CompatibleT>
131 static inline Matrix<T, rows, columns> FromTypeHelper(const CompatibleT& compatible);
132 
133 template <typename T, int rows, int columns, typename CompatibleT>
134 static inline CompatibleT ToTypeHelper(const Matrix<T, rows, columns>& m);
135 /// @endcond
136 
137 /// @addtogroup mathfu_matrix
138 /// @{
139 /// @class Matrix
140 /// @brief Matrix stores a set of "rows" by "columns" elements of type T
141 /// and provides functions that operate on the set of elements.
142 ///
143 /// @tparam T type of each element in the matrix.
144 /// @tparam rows Number of rows in the matrix.
145 /// @tparam columns Number of columns in the matrix.
146 template <class T, int rows, int columns>
147 class Matrix {
148  public:
149  /// @brief Construct a Matrix of uninitialized values.
150  inline Matrix() {}
151 
152  /// @brief Construct a Matrix from another Matrix copying each element.
153  ////
154  /// @param m Matrix that the data will be copied from.
155  inline Matrix(const Matrix<T, rows, columns>& m) {
156  MATHFU_MAT_OPERATION(data_[i] = m.data_[i]);
157  }
158 
159  /// @brief Construct a Matrix from a single float.
160  ///
161  /// @param s Scalar value used to initialize each element of the matrix.
162  explicit inline Matrix(const T& s) {
163  MATHFU_MAT_OPERATION((data_[i] = Vector<T, rows>(s)));
164  }
165 
166  /// @brief Construct a Matrix from four floats.
167  ///
168  /// @note This method only works with a 2x2 Matrix.
169  ///
170  /// @param s00 Value of the first row and column.
171  /// @param s10 Value of the second row, first column.
172  /// @param s01 Value of the first row, second column.
173  /// @param s11 Value of the second row and column.
174  inline Matrix(const T& s00, const T& s10, const T& s01, const T& s11) {
175  MATHFU_STATIC_ASSERT(rows == 2 && columns == 2);
176  data_[0] = Vector<T, rows>(s00, s10);
177  data_[1] = Vector<T, rows>(s01, s11);
178  }
179 
180  /// @brief Create a Matrix from nine floats.
181  ///
182  /// @note This method only works with a 3x3 Matrix.
183  ///
184  /// @param s00 Value of the first row and column.
185  /// @param s10 Value of the second row, first column.
186  /// @param s20 Value of the third row, first column.
187  /// @param s01 Value of the first row, second column.
188  /// @param s11 Value of the second row and column.
189  /// @param s21 Value of the third row, second column.
190  /// @param s02 Value of the first row, third column.
191  /// @param s12 Value of the second row, third column.
192  /// @param s22 Value of the third row and column.
193  inline Matrix(const T& s00, const T& s10, const T& s20, const T& s01,
194  const T& s11, const T& s21, const T& s02, const T& s12,
195  const T& s22) {
196  MATHFU_STATIC_ASSERT(rows == 3 && columns == 3);
197  data_[0] = Vector<T, rows>(s00, s10, s20);
198  data_[1] = Vector<T, rows>(s01, s11, s21);
199  data_[2] = Vector<T, rows>(s02, s12, s22);
200  }
201 
202  /// @brief Creates a Matrix from twelve floats.
203  ///
204  /// @note This method only works with Matrix<float, 4, 3>.
205  ///
206  ///
207  /// @param s00 Value of the first row and column.
208  /// @param s10 Value of the second row, first column.
209  /// @param s20 Value of the third row, first column.
210  /// @param s30 Value of the fourth row, first column.
211  /// @param s01 Value of the first row, second column.
212  /// @param s11 Value of the second row and column.
213  /// @param s21 Value of the third row, second column.
214  /// @param s31 Value of the fourth row, second column.
215  /// @param s02 Value of the first row, third column.
216  /// @param s12 Value of the second row, third column.
217  /// @param s22 Value of the third row and column.
218  /// @param s32 Value of the fourth row, third column.
219  inline Matrix(const T& s00, const T& s10, const T& s20, const T& s30,
220  const T& s01, const T& s11, const T& s21, const T& s31,
221  const T& s02, const T& s12, const T& s22, const T& s32) {
222  MATHFU_STATIC_ASSERT(rows == 4 && columns == 3);
223  data_[0] = Vector<T, rows>(s00, s10, s20, s30);
224  data_[1] = Vector<T, rows>(s01, s11, s21, s31);
225  data_[2] = Vector<T, rows>(s02, s12, s22, s32);
226  }
227 
228  /// @brief Create a Matrix from sixteen floats.
229  ///
230  /// @note This method only works with a 4x4 Matrix.
231  ///
232  /// @param s00 Value of the first row and column.
233  /// @param s10 Value of the second row, first column.
234  /// @param s20 Value of the third row, first column.
235  /// @param s30 Value of the fourth row, first column.
236  /// @param s01 Value of the first row, second column.
237  /// @param s11 Value of the second row and column.
238  /// @param s21 Value of the third row, second column.
239  /// @param s31 Value of the fourth row, second column.
240  /// @param s02 Value of the first row, third column.
241  /// @param s12 Value of the second row, third column.
242  /// @param s22 Value of the third row and column.
243  /// @param s32 Value of the fourth row, third column.
244  /// @param s03 Value of the first row, fourth column.
245  /// @param s13 Value of the second row, fourth column.
246  /// @param s23 Value of the third row, fourth column.
247  /// @param s33 Value of the fourth row and column.
248  inline Matrix(const T& s00, const T& s10, const T& s20, const T& s30,
249  const T& s01, const T& s11, const T& s21, const T& s31,
250  const T& s02, const T& s12, const T& s22, const T& s32,
251  const T& s03, const T& s13, const T& s23, const T& s33) {
252  MATHFU_STATIC_ASSERT(rows == 4 && columns == 4);
253  data_[0] = Vector<T, rows>(s00, s10, s20, s30);
254  data_[1] = Vector<T, rows>(s01, s11, s21, s31);
255  data_[2] = Vector<T, rows>(s02, s12, s22, s32);
256  data_[3] = Vector<T, rows>(s03, s13, s23, s33);
257  }
258 
259  /// @brief Create 4x4 Matrix from 4, 4 element vectors.
260  ///
261  /// @note This method only works with a 4x4 Matrix.
262  ///
263  /// @param column0 Vector used for the first column.
264  /// @param column1 Vector used for the second column.
265  /// @param column2 Vector used for the third column.
266  /// @param column3 Vector used for the fourth column.
267  inline Matrix(const Vector<T, 4>& column0, const Vector<T, 4>& column1,
268  const Vector<T, 4>& column2, const Vector<T, 4>& column3) {
269  MATHFU_STATIC_ASSERT(rows == 4 && columns == 4);
270  data_[0] = column0;
271  data_[1] = column1;
272  data_[2] = column2;
273  data_[3] = column3;
274  }
275 
276  /// @brief Create a Matrix from the first row * column elements of an array.
277  ///
278  /// @param a Array of values that the matrix will be iniitlized to.
279  explicit inline Matrix(const T* const a) {
280  MATHFU_MAT_OPERATION((data_[i] = Vector<T, rows>(&a[i * columns])));
281  }
282 
283  /// @brief Create a Matrix from an array of "columns", "rows" element packed
284  /// vectors.
285  ///
286  /// @param vectors Array of "columns", "rows" element packed vectors.
287  explicit inline Matrix(const VectorPacked<T, rows>* const vectors) {
288  MATHFU_MAT_OPERATION((data_[i] = Vector<T, rows>(vectors[i])));
289  }
290 
291  /// @brief Access an element of the matrix.
292  ///
293  /// @param row Index of the row to access.
294  /// @param column Index of the column to access.
295  /// @return Const reference to the element.
296  inline const T& operator()(const int row, const int column) const {
297  return data_[column][row];
298  }
299 
300  /// @brief Access an element of the Matrix.
301  ///
302  /// @param row Index of the row to access.
303  /// @param column Index of the column to access.
304  /// @return Reference to the data that can be modified by the caller.
305  inline T& operator()(const int row, const int column) {
306  return data_[column][row];
307  }
308 
309  /// @brief Access an element of the Matrix.
310  ///
311  /// @param i Index of the element to access in flattened memory. Where
312  /// the column accessed is i / rows and the row is i % rows.
313  /// @return Reference to the data that can be modified by the caller.
314  inline const T& operator()(const int i) const { return operator[](i); }
315 
316  /// @brief Access an element of the Matrix.
317  ///
318  /// @param i Index of the element to access in flattened memory. Where
319  /// the column accessed is i / rows and the row is i % rows.
320  /// @return Reference to the data that can be modified by the caller.
321  inline T& operator()(const int i) { return operator[](i); }
322 
323  /// @brief Access an element of the Matrix.
324  ///
325  /// @param i Index of the element to access in flattened memory. Where
326  /// the column accessed is i / rows and the row is i % rows.
327  /// @return Const reference to the data.
328  inline const T& operator[](const int i) const {
329  return const_cast<Matrix<T, rows, columns>*>(this)->operator[](i);
330  }
331 
332  /// @brief Access an element of the Matrix.
333  ///
334  /// @param i Index of the element to access in flattened memory. Where
335  /// the column accessed is i / rows and the row is i % rows.
336  /// @return Reference to the data that can be modified by the caller.
337  inline T& operator[](const int i) {
338 #if defined(MATHFU_COMPILE_WITH_PADDING)
339  // In this case Vector<T, 3> is padded, so the element offset must be
340  // accessed using the array operator.
341  if (rows == 3) {
342  const int row = i % rows;
343  const int col = i / rows;
344  return data_[col][row];
345  } else {
346  return reinterpret_cast<T*>(data_)[i];
347  }
348 #else
349  return reinterpret_cast<T*>(data_)[i];
350 #endif // defined(MATHFU_COMPILE_WITH_PADDING)
351  }
352 
353  /// @brief Pack the matrix to an array of "rows" element vectors,
354  /// one vector per matrix column.
355  ///
356  /// @param vector Array of "columns" entries to write to.
357  inline void Pack(VectorPacked<T, rows>* const vector) const {
358  MATHFU_MAT_OPERATION(GetColumn(i).Pack(&vector[i]));
359  }
360 
361  /// @cond MATHFU_INTERNAL
362  /// @brief Access a column vector of the Matrix.
363  ///
364  /// @param i Index of the column to access.
365  /// @return Reference to the data that can be modified by the caller.
366  inline Vector<T, rows>& GetColumn(const int i) { return data_[i]; }
367 
368  /// @brief Access a column vector of the Matrix.
369  ///
370  /// @param i Index of the column to access.
371  /// @return Const reference to the data.
372  inline const Vector<T, rows>& GetColumn(const int i) const {
373  return data_[i];
374  }
375  /// @endcond
376 
377  /// @brief Negate this Matrix.
378  ///
379  /// @return Matrix containing the result.
381  MATHFU_MAT_OPERATOR(-data_[i]);
382  }
383 
384  /// @brief Add a Matrix to this Matrix.
385  ///
386  /// @param m Matrix to add to this Matrix.
387  /// @return Matrix containing the result.
389  const Matrix<T, rows, columns>& m) const {
390  MATHFU_MAT_OPERATOR(data_[i] + m.data_[i]);
391  }
392 
393  /// @brief Subtract a Matrix from this Matrix.
394  ///
395  /// @param m Matrix to subtract from this Matrix.
396  /// @return Matrix containing the result.
398  const Matrix<T, rows, columns>& m) const {
399  MATHFU_MAT_OPERATOR(data_[i] - m.data_[i]);
400  }
401 
402  /// @brief Add a scalar to each element of this Matrix.
403  ///
404  /// @param s Scalar to add to this Matrix.
405  /// @return Matrix containing the result.
406  inline Matrix<T, rows, columns> operator+(const T& s) const {
407  MATHFU_MAT_OPERATOR(data_[i] + s);
408  }
409 
410  /// @brief Subtract a scalar from each element of this Matrix.
411  ///
412  /// @param s Scalar to subtract from this matrix.
413  /// @return Matrix containing the result.
414  inline Matrix<T, rows, columns> operator-(const T& s) const {
415  MATHFU_MAT_OPERATOR(data_[i] - s);
416  }
417 
418  /// @brief Multiply each element of this Matrix with a scalar.
419  ///
420  /// @param s Scalar to multiply with this Matrix.
421  /// @return Matrix containing the result.
422  inline Matrix<T, rows, columns> operator*(const T& s) const {
423  MATHFU_MAT_OPERATOR(data_[i] * s);
424  }
425 
426  /// @brief Divide each element of this Matrix with a scalar.
427  ///
428  /// @param s Scalar to divide this Matrix with.
429  /// @return Matrix containing the result.
430  inline Matrix<T, rows, columns> operator/(const T& s) const {
431  return (*this) * (1 / s);
432  }
433 
434  /// @brief Multiply this Matrix with another Matrix.
435  ///
436  /// @param m Matrix to multiply with this Matrix.
437  /// @return Matrix containing the result.
439  const Matrix<T, rows, columns>& m) const {
441  TimesHelper(*this, m, &result);
442  return result;
443  }
444 
445  /// @brief Add a Matrix to this Matrix (in-place).
446  ///
447  /// @param m Matrix to add to this Matrix.
448  /// @return Reference to this class.
450  const Matrix<T, rows, columns>& m) {
451  MATHFU_MAT_SELF_OPERATOR(data_[i] += m.data_[i]);
452  }
453 
454  /// @brief Subtract a Matrix from this Matrix (in-place).
455  ///
456  /// @param m Matrix to subtract from this Matrix.
457  /// @return Reference to this class.
459  const Matrix<T, rows, columns>& m) {
460  MATHFU_MAT_SELF_OPERATOR(data_[i] -= m.data_[i]);
461  }
462 
463  /// @brief Add a scalar to each element of this Matrix (in-place).
464  ///
465  /// @param s Scalar to add to each element of this Matrix.
466  /// @return Reference to this class.
467  inline Matrix<T, rows, columns>& operator+=(const T& s) {
468  MATHFU_MAT_SELF_OPERATOR(data_[i] += s);
469  }
470 
471  /// @brief Subtract a scalar from each element of this Matrix (in-place).
472  ///
473  /// @param s Scalar to subtract from each element of this Matrix.
474  /// @return Reference to this class.
475  inline Matrix<T, rows, columns>& operator-=(const T& s) {
476  MATHFU_MAT_SELF_OPERATOR(data_[i] -= s);
477  }
478 
479  /// @brief Multiply each element of this Matrix with a scalar (in-place).
480  ///
481  /// @param s Scalar to multiply with each element of this Matrix.
482  /// @return Reference to this class.
483  inline Matrix<T, rows, columns>& operator*=(const T& s) {
484  MATHFU_MAT_SELF_OPERATOR(data_[i] *= s);
485  }
486 
487  /// @brief Divide each element of this Matrix by a scalar (in-place).
488  ///
489  /// @param s Scalar to divide this Matrix by.
490  /// @return Reference to this class.
491  inline Matrix<T, rows, columns>& operator/=(const T& s) {
492  return (*this) *= (1 / s);
493  }
494 
495  /// @brief Multiply this Matrix with another Matrix (in-place).
496  ///
497  /// @param m Matrix to multiply with this Matrix.
498  /// @return Reference to this class.
500  const Matrix<T, rows, columns>& m) {
501  const Matrix<T, rows, columns> copy_of_this(*this);
502  TimesHelper(copy_of_this, m, this);
503  return *this;
504  }
505 
506  /// @brief Calculate the inverse of this Matrix.
507  ///
508  /// This calculates the inverse Matrix such that
509  /// <code>(m * m).Inverse()</code> is the identity.
510  /// @return Matrix containing the result.
512  Matrix<T, rows, columns> inverse;
513  InverseHelper<false>(*this, &inverse);
514  return inverse;
515  }
516 
517  /// @brief Calculate the inverse of this Matrix.
518  ///
519  /// This calculates the inverse Matrix such that
520  /// <code>(m * m).Inverse()</code> is the identity.
521  /// By contrast to Inverse() this returns whether the matrix is invertible.
522  ///
523  /// The invertible check simply compares the calculated determinant with
524  /// Constants<T>::GetDeterminantThreshold() to roughly determine whether the
525  /// matrix is invertible. This simple check works in common cases but will
526  /// fail for corner cases where the matrix is a combination of huge and tiny
527  /// values that can't be accurately represented by the floating point
528  /// datatype T. More extensive checks (relative to the input values) are
529  /// possible but <b>far</b> more expensive, complicated and difficult to
530  /// test.
531  /// @return Whether the matrix is invertible.
533  Matrix<T, rows, columns>* const inverse) const {
534  return InverseHelper<true>(*this, inverse);
535  }
536 
537  /// @brief Calculate the transpose of this Matrix.
538  ///
539  /// @return The transpose of the specified Matrix.
541  Matrix<T, columns, rows> transpose;
542  MATHFU_UNROLLED_LOOP(
543  i, columns, MATHFU_UNROLLED_LOOP(
544  j, rows, transpose.GetColumn(j)[i] = GetColumn(i)[j]))
545  return transpose;
546  }
547 
548  /// @brief Get the 2-dimensional translation of a 2-dimensional affine
549  /// transform.
550  ///
551  /// @note 2-dimensional affine transforms are represented by 3x3 matrices.
552  /// @return Vector with the first two components of column 2 of this Matrix.
554  MATHFU_STATIC_ASSERT(rows == 3 && columns == 3);
555  return Vector<T, 2>(data_[2][0], data_[2][1]);
556  }
557 
558  /// @brief Get the 3-dimensional translation of a 3-dimensional affine
559  /// transform.
560  ///
561  /// @note 3-dimensional affine transforms are represented by 4x4 matrices.
562  /// @return Vector with the first three components of column 3.
564  MATHFU_STATIC_ASSERT(rows == 4 && columns == 4);
565  return Vector<T, 3>(data_[3][0], data_[3][1], data_[3][2]);
566  }
567 
568  /// @brief Load from any byte-wise compatible external matrix.
569  ///
570  /// Format should be `columns` vectors, each holding `rows` values of type T.
571  ///
572  /// Use this for safe conversion from external matrix classes.
573  /// Often, external libraries will have their own matrix types that are,
574  /// byte-for-byte, exactly the same as mathfu::Matrix. This function allows
575  /// you to load a mathfu::Matrix from those external types, without potential
576  /// aliasing bugs that are caused by casting.
577  ///
578  /// @note If your external type gives you access to a T*, then you can
579  /// equivalently use the Matrix(const T*) constructor.
580  ///
581  /// @param compatible reference to a byte-wise compatible matrix structure;
582  /// array of columns x rows Ts.
583  /// @returns `compatible` loaded as a mathfu::Matrix.
584  template <typename CompatibleT>
585  static inline Matrix<T, rows, columns> FromType(const CompatibleT& compatible) {
586  return FromTypeHelper<T, rows, columns, CompatibleT>(compatible);
587  }
588 
589  /// @brief Load into any byte-wise compatible external matrix.
590  ///
591  /// Format should be `columns` vectors, each holding `rows` values of type T.
592  ///
593  /// Use this for safe conversion to external matrix classes.
594  /// Often, external libraries will have their own matrix types that are,
595  /// byte-for-byte, exactly the same as mathfu::Matrix. This function allows
596  /// you to load an external type from a mathfu::Matrix, without potential
597  /// aliasing bugs that are caused by casting.
598  ///
599  /// @param m reference to mathfu::Matrix to convert.
600  /// @returns CompatibleT loaded from m.
601  template <typename CompatibleT>
602  static inline CompatibleT ToType(const Matrix<T, rows, columns>& m) {
603  return ToTypeHelper<T, rows, columns, CompatibleT>(m);
604  }
605 
606  /// @brief Calculate the outer product of two Vectors.
607  ///
608  /// @return Matrix containing the result.
610  const Vector<T, rows>& v1, const Vector<T, columns>& v2) {
611  return OuterProductHelper(v1, v2);
612  }
613 
614  /// @brief Calculate the hadamard / component-wise product of two matrices.
615  ///
616  /// @param m1 First Matrix.
617  /// @param m2 Second Matrix.
618  /// @return Matrix containing the result.
620  const Matrix<T, rows, columns>& m1, const Matrix<T, rows, columns>& m2) {
621  MATHFU_MAT_OPERATOR(m1[i] * m2[i]);
622  }
623 
624  /// @brief Calculate the identity Matrix.
625  ///
626  /// @return Matrix containing the result.
628  return IdentityHelper<T, rows, columns>();
629  }
630 
631  /// @brief Create a 3x3 translation Matrix from a 2-dimensional Vector.
632  ///
633  /// This matrix will have an empty or zero rotation component.
634  ///
635  /// @param v Vector of size 2.
636  /// @return Matrix containing the result.
638  return Matrix<T, 3>(1, 0, 0, 0, 1, 0, v[0], v[1], 1);
639  }
640 
641  /// @brief Create a 4x4 translation Matrix from a 3-dimensional Vector.
642  ///
643  /// This matrix will have an empty or zero rotation component.
644  ///
645  /// @param v The vector of size 3.
646  /// @return Matrix containing the result.
648  return Matrix<T, 4>(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, v[0], v[1], v[2],
649  1);
650  }
651 
652  /// @brief Create a square Matrix with the diagonal component set to v.
653  ///
654  /// This is an affine transform matrix, so the dimension of the vector is
655  /// one less than the dimension of the matrix.
656  ///
657  /// @param v Vector containing components for scaling.
658  /// @return Matrix with v along the diagonal, and 1 in the bottom right.
660  // TODO OPT: Use a helper function in a similar way to Identity to
661  // construct the matrix for the specialized cases 2, 3, 4, and only run
662  // this method in the general case. This will also allow you to use the
663  // helper methods from specialized classes like Matrix<T, 4, 4>.
664  Matrix<T, rows> return_matrix(Identity());
665  for (int i = 0; i < rows - 1; ++i) return_matrix(i, i) = v[i];
666  return return_matrix;
667  }
668 
669  /// @brief Create a 4x4 Matrix from a 3x3 rotation Matrix.
670  ///
671  /// This Matrix will have an empty or zero translation component.
672  ///
673  /// @param m 3x3 rotation Matrix.
674  /// @return Matrix containing the result.
675  static inline Matrix<T, 4> FromRotationMatrix(const Matrix<T, 3>& m) {
676  return Matrix<T, 4>(m[0], m[1], m[2], 0, m[3], m[4], m[5], 0, m[6], m[7],
677  m[8], 0, 0, 0, 0, 1);
678  }
679 
680  /// @brief Extracts the 3x3 rotation Matrix from a 4x4 Matrix.
681  ///
682  /// This resulting Matrix will contain the upper-left 3x3 sub-matrix of the
683  /// input Matrix.
684  ///
685  /// @param m 4x4 Matrix.
686  /// @return rotation Matrix containing the result.
687  static inline Matrix<T, 3> ToRotationMatrix(const Matrix<T, 4>& m) {
688  return Matrix<T, 3>(m[0], m[1], m[2], m[4], m[5], m[6], m[8], m[9],
689  m[10]);
690  }
691 
692  /// @brief Constructs a Matrix<float, 4> from an AffineTransform.
693  ///
694  /// @param affine An AffineTransform reference to be used to construct
695  /// a Matrix<float, 4> by adding in the 'w' row of [0, 0, 0, 1].
697  const Matrix<T, 4, 3>& affine) {
698  return Matrix<T, 4>(affine[0], affine[4], affine[8], static_cast<T>(0),
699  affine[1], affine[5], affine[9], static_cast<T>(0),
700  affine[2], affine[6], affine[10], static_cast<T>(0),
701  affine[3], affine[7], affine[11], static_cast<T>(1));
702  }
703 
704  /// @brief Converts a Matrix<float, 4> into an AffineTransform.
705  ///
706  /// @param m A Matrix<float, 4> reference to be converted into an
707  /// AffineTransform by dropping the fixed 'w' row.
708  ///
709  /// @return Returns an AffineTransform that contains the essential
710  /// transformation data from the Matrix<float, 4>.
712  return Matrix<T, 4, 3>(m[0], m[4], m[8], m[12], m[1], m[5], m[9], m[13],
713  m[2], m[6], m[10], m[14]);
714  }
715 
716  /// @brief Create a 3x3 rotation Matrix from a 2D normalized directional
717  /// Vector around the X axis.
718  ///
719  /// @param v 2D normalized directional Vector.
720  /// @return Matrix containing the result.
721  static inline Matrix<T, 3> RotationX(const Vector<T, 2>& v) {
722  return Matrix<T, 3>(1, 0, 0, 0, v.x, v.y, 0, -v.y, v.x);
723  }
724 
725  /// @brief Create a 3x3 rotation Matrix from a 2D normalized directional
726  /// Vector around the Y axis.
727  ///
728  /// @param v 2D normalized directional Vector.
729  /// @return Matrix containing the result.
730  static inline Matrix<T, 3> RotationY(const Vector<T, 2>& v) {
731  return Matrix<T, 3>(v.x, 0, -v.y, 0, 1, 0, v.y, 0, v.x);
732  }
733 
734  /// @brief Create a 3x3 rotation Matrix from a 2D normalized directional
735  /// Vector around the Z axis.
736  ///
737  /// @param v 2D normalized directional Vector.
738  /// @return Matrix containing the result.
739  static inline Matrix<T, 3> RotationZ(const Vector<T, 2>& v) {
740  return Matrix<T, 3>(v.x, v.y, 0, -v.y, v.x, 0, 0, 0, 1);
741  }
742 
743  /// @brief Create a 3x3 rotation Matrix from an angle (in radians) around
744  /// the X axis.
745  ///
746  /// @param angle Angle (in radians).
747  /// @return Matrix containing the result.
748  static inline Matrix<T, 3> RotationX(T angle) {
749  return RotationX(Vector<T, 2>(cosf(angle), sinf(angle)));
750  }
751 
752  /// @brief Create a 3x3 rotation Matrix from an angle (in radians) around
753  /// the Y axis.
754  ///
755  /// @param angle Angle (in radians).
756  /// @return Matrix containing the result.
757  static inline Matrix<T, 3> RotationY(T angle) {
758  return RotationY(Vector<T, 2>(cosf(angle), sinf(angle)));
759  }
760 
761  /// @brief Create a 3x3 rotation Matrix from an angle (in radians)
762  /// around the Z axis.
763  ///
764  /// @param angle Angle (in radians).
765  /// @return Matrix containing the result.
766  static inline Matrix<T, 3> RotationZ(T angle) {
767  return RotationZ(Vector<T, 2>(cosf(angle), sinf(angle)));
768  }
769 
770  /// @brief Create a 4x4 perspective Matrix.
771  ///
772  /// @param fovy Field of view.
773  /// @param aspect Aspect ratio.
774  /// @param znear Near plane location.
775  /// @param zfar Far plane location.
776  /// @param handedness 1.0f for RH, -1.0f for LH
777  /// @return 4x4 perspective Matrix.
778  static inline Matrix<T, 4, 4> Perspective(T fovy, T aspect, T znear, T zfar,
779  T handedness = 1) {
780  return PerspectiveHelper(fovy, aspect, znear, zfar, handedness);
781  }
782 
783  /// @brief Create a 4x4 orthographic Matrix.
784  ///
785  /// @param left Left extent.
786  /// @param right Right extent.
787  /// @param bottom Bottom extent.
788  /// @param top Top extent.
789  /// @param znear Near plane location.
790  /// @param zfar Far plane location.
791  /// @param handedness 1.0f for RH, -1.0f for LH
792  /// @return 4x4 orthographic Matrix.
793  static inline Matrix<T, 4, 4> Ortho(T left, T right, T bottom, T top, T znear,
794  T zfar, T handedness = 1) {
795  return OrthoHelper(left, right, bottom, top, znear, zfar, handedness);
796  }
797 
798  /// @brief Create a 3-dimensional camera Matrix.
799  ///
800  /// @param at The look-at target of the camera.
801  /// @param eye The position of the camera.
802  /// @param up The up vector in the world, for example (0, 1, 0) if the
803  /// y-axis is up.
804  /// @param handedness 1.0f for RH, -1.0f for LH.
805  /// @return 3-dimensional camera Matrix.
806  /// TODO: Change default handedness to +1 so that it matches Perspective().
807  static inline Matrix<T, 4, 4> LookAt(const Vector<T, 3>& at,
808  const Vector<T, 3>& eye,
809  const Vector<T, 3>& up,
810  T handedness = -1) {
811  return LookAtHelper(at, eye, up, handedness);
812  }
813 
814  /// @brief Get the 3D position in object space from a window coordinate.
815  ///
816  /// @param window_coord The window coordinate. The z value is for depth.
817  /// A window coordinate on the near plane will have 0 as the z value.
818  /// And a window coordinate on the far plane will have 1 as the z value.
819  /// z value should be with in [0, 1] here.
820  /// @param model_view The Model View matrix.
821  /// @param projection The projection matrix.
822  /// @param window_width Width of the window.
823  /// @param window_height Height of the window.
824  /// @return the mapped 3D position in object space.
825  static inline Vector<T, 3> UnProject(const Vector<T, 3>& window_coord,
826  const Matrix<T, 4, 4>& model_view,
827  const Matrix<T, 4, 4>& projection,
828  const float window_width,
829  const float window_height) {
830  Vector<T, 3> result;
831  UnProjectHelper(window_coord, model_view, projection, window_width,
832  window_height, result);
833  return result;
834  }
835 
836  /// @brief Multiply a Vector by a Matrix.
837  ///
838  /// @param v Vector to multiply.
839  /// @param m Matrix to multiply.
840  /// @return Matrix containing the result.
842  const Vector<T, rows>& v, const Matrix<T, rows, columns>& m) {
843  const int d = columns;
844  MATHFU_VECTOR_OPERATOR((Vector<T, rows>::DotProduct(m.data_[i], v)));
845  }
846 
847  // Dimensions of the matrix.
848  /// Number of rows in the matrix.
849  static const int kRows = rows;
850  /// Number of columns in the matrix.
851  static const int kColumns = columns;
852  /// Total number of elements in the matrix.
853  static const int kElements = rows * columns;
854 
856 
857  private:
858  Vector<T, rows> data_[columns];
859 };
860 /// @}
861 
862 /// @addtogroup mathfu_matrix
863 /// @{
864 
865 /// @brief Multiply each element of a Matrix by a scalar.
866 ///
867 /// @param s Scalar to multiply by.
868 /// @param m Matrix to multiply.
869 /// @return Matrix containing the result.
870 /// @tparam T Type of each element in the Matrix and the scalar type.
871 /// @tparam rows Number of rows in the matrix.
872 /// @tparam columns Number of columns in the matrix.
873 ///
874 /// @related mathfu::Matrix
875 template <class T, int rows, int columns>
877  const Matrix<T, columns, rows>& m) {
878  return m * s;
879 }
880 
881 /// @brief Multiply a Matrix by a Vector.
882 ///
883 /// @note Template specialized versions are implemented for 2x2, 3x3, and 4x4
884 /// matrices to increase performance. The 3x3 float is also specialized
885 /// to supported padded the 3-dimensional Vector in SIMD build configurations.
886 ///
887 /// @param m Matrix to multiply.
888 /// @param v Vector to multiply.
889 /// @return Vector containing the result.
890 ///
891 /// @related mathfu::Matrix
892 template <class T, int rows, int columns>
894  const Vector<T, columns>& v) {
895  const Vector<T, rows> result(0);
896  int offset = 0;
897  for (int column = 0; column < columns; column++) {
898  for (int row = 0; row < rows; row++) {
899  result[row] += m[offset + row] * v[column];
900  }
901  offset += rows;
902  }
903  return result;
904 }
905 
906 /// @cond MATHFU_INTERNAL
907 template <class T>
908 inline Vector<T, 2> operator*(const Matrix<T, 2, 2>& m, const Vector<T, 2>& v) {
909  return Vector<T, 2>(m[0] * v[0] + m[2] * v[1], m[1] * v[0] + m[3] * v[1]);
910 }
911 /// @endcond
912 
913 /// @cond MATHFU_INTERNAL
914 template <class T>
915 inline Vector<T, 3> operator*(const Matrix<T, 3, 3>& m, const Vector<T, 3>& v) {
916  return Vector<T, 3>(MATHFU_MATRIX_3X3_DOT(&m[0], v, 0, 3),
917  MATHFU_MATRIX_3X3_DOT(&m[0], v, 1, 3),
918  MATHFU_MATRIX_3X3_DOT(&m[0], v, 2, 3));
919 }
920 /// @endcond
921 
922 /// @cond MATHFU_INTERNAL
923 template <>
924 inline Vector<float, 3> operator*(const Matrix<float, 3, 3>& m,
925  const Vector<float, 3>& v) {
926  return Vector<float, 3>(
927  MATHFU_MATRIX_3X3_DOT(&m[0], v, 0, MATHFU_VECTOR_STRIDE_FLOATS(v)),
928  MATHFU_MATRIX_3X3_DOT(&m[0], v, 1, MATHFU_VECTOR_STRIDE_FLOATS(v)),
929  MATHFU_MATRIX_3X3_DOT(&m[0], v, 2, MATHFU_VECTOR_STRIDE_FLOATS(v)));
930 }
931 /// @endcond
932 
933 /// @cond MATHFU_INTERNAL
934 template <class T>
935 inline Vector<T, 4> operator*(const Matrix<T, 4, 4>& m, const Vector<T, 4>& v) {
936  return Vector<T, 4>(
937  MATHFU_MATRIX_4X4_DOT(&m[0], v, 0), MATHFU_MATRIX_4X4_DOT(&m[0], v, 1),
938  MATHFU_MATRIX_4X4_DOT(&m[0], v, 2), MATHFU_MATRIX_4X4_DOT(&m[0], v, 3));
939 }
940 /// @endcond
941 
942 /// @brief Multiply a 4x4 Matrix by a 3-dimensional Vector.
943 ///
944 /// This is provided as a convenience and assumes the vector has a fourth
945 /// component equal to 1.
946 ///
947 /// @param m 4x4 Matrix.
948 /// @param v 3-dimensional Vector.
949 /// @return 3-dimensional Vector result.
950 ///
951 /// @related mathfu::Matrix
952 template <class T>
954  Vector<T, 4> v4(v[0], v[1], v[2], 1);
955  v4 = m * v4;
956  return Vector<T, 3>(v4[0] / v4[3], v4[1] / v4[3], v4[2] / v4[3]);
957 }
958 
959 /// @cond MATHFU_INTERNAL
960 /// @brief Multiply a Matrix with another Matrix.
961 ///
962 /// @note Template specialized versions are implemented for 2x2, 3x3, and 4x4
963 /// matrices to improve performance. 3x3 float is also specialized because if
964 /// SIMD is used the vectors of this type of length 4.
965 ///
966 /// @param m1 Matrix to multiply.
967 /// @param m2 Matrix to multiply.
968 /// @param out_m Pointer to a Matrix which receives the result.
969 ///
970 /// @tparam T Type of each element in the returned Matrix.
971 /// @tparam size1 Number of rows in the returned Matrix and columns in m1.
972 /// @tparam size2 Number of columns in the returned Matrix and rows in m2.
973 /// @tparam size3 Number of columns in m3.
974 template <class T, int size1, int size2, int size3>
975 inline void TimesHelper(const Matrix<T, size1, size2>& m1,
976  const Matrix<T, size2, size3>& m2,
977  Matrix<T, size1, size3>* out_m) {
978  for (int i = 0; i < size1; i++) {
979  for (int j = 0; j < size3; j++) {
980  Vector<T, size2> row;
981  for (int k = 0; k < size2; k++) {
982  row[k] = m1(i, k);
983  }
984  (*out_m)(i, j) = Vector<T, size2>::DotProduct(m2.GetColumn(j), row);
985  }
986  }
987 }
988 /// @endcond
989 
990 /// @cond MATHFU_INTERNAL
991 template <class T>
992 inline void TimesHelper(const Matrix<T, 2, 2>& m1, const Matrix<T, 2, 2>& m2,
993  Matrix<T, 2, 2>* out_m) {
994  Matrix<T, 2, 2>& out = *out_m;
995  out[0] = m1[0] * m2[0] + m1[2] * m2[1];
996  out[1] = m1[1] * m2[0] + m1[3] * m2[1];
997  out[2] = m1[0] * m2[2] + m1[2] * m2[3];
998  out[3] = m1[1] * m2[2] + m1[3] * m2[3];
999 }
1000 /// @endcond
1001 
1002 /// @cond MATHFU_INTERNAL
1003 template <typename T>
1004 inline void TimesHelper(const Matrix<T, 3, 3>& m1, const Matrix<T, 3, 3>& m2,
1005  Matrix<T, 3, 3>* out_m) {
1006  Matrix<T, 3, 3>& out = *out_m;
1007  {
1008  Vector<T, 3> row(m1[0], m1[3], m1[6]);
1009  out[0] = Vector<T, 3>::DotProduct(m2.GetColumn(0), row);
1010  out[3] = Vector<T, 3>::DotProduct(m2.GetColumn(1), row);
1011  out[6] = Vector<T, 3>::DotProduct(m2.GetColumn(2), row);
1012  }
1013  {
1014  Vector<T, 3> row(m1[1], m1[4], m1[7]);
1015  out[1] = Vector<T, 3>::DotProduct(m2.GetColumn(0), row);
1016  out[4] = Vector<T, 3>::DotProduct(m2.GetColumn(1), row);
1017  out[7] = Vector<T, 3>::DotProduct(m2.GetColumn(2), row);
1018  }
1019  {
1020  Vector<T, 3> row(m1[2], m1[5], m1[8]);
1021  out[2] = Vector<T, 3>::DotProduct(m2.GetColumn(0), row);
1022  out[5] = Vector<T, 3>::DotProduct(m2.GetColumn(1), row);
1023  out[8] = Vector<T, 3>::DotProduct(m2.GetColumn(2), row);
1024  }
1025 }
1026 /// @endcond
1027 
1028 /// @cond MATHFU_INTERNAL
1029 template <class T>
1030 inline void TimesHelper(const Matrix<T, 4, 4>& m1, const Matrix<T, 4, 4>& m2,
1031  Matrix<T, 4, 4>* out_m) {
1032  Matrix<T, 4, 4>& out = *out_m;
1033  {
1034  Vector<T, 4> row(m1[0], m1[4], m1[8], m1[12]);
1035  out[0] = Vector<T, 4>::DotProduct(m2.GetColumn(0), row);
1036  out[4] = Vector<T, 4>::DotProduct(m2.GetColumn(1), row);
1037  out[8] = Vector<T, 4>::DotProduct(m2.GetColumn(2), row);
1038  out[12] = Vector<T, 4>::DotProduct(m2.GetColumn(3), row);
1039  }
1040  {
1041  Vector<T, 4> row(m1[1], m1[5], m1[9], m1[13]);
1042  out[1] = Vector<T, 4>::DotProduct(m2.GetColumn(0), row);
1043  out[5] = Vector<T, 4>::DotProduct(m2.GetColumn(1), row);
1044  out[9] = Vector<T, 4>::DotProduct(m2.GetColumn(2), row);
1045  out[13] = Vector<T, 4>::DotProduct(m2.GetColumn(3), row);
1046  }
1047  {
1048  Vector<T, 4> row(m1[2], m1[6], m1[10], m1[14]);
1049  out[2] = Vector<T, 4>::DotProduct(m2.GetColumn(0), row);
1050  out[6] = Vector<T, 4>::DotProduct(m2.GetColumn(1), row);
1051  out[10] = Vector<T, 4>::DotProduct(m2.GetColumn(2), row);
1052  out[14] = Vector<T, 4>::DotProduct(m2.GetColumn(3), row);
1053  }
1054  {
1055  Vector<T, 4> row(m1[3], m1[7], m1[11], m1[15]);
1056  out[3] = Vector<T, 4>::DotProduct(m2.GetColumn(0), row);
1057  out[7] = Vector<T, 4>::DotProduct(m2.GetColumn(1), row);
1058  out[11] = Vector<T, 4>::DotProduct(m2.GetColumn(2), row);
1059  out[15] = Vector<T, 4>::DotProduct(m2.GetColumn(3), row);
1060  }
1061 }
1062 /// @endcond
1063 
1064 /// @cond MATHFU_INTERNAL
1065 /// @brief Compute the identity matrix.
1066 ///
1067 /// @note There are template specializations for 2x2, 3x3, and 4x4 matrices to
1068 /// increase performance.
1069 ///
1070 /// @return Identity Matrix.
1071 /// @tparam T Type of each element in the returned Matrix.
1072 /// @tparam rows Number of rows in the returned Matrix.
1073 /// @tparam columns Number of columns in the returned Matrix.
1074 template <class T, int rows, int columns>
1075 inline Matrix<T, rows, columns> IdentityHelper() {
1076  Matrix<T, rows, columns> return_matrix(0.f);
1077  int min_d = rows < columns ? rows : columns;
1078  for (int i = 0; i < min_d; ++i) return_matrix(i, i) = 1;
1079  return return_matrix;
1080 }
1081 /// @endcond
1082 
1083 /// @cond MATHFU_INTERNAL
1084 template <class T>
1085 inline Matrix<T, 2, 2> IdentityHelper() {
1086  return Matrix<T, 2, 2>(1, 0, 0, 1);
1087 }
1088 /// @endcond
1089 
1090 /// @cond MATHFU_INTERNAL
1091 template <class T>
1092 inline Matrix<T, 3, 3> IdentityHelper() {
1093  return Matrix<T, 3, 3>(1, 0, 0, 0, 1, 0, 0, 0, 1);
1094 }
1095 /// @endcond
1096 
1097 /// @cond MATHFU_INTERNAL
1098 template <class T>
1099 inline Matrix<T, 4, 4> IdentityHelper() {
1100  return Matrix<T, 4, 4>(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
1101 }
1102 /// @endcond
1103 
1104 /// @cond MATHFU_INTERNAL
1105 /// @brief Compute the outer product of two vectors.
1106 ///
1107 /// @note There are template specialization for 2x2, 3x3, and 4x4 matrices to
1108 /// increase performance.
1109 template <class T, int rows, int columns>
1110 static inline Matrix<T, rows, columns> OuterProductHelper(
1111  const Vector<T, rows>& v1, const Vector<T, columns>& v2) {
1112  Matrix<T, rows, columns> result(0);
1113  int offset = 0;
1114  for (int column = 0; column < columns; column++) {
1115  for (int row = 0; row < rows; row++) {
1116  result[row + offset] = v1[row] * v2[column];
1117  }
1118  offset += rows;
1119  }
1120  return result;
1121 }
1122 /// @endcond
1123 
1124 /// @cond MATHFU_INTERNAL
1125 template <class T>
1126 static inline Matrix<T, 2, 2> OuterProductHelper(const Vector<T, 2>& v1,
1127  const Vector<T, 2>& v2) {
1128  return Matrix<T, 2, 2>(v1[0] * v2[0], v1[1] * v2[0], v1[0] * v2[1],
1129  v1[1] * v2[1]);
1130 }
1131 /// @endcond
1132 
1133 /// @cond MATHFU_INTERNAL
1134 template <class T>
1135 static inline Matrix<T, 3, 3> OuterProductHelper(const Vector<T, 3>& v1,
1136  const Vector<T, 3>& v2) {
1137  return Matrix<T, 3, 3>(v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0],
1138  v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1],
1139  v1[0] * v2[2], v1[1] * v2[2], v1[2] * v2[2]);
1140 }
1141 /// @endcond
1142 
1143 /// @cond MATHFU_INTERNAL
1144 template <class T>
1145 static inline Matrix<T, 4, 4> OuterProductHelper(const Vector<T, 4>& v1,
1146  const Vector<T, 4>& v2) {
1147  return Matrix<T, 4, 4>(
1148  v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[3] * v2[0], v1[0] * v2[1],
1149  v1[1] * v2[1], v1[2] * v2[1], v1[3] * v2[1], v1[0] * v2[2], v1[1] * v2[2],
1150  v1[2] * v2[2], v1[3] * v2[2], v1[0] * v2[3], v1[1] * v2[3], v1[2] * v2[3],
1151  v1[3] * v2[3]);
1152 }
1153 /// @endcond
1154 
1155 /// @cond MATHFU_INTERNAL
1156 /// Struct used for template specialization for functions that
1157 /// returns constants.
1158 template <class T>
1159 class Constants {
1160  public:
1161  /// Minimum absolute value of the determinant of an invertible matrix.
1162  static T GetDeterminantThreshold() {
1163  // No constant defined for the general case.
1164  assert(false);
1165  return 0;
1166  }
1167 };
1168 /// @endcond
1169 
1170 /// Functions that return constants for <code>float</code> values.
1171 template <>
1172 class Constants<float> {
1173  public:
1174  /// @brief Minimum absolute value of the determinant of an invertible
1175  /// <code>float</code> Matrix.
1176  ///
1177  /// <code>float</code> values have 23 bits of precision which is roughly
1178  /// 1e7f, given that the final step of matrix inversion is multiplication
1179  /// with the inverse of the determinant, the minimum value of the
1180  /// determinant is 1e-7f before the precision too low to accurately
1181  /// calculate the inverse.
1182  /// @returns Minimum absolute value of the determinant of an invertible
1183  /// <code>float</code> Matrix.
1184  ///
1185  /// @related mathfu::Matrix::InverseWithDeterminantCheck()
1186  static float GetDeterminantThreshold() { return 1e-7f; }
1187 };
1188 
1189 /// Functions that return constants for <code>double</code> values.
1190 template <>
1191 class Constants<double> {
1192  public:
1193  /// @brief Minimum absolute value of the determinant of an invertible
1194  /// <code>double</code> Matrix.
1195  ///
1196  /// <code>double</code> values have 46 bits of precision which is roughly
1197  /// 1e15, given that the final step of matrix inversion is multiplication
1198  /// with the inverse of the determinant, the minimum value of the
1199  /// determinant is 1e-15 before the precision too low to accurately
1200  /// calculate the inverse.
1201  /// @returns Minimum absolute value of the determinant of an invertible
1202  /// <code>double</code> Matrix.
1203  ///
1204  /// @related mathfu::Matrix::InverseWithDeterminantCheck()
1205  static double GetDeterminantThreshold() { return 1e-15; }
1206 };
1207 
1208 /// @cond MATHFU_INTERNAL
1209 /// @brief Compute the inverse of a matrix.
1210 ///
1211 /// There is template specialization for 2x2, 3x3, and 4x4 matrices to
1212 /// increase performance. Inverse is not implemented for dense matrices that
1213 /// are not of size 2x2, 3x3, and 4x4. If check_invertible is true the
1214 /// determine of the matrix is compared with
1215 /// Constants<T>::GetDeterminantThreshold() to roughly determine whether the
1216 /// Matrix is invertible.
1217 template <bool check_invertible, class T, int rows, int columns>
1218 inline bool InverseHelper(const Matrix<T, rows, columns>& m,
1219  Matrix<T, rows, columns>* const inverse) {
1220  assert(false);
1221  (void)m;
1222  *inverse = T::Identity();
1223  return false;
1224 }
1225 /// @endcond
1226 
1227 /// @cond MATHFU_INTERNAL
1228 template <bool check_invertible, class T>
1229 inline bool InverseHelper(const Matrix<T, 2, 2>& m,
1230  Matrix<T, 2, 2>* const inverse) {
1231  T determinant = m[0] * m[3] - m[1] * m[2];
1232  if (check_invertible &&
1233  fabs(determinant) < Constants<T>::GetDeterminantThreshold()) {
1234  return false;
1235  }
1236  T inverseDeterminant = 1 / determinant;
1237  (*inverse)[0] = inverseDeterminant * m[3];
1238  (*inverse)[1] = -inverseDeterminant * m[1];
1239  (*inverse)[2] = -inverseDeterminant * m[2];
1240  (*inverse)[3] = inverseDeterminant * m[0];
1241  return true;
1242 }
1243 /// @endcond
1244 
1245 /// @cond MATHFU_INTERNAL
1246 template <bool check_invertible, class T>
1247 inline bool InverseHelper(const Matrix<T, 3, 3>& m,
1248  Matrix<T, 3, 3>* const inverse) {
1249  // Find determinant of matrix.
1250  T sub11 = m[4] * m[8] - m[5] * m[7], sub12 = -m[1] * m[8] + m[2] * m[7],
1251  sub13 = m[1] * m[5] - m[2] * m[4];
1252  T determinant = m[0] * sub11 + m[3] * sub12 + m[6] * sub13;
1253  if (check_invertible &&
1254  fabs(determinant) < Constants<T>::GetDeterminantThreshold()) {
1255  return false;
1256  }
1257  // Find determinants of 2x2 submatrices for the elements of the inverse.
1258  *inverse = Matrix<T, 3, 3>(
1259  sub11, sub12, sub13, m[6] * m[5] - m[3] * m[8], m[0] * m[8] - m[6] * m[2],
1260  m[3] * m[2] - m[0] * m[5], m[3] * m[7] - m[6] * m[4],
1261  m[6] * m[1] - m[0] * m[7], m[0] * m[4] - m[3] * m[1]);
1262  *(inverse) *= 1 / determinant;
1263  return true;
1264 }
1265 /// @endcond
1266 
1267 /// @cond MATHFU_INTERNAL
1268 template <class T>
1269 inline int FindLargestPivotElem(const Matrix<T, 4, 4>& m) {
1270  Vector<T, 4> fabs_column(fabs(m[0]), fabs(m[1]), fabs(m[2]), fabs(m[3]));
1271  if (fabs_column[0] > fabs_column[1]) {
1272  if (fabs_column[0] > fabs_column[2]) {
1273  if (fabs_column[0] > fabs_column[3]) {
1274  return 0;
1275  } else {
1276  return 3;
1277  }
1278  } else if (fabs_column[2] > fabs_column[3]) {
1279  return 2;
1280  } else {
1281  return 3;
1282  }
1283  } else if (fabs_column[1] > fabs_column[2]) {
1284  if (fabs_column[1] > fabs_column[3]) {
1285  return 1;
1286  } else {
1287  return 3;
1288  }
1289  } else if (fabs_column[2] > fabs_column[3]) {
1290  return 2;
1291  } else {
1292  return 3;
1293  }
1294 }
1295 /// @endcond
1296 
1297 /// @cond MATHFU_INTERNAL
1298 template <bool check_invertible, class T>
1299 bool InverseHelper(const Matrix<T, 4, 4>& m, Matrix<T, 4, 4>* const inverse) {
1300  // This will find the pivot element.
1301  int pivot_elem = FindLargestPivotElem(m);
1302  // This will perform the pivot and find the row, column, and 3x3 submatrix
1303  // for this pivot.
1304  Vector<T, 3> row, column;
1305  Matrix<T, 3> matrix;
1306  if (pivot_elem == 0) {
1307  row = Vector<T, 3>(m[4], m[8], m[12]);
1308  column = Vector<T, 3>(m[1], m[2], m[3]);
1309  matrix =
1310  Matrix<T, 3>(m[5], m[6], m[7], m[9], m[10], m[11], m[13], m[14], m[15]);
1311  } else if (pivot_elem == 1) {
1312  row = Vector<T, 3>(m[5], m[9], m[13]);
1313  column = Vector<T, 3>(m[0], m[2], m[3]);
1314  matrix =
1315  Matrix<T, 3>(m[4], m[6], m[7], m[8], m[10], m[11], m[12], m[14], m[15]);
1316  } else if (pivot_elem == 2) {
1317  row = Vector<T, 3>(m[6], m[10], m[14]);
1318  column = Vector<T, 3>(m[0], m[1], m[3]);
1319  matrix =
1320  Matrix<T, 3>(m[4], m[5], m[7], m[8], m[9], m[11], m[12], m[13], m[15]);
1321  } else {
1322  row = Vector<T, 3>(m[7], m[11], m[15]);
1323  column = Vector<T, 3>(m[0], m[1], m[2]);
1324  matrix =
1325  Matrix<T, 3>(m[4], m[5], m[6], m[8], m[9], m[10], m[12], m[13], m[14]);
1326  }
1327  T pivot_value = m[pivot_elem];
1328  if (check_invertible &&
1329  fabs(pivot_value) < Constants<T>::GetDeterminantThreshold()) {
1330  return false;
1331  }
1332  // This will compute the inverse using the row, column, and 3x3 submatrix.
1333  T inv = -1 / pivot_value;
1334  row *= inv;
1335  matrix += Matrix<T, 3>::OuterProduct(column, row);
1336  Matrix<T, 3> mat_inverse;
1337  if (!InverseHelper<check_invertible>(matrix, &mat_inverse) &&
1338  check_invertible) {
1339  return false;
1340  }
1341  Vector<T, 3> col_inverse = mat_inverse * (column * inv);
1342  Vector<T, 3> row_inverse = row * mat_inverse;
1343  T pivot_inverse = Vector<T, 3>::DotProduct(row, col_inverse) - inv;
1344  if (pivot_elem == 0) {
1345  *inverse = Matrix<T, 4, 4>(
1346  pivot_inverse, col_inverse[0], col_inverse[1], col_inverse[2],
1347  row_inverse[0], mat_inverse[0], mat_inverse[1], mat_inverse[2],
1348  row_inverse[1], mat_inverse[3], mat_inverse[4], mat_inverse[5],
1349  row_inverse[2], mat_inverse[6], mat_inverse[7], mat_inverse[8]);
1350  } else if (pivot_elem == 1) {
1351  *inverse = Matrix<T, 4, 4>(
1352  row_inverse[0], mat_inverse[0], mat_inverse[1], mat_inverse[2],
1353  pivot_inverse, col_inverse[0], col_inverse[1], col_inverse[2],
1354  row_inverse[1], mat_inverse[3], mat_inverse[4], mat_inverse[5],
1355  row_inverse[2], mat_inverse[6], mat_inverse[7], mat_inverse[8]);
1356  } else if (pivot_elem == 2) {
1357  *inverse = Matrix<T, 4, 4>(
1358  row_inverse[0], mat_inverse[0], mat_inverse[1], mat_inverse[2],
1359  row_inverse[1], mat_inverse[3], mat_inverse[4], mat_inverse[5],
1360  pivot_inverse, col_inverse[0], col_inverse[1], col_inverse[2],
1361  row_inverse[2], mat_inverse[6], mat_inverse[7], mat_inverse[8]);
1362  } else {
1363  *inverse = Matrix<T, 4, 4>(
1364  row_inverse[0], mat_inverse[0], mat_inverse[1], mat_inverse[2],
1365  row_inverse[1], mat_inverse[3], mat_inverse[4], mat_inverse[5],
1366  row_inverse[2], mat_inverse[6], mat_inverse[7], mat_inverse[8],
1367  pivot_inverse, col_inverse[0], col_inverse[1], col_inverse[2]);
1368  }
1369  return true;
1370 }
1371 /// @endcond
1372 
1373 /// @cond MATHFU_INTERNAL
1374 /// Create a 4x4 perpective matrix.
1375 template <class T>
1376 inline Matrix<T, 4, 4> PerspectiveHelper(T fovy, T aspect, T znear, T zfar,
1377  T handedness) {
1378  const T y = 1 / std::tan(fovy * static_cast<T>(.5));
1379  const T x = y / aspect;
1380  const T zdist = (znear - zfar);
1381  const T zfar_per_zdist = zfar / zdist;
1382  return Matrix<T, 4, 4>(x, 0, 0, 0, 0, y, 0, 0, 0, 0,
1383  zfar_per_zdist * handedness, -1 * handedness, 0, 0,
1384  2.0f * znear * zfar_per_zdist, 0);
1385 }
1386 /// @endcond
1387 
1388 /// @cond MATHFU_INTERNAL
1389 /// Create a 4x4 orthographic matrix.
1390 template <class T>
1391 static inline Matrix<T, 4, 4> OrthoHelper(T left, T right, T bottom, T top,
1392  T znear, T zfar, T handedness) {
1393  return Matrix<T, 4, 4>(static_cast<T>(2) / (right - left), 0, 0, 0, 0,
1394  static_cast<T>(2) / (top - bottom), 0, 0, 0, 0,
1395  -handedness * static_cast<T>(2) / (zfar - znear), 0,
1396  -(right + left) / (right - left),
1397  -(top + bottom) / (top - bottom),
1398  -(zfar + znear) / (zfar - znear), static_cast<T>(1));
1399 }
1400 /// @endcond
1401 
1402 /// @cond MATHFU_INTERNAL
1403 /// Calculate the axes required to construct a 3-dimensional camera matrix that
1404 /// looks at "at" from eye position "eye" with the up vector "up". The axes
1405 /// are returned in a 4 element "axes" array.
1406 template <class T>
1407 static void LookAtHelperCalculateAxes(const Vector<T, 3>& at,
1408  const Vector<T, 3>& eye,
1409  const Vector<T, 3>& up, T handedness,
1410  Vector<T, 3>* const axes) {
1411  // Notice that y-axis is always the same regardless of handedness.
1412  axes[2] = (at - eye).Normalized();
1413  axes[0] = Vector<T, 3>::CrossProduct(up, axes[2]).Normalized();
1414  axes[1] = Vector<T, 3>::CrossProduct(axes[2], axes[0]);
1415  axes[3] = Vector<T, 3>(handedness * Vector<T, 3>::DotProduct(axes[0], eye),
1416  -Vector<T, 3>::DotProduct(axes[1], eye),
1417  handedness * Vector<T, 3>::DotProduct(axes[2], eye));
1418 
1419  // Default calculation is left-handed (i.e. handedness=-1).
1420  // Negate x and z axes for right-handed (i.e. handedness=+1) case.
1421  const T neg = -handedness;
1422  axes[0] *= neg;
1423  axes[2] *= neg;
1424 }
1425 /// @endcond
1426 
1427 /// @cond MATHFU_INTERNAL
1428 /// Create a 3-dimensional camera matrix.
1429 template <class T>
1430 static inline Matrix<T, 4, 4> LookAtHelper(const Vector<T, 3>& at,
1431  const Vector<T, 3>& eye,
1432  const Vector<T, 3>& up,
1433  T handedness) {
1434  Vector<T, 3> axes[4];
1435  LookAtHelperCalculateAxes(at, eye, up, handedness, axes);
1436  const Vector<T, 4> column0(axes[0][0], axes[1][0], axes[2][0], 0);
1437  const Vector<T, 4> column1(axes[0][1], axes[1][1], axes[2][1], 0);
1438  const Vector<T, 4> column2(axes[0][2], axes[1][2], axes[2][2], 0);
1439  const Vector<T, 4> column3(axes[3], 1);
1440  return Matrix<T, 4, 4>(column0, column1, column2, column3);
1441 }
1442 /// @endcond
1443 
1444 /// @cond MATHFU_INTERNAL
1445 /// Get the 3D position in object space from a window coordinate.
1446 template <class T>
1447 static inline bool UnProjectHelper(const Vector<T, 3>& window_coord,
1448  const Matrix<T, 4, 4>& model_view,
1449  const Matrix<T, 4, 4>& projection,
1450  const float window_width,
1451  const float window_height,
1452  Vector<T, 3>& result) {
1453  if (window_coord.z < static_cast<T>(0) ||
1454  window_coord.z > static_cast<T>(1)) {
1455  // window_coord.z should be with in [0, 1]
1456  // 0: near plane
1457  // 1: far plane
1458  return false;
1459  }
1460  Matrix<T, 4, 4> matrix = (projection * model_view).Inverse();
1461  Vector<T, 4> standardized = Vector<T, 4>(
1462  static_cast<T>(2) * (window_coord.x - window_width) / window_width +
1463  static_cast<T>(1),
1464  static_cast<T>(2) * (window_coord.y - window_height) / window_height +
1465  static_cast<T>(1),
1466  static_cast<T>(2) * window_coord.z - static_cast<T>(1),
1467  static_cast<T>(1));
1468 
1469  Vector<T, 4> multiply = matrix * standardized;
1470  if (multiply.w == static_cast<T>(0)) {
1471  return false;
1472  }
1473  result = multiply.xyz() / multiply.w;
1474  return true;
1475 }
1476 /// @endcond
1477 
1478 /// @cond MATHFU_INTERNAL
1479 template <typename T, int rows, int columns, typename CompatibleT>
1480 static inline Matrix<T, rows, columns> FromTypeHelper(const CompatibleT& compatible) {
1481 // C++11 is required for constructed unions.
1482 #if __cplusplus >= 201103L
1483  // Use a union instead of reinterpret_cast to avoid aliasing bugs.
1484  union ConversionUnion {
1485  ConversionUnion() {} // C++11.
1486  CompatibleT compatible;
1487  VectorPacked<T, rows> packed[columns];
1488  } u;
1489  static_assert(sizeof(u.compatible) == sizeof(u.packed), "Conversion size mismatch.");
1490 
1491  // The read of `compatible` and write to `u.compatible` gets optimized away,
1492  // and this becomes essentially a safe reinterpret_cast.
1493  u.compatible = compatible;
1494 
1495  // Call the packed vector constructor with the `compatible` data.
1496  return Matrix<T, rows, columns>(u.packed);
1497 #else
1498  // Use the less-desirable memcpy technique if C++11 is not available.
1499  // Most compilers understand memcpy deep enough to avoid replace the function
1500  // call with a series of load/stores, which should then get optimized away,
1501  // however in the worst case the optimize away may not happen.
1502  // Note: Memcpy avoids aliasing bugs because it operates via unsigned char*,
1503  // which is allowed to alias any type.
1504  // See:
1505  // http://stackoverflow.com/questions/15745030/type-punning-with-void-without-breaking-the-strict-aliasing-rule-in-c99
1506  Matrix<T, rows, columns> m;
1507  assert(sizeof(m) == sizeof(compatible));
1508  memcpy(&m, &compatible, sizeof(m));
1509  return m;
1510 #endif // __cplusplus >= 201103L
1511 }
1512 /// @endcond
1513 
1514 /// @cond MATHFU_INTERNAL
1515 template <typename T, int rows, int columns, typename CompatibleT>
1516 static inline CompatibleT ToTypeHelper(const Matrix<T, rows, columns>& m) {
1517 // See FromTypeHelper() for comments.
1518 #if __cplusplus >= 201103L
1519  union ConversionUnion {
1520  ConversionUnion() {}
1521  CompatibleT compatible;
1522  VectorPacked<T, rows> packed[columns];
1523  } u;
1524  static_assert(sizeof(u.compatible) == sizeof(u.packed), "Conversion size mismatch.");
1525  m.Pack(u.packed);
1526  return u.compatible;
1527 #else
1528  CompatibleT compatible;
1529  assert(sizeof(m) == sizeof(compatible));
1530  memcpy(&compatible, &m, sizeof(compatible));
1531  return compatible;
1532 #endif // __cplusplus >= 201103L
1533 }
1534 /// @endcond
1535 
1536 /// @typedef AffineTransform
1537 ///
1538 /// @brief A typedef representing a 4x3 float affine transformation.
1539 /// Since the last row ('w' row) of an affine transformation is fixed,
1540 /// this data type only includes the variable information for the transform.
1542 /// @}
1543 
1544 } // namespace mathfu
1545 
1546 #ifdef _MSC_VER
1547 #pragma warning(pop)
1548 #endif
1549 
1550 // Include the specializations to avoid template errors.
1551 // See includes at bottom of vector.h for further explanation.
1552 #include "mathfu/matrix_4x4.h"
1553 
1554 #endif // MATHFU_MATRIX_H_
Matrix(const T &s00, const T &s10, const T &s20, const T &s01, const T &s11, const T &s21, const T &s02, const T &s12, const T &s22)
Create a Matrix from nine floats.
Definition: matrix.h:193
Definition: vector_3.h:24
T & operator()(const int row, const int column)
Access an element of the Matrix.
Definition: matrix.h:305
Matrix< T, rows, columns > Inverse() const
Calculate the inverse of this Matrix.
Definition: matrix.h:511
static Matrix< T, 3 > RotationX(T angle)
Create a 3x3 rotation Matrix from an angle (in radians) around the X axis.
Definition: matrix.h:748
Vector< T, 3 > TranslationVector3D() const
Get the 3-dimensional translation of a 3-dimensional affine transform.
Definition: matrix.h:563
static Matrix< T, 4, 4 > LookAt(const Vector< T, 3 > &at, const Vector< T, 3 > &eye, const Vector< T, 3 > &up, T handedness=-1)
Create a 3-dimensional camera Matrix.
Definition: matrix.h:807
Matrix()
Construct a Matrix of uninitialized values.
Definition: matrix.h:150
static Matrix< T, 3 > RotationZ(T angle)
Create a 3x3 rotation Matrix from an angle (in radians) around the Z axis.
Definition: matrix.h:766
static Matrix< T, 4 > FromAffineTransform(const Matrix< T, 4, 3 > &affine)
Constructs a Matrix<float, 4> from an AffineTransform.
Definition: matrix.h:696
static const int kElements
Total number of elements in the matrix.
Definition: matrix.h:853
Matrix< T, rows, columns > & operator*=(const T &s)
Multiply each element of this Matrix with a scalar (in-place).
Definition: matrix.h:483
Definition: vector_2.h:24
T & operator()(const int i)
Access an element of the Matrix.
Definition: matrix.h:321
Utility macros and functions.
Matrix< T, rows, columns > & operator*=(const Matrix< T, rows, columns > &m)
Multiply this Matrix with another Matrix (in-place).
Definition: matrix.h:499
Matrix(const T &s00, const T &s10, const T &s20, const T &s30, const T &s01, const T &s11, const T &s21, const T &s31, const T &s02, const T &s12, const T &s22, const T &s32, const T &s03, const T &s13, const T &s23, const T &s33)
Create a Matrix from sixteen floats.
Definition: matrix.h:248
static Matrix< T, 4, 4 > Ortho(T left, T right, T bottom, T top, T znear, T zfar, T handedness=1)
Create a 4x4 orthographic Matrix.
Definition: matrix.h:793
static float GetDeterminantThreshold()
Minimum absolute value of the determinant of an invertible float Matrix.
Definition: matrix.h:1186
bool InverseWithDeterminantCheck(Matrix< T, rows, columns > *const inverse) const
Calculate the inverse of this Matrix.
Definition: matrix.h:532
#define MATHFU_DEFINE_CLASS_SIMD_AWARE_NEW_DELETE
Macro which defines the new and delete for MathFu classes.
Definition: utilities.h:600
static double GetDeterminantThreshold()
Minimum absolute value of the determinant of an invertible double Matrix.
Definition: matrix.h:1205
friend Vector< T, columns > operator*(const Vector< T, rows > &v, const Matrix< T, rows, columns > &m)
Multiply a Vector by a Matrix.
Definition: matrix.h:841
T & operator[](const int i)
Access an element of the Matrix.
Definition: matrix.h:337
static Matrix< T, 4 > FromRotationMatrix(const Matrix< T, 3 > &m)
Create a 4x4 Matrix from a 3x3 rotation Matrix.
Definition: matrix.h:675
static Matrix< T, rows > FromScaleVector(const Vector< T, rows-1 > &v)
Create a square Matrix with the diagonal component set to v.
Definition: matrix.h:659
static Vector< T, 3 > UnProject(const Vector< T, 3 > &window_coord, const Matrix< T, 4, 4 > &model_view, const Matrix< T, 4, 4 > &projection, const float window_width, const float window_height)
Get the 3D position in object space from a window coordinate.
Definition: matrix.h:825
Matrix< T, rows, columns > operator+(const Matrix< T, rows, columns > &m) const
Add a Matrix to this Matrix.
Definition: matrix.h:388
Matrix stores a set of "rows" by "columns" elements of type T and provides functions that operate on ...
Definition: matrix.h:147
#define MATHFU_STATIC_ASSERT(x)
Compile time assert for pre-C++11 compilers.
Definition: utilities.h:244
Matrix< T, rows, columns > & operator+=(const Matrix< T, rows, columns > &m)
Add a Matrix to this Matrix (in-place).
Definition: matrix.h:449
static Matrix< T, rows, columns > HadamardProduct(const Matrix< T, rows, columns > &m1, const Matrix< T, rows, columns > &m2)
Calculate the hadamard / component-wise product of two matrices.
Definition: matrix.h:619
static Matrix< T, rows, columns > OuterProduct(const Vector< T, rows > &v1, const Vector< T, columns > &v2)
Calculate the outer product of two Vectors.
Definition: matrix.h:609
Matrix< T, rows, columns > operator*(const T &s) const
Multiply each element of this Matrix with a scalar.
Definition: matrix.h:422
const T & operator()(const int row, const int column) const
Access an element of the matrix.
Definition: matrix.h:296
Matrix(const VectorPacked< T, rows > *const vectors)
Create a Matrix from an array of "columns", "rows" element packed vectors.
Definition: matrix.h:287
Matrix(const T &s00, const T &s10, const T &s20, const T &s30, const T &s01, const T &s11, const T &s21, const T &s31, const T &s02, const T &s12, const T &s22, const T &s32)
Creates a Matrix from twelve floats.
Definition: matrix.h:219
Matrix(const Vector< T, 4 > &column0, const Vector< T, 4 > &column1, const Vector< T, 4 > &column2, const Vector< T, 4 > &column3)
Create 4x4 Matrix from 4, 4 element vectors.
Definition: matrix.h:267
Matrix< T, rows, columns > operator*(const T &s, const Matrix< T, columns, rows > &m)
Multiply each element of a Matrix by a scalar.
Definition: matrix.h:876
static Matrix< T, 3 > RotationZ(const Vector< T, 2 > &v)
Create a 3x3 rotation Matrix from a 2D normalized directional Vector around the Z axis...
Definition: matrix.h:739
Vector< T, d > operator*(const Vector< T, d > &lhs, const Vector< T, d > &rhs)
Multiply a vector by another Vector.
Definition: vector.h:589
Vector< T, 2 > TranslationVector2D() const
Get the 2-dimensional translation of a 2-dimensional affine transform.
Definition: matrix.h:553
static Matrix< T, rows, columns > FromType(const CompatibleT &compatible)
Load from any byte-wise compatible external matrix.
Definition: matrix.h:585
const T & operator()(const int i) const
Access an element of the Matrix.
Definition: matrix.h:314
Definition: vector_4.h:25
static Matrix< T, 3 > RotationY(const Vector< T, 2 > &v)
Create a 3x3 rotation Matrix from a 2D normalized directional Vector around the Y axis...
Definition: matrix.h:730
Matrix< float, 4, 3 > AffineTransform
A typedef representing a 4x3 float affine transformation. Since the last row ('w' row) of an affine t...
Definition: matrix.h:1541
Matrix(const T &s00, const T &s10, const T &s01, const T &s11)
Construct a Matrix from four floats.
Definition: matrix.h:174
static T DotProduct(const Vector< T, d > &v1, const Vector< T, d > &v2)
Calculate the dot product of two vectors.
Definition: vector.h:426
static const int kColumns
Number of columns in the matrix.
Definition: matrix.h:851
Vector< T, 3 > operator*(const Matrix< T, 4, 4 > &m, const Vector< T, 3 > &v)
Multiply a 4x4 Matrix by a 3-dimensional Vector.
Definition: matrix.h:953
static Matrix< T, 4, 4 > Perspective(T fovy, T aspect, T znear, T zfar, T handedness=1)
Create a 4x4 perspective Matrix.
Definition: matrix.h:778
static CompatibleT ToType(const Matrix< T, rows, columns > &m)
Load into any byte-wise compatible external matrix.
Definition: matrix.h:602
static Matrix< T, 3 > RotationX(const Vector< T, 2 > &v)
Create a 3x3 rotation Matrix from a 2D normalized directional Vector around the X axis...
Definition: matrix.h:721
const T & operator[](const int i) const
Access an element of the Matrix.
Definition: matrix.h:328
static Matrix< T, 3 > ToRotationMatrix(const Matrix< T, 4 > &m)
Extracts the 3x3 rotation Matrix from a 4x4 Matrix.
Definition: matrix.h:687
Matrix(const T *const a)
Create a Matrix from the first row * column elements of an array.
Definition: matrix.h:279
Matrix< T, rows, columns > & operator-=(const Matrix< T, rows, columns > &m)
Subtract a Matrix from this Matrix (in-place).
Definition: matrix.h:458
Packed N-dimensional vector.
Definition: vector.h:121
Matrix< T, rows, columns > & operator-=(const T &s)
Subtract a scalar from each element of this Matrix (in-place).
Definition: matrix.h:475
Vector class and functions.
static Matrix< T, rows, columns > Identity()
Calculate the identity Matrix.
Definition: matrix.h:627
void Pack(VectorPacked< T, rows > *const vector) const
Pack the matrix to an array of "rows" element vectors, one vector per matrix column.
Definition: matrix.h:357
Matrix< T, rows, columns > & operator/=(const T &s)
Divide each element of this Matrix by a scalar (in-place).
Definition: matrix.h:491
Matrix< T, rows, columns > operator-() const
Negate this Matrix.
Definition: matrix.h:380
static Matrix< T, 4 > FromTranslationVector(const Vector< T, 3 > &v)
Create a 4x4 translation Matrix from a 3-dimensional Vector.
Definition: matrix.h:647
Matrix(const Matrix< T, rows, columns > &m)
Construct a Matrix from another Matrix copying each element. /.
Definition: matrix.h:155
Matrix< T, rows, columns > operator/(const T &s) const
Divide each element of this Matrix with a scalar.
Definition: matrix.h:430
static Matrix< T, 3 > FromTranslationVector(const Vector< T, 2 > &v)
Create a 3x3 translation Matrix from a 2-dimensional Vector.
Definition: matrix.h:637
Matrix< T, rows, columns > operator*(const Matrix< T, rows, columns > &m) const
Multiply this Matrix with another Matrix.
Definition: matrix.h:438
static Matrix< T, 4, 3 > ToAffineTransform(const Matrix< T, 4 > &m)
Converts a Matrix<float, 4> into an AffineTransform.
Definition: matrix.h:711
Vector< T, rows > operator*(const Matrix< T, rows, columns > &m, const Vector< T, columns > &v)
Multiply a Matrix by a Vector.
Definition: matrix.h:893
Matrix(const T &s)
Construct a Matrix from a single float.
Definition: matrix.h:162
static Vector< T, 3 > CrossProduct(const Vector< T, 3 > &v1, const Vector< T, 3 > &v2)
Calculate the cross product of two vectors.
Definition: vector.h:446
Matrix< T, rows, columns > operator+(const T &s) const
Add a scalar to each element of this Matrix.
Definition: matrix.h:406
Matrix< T, rows, columns > operator-(const Matrix< T, rows, columns > &m) const
Subtract a Matrix from this Matrix.
Definition: matrix.h:397
Matrix< T, columns, rows > Transpose() const
Calculate the transpose of this Matrix.
Definition: matrix.h:540
Matrix< T, rows, columns > operator-(const T &s) const
Subtract a scalar from each element of this Matrix.
Definition: matrix.h:414
static Matrix< T, 3 > RotationY(T angle)
Create a 3x3 rotation Matrix from an angle (in radians) around the Y axis.
Definition: matrix.h:757
Matrix< T, rows, columns > & operator+=(const T &s)
Add a scalar to each element of this Matrix (in-place).
Definition: matrix.h:467
static const int kRows
Number of rows in the matrix.
Definition: matrix.h:849