MathFu
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Typedefs Friends Groups Pages
matrix_4x4_simd.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_4X4_SIMD_H_
17 #define MATHFU_MATRIX_4X4_SIMD_H_
18 
19 #include "mathfu/matrix.h"
20 
21 #ifdef MATHFU_COMPILE_WITH_SIMD
22 #include "vectorial/simd4x4f.h"
23 #endif
24 
25 /// @file mathfu/internal/matrix_4x4_simd.h MathFu Matrix<T, 4, 4>
26 /// Specialization
27 /// @brief 4x4 specialization of mathfu::Matrix for SIMD optimized builds.
28 /// @see mathfu::Matrix
29 
30 namespace mathfu {
31 
32 #ifdef MATHFU_COMPILE_WITH_SIMD
33 
34 static const Vector<float, 4> kAffineWColumn(0.0f, 0.0f, 0.0f, 1.0f);
35 
36 /// @cond MATHFU_INTERNAL
37 template <>
38 class Matrix<float, 4> {
39  public:
40  Matrix<float, 4>() {}
41 
42  inline Matrix<float, 4>(const Matrix<float, 4>& m) {
43  data_.simd_matrix.x = m.data_.simd_matrix.x;
44  data_.simd_matrix.y = m.data_.simd_matrix.y;
45  data_.simd_matrix.z = m.data_.simd_matrix.z;
46  data_.simd_matrix.w = m.data_.simd_matrix.w;
47  }
48 
49  explicit inline Matrix<float, 4>(const float& s) {
50  simd4f v = simd4f_create(s, s, s, s);
51  data_.simd_matrix = simd4x4f_create(v, v, v, v);
52  }
53 
54  inline Matrix<float, 4>(const float& s00, const float& s10, const float& s20,
55  const float& s30, const float& s01, const float& s11,
56  const float& s21, const float& s31, const float& s02,
57  const float& s12, const float& s22, const float& s32,
58  const float& s03, const float& s13, const float& s23,
59  const float& s33) {
60  data_.simd_matrix = simd4x4f_create(
61  simd4f_create(s00, s10, s20, s30), simd4f_create(s01, s11, s21, s31),
62  simd4f_create(s02, s12, s22, s32), simd4f_create(s03, s13, s23, s33));
63  }
64 
65  explicit inline Matrix<float, 4>(const float* m) {
66  data_.simd_matrix =
67  simd4x4f_create(simd4f_create(m[0], m[1], m[2], m[3]),
68  simd4f_create(m[4], m[5], m[6], m[7]),
69  simd4f_create(m[8], m[9], m[10], m[11]),
70  simd4f_create(m[12], m[13], m[14], m[15]));
71  }
72 
73  inline Matrix<float, 4>(const Vector<float, 4>& column0,
74  const Vector<float, 4>& column1,
75  const Vector<float, 4>& column2,
76  const Vector<float, 4>& column3) {
77 #if defined(MATHFU_COMPILE_WITH_PADDING)
78  data_.simd_matrix = simd4x4f_create(column0.data_.simd, column1.data_.simd,
79  column2.data_.simd, column3.data_.simd);
80 #else
81  data_.simd_matrix = simd4x4f_create(
82  simd4f_create(column0[0], column0[1], column0[2], column0[3]),
83  simd4f_create(column1[0], column1[1], column1[2], column1[3]),
84  simd4f_create(column2[0], column2[1], column2[2], column2[3]),
85  simd4f_create(column3[0], column3[1], column3[2], column3[3]));
86 #endif // defined(MATHFU_COMPILE_WITH_PADDING)
87  }
88 
89  explicit inline Matrix(const VectorPacked<float, 4>* const vectors) {
90  data_.simd_matrix.x = simd4f_uload4(vectors[0].data);
91  data_.simd_matrix.y = simd4f_uload4(vectors[1].data);
92  data_.simd_matrix.z = simd4f_uload4(vectors[2].data);
93  data_.simd_matrix.w = simd4f_uload4(vectors[3].data);
94  }
95 
96  inline const float& operator()(const int i, const int j) const {
97  return FindElem(i, FindColumn(j));
98  }
99 
100  inline float& operator()(const int i, const int j) {
101  return FindElem(i, FindColumn(j));
102  }
103 
104  inline const float& operator()(const int i) const {
105  return this->operator[](i);
106  }
107 
108  inline float& operator()(const int i) { return this->operator[](i); }
109 
110  inline const float& operator[](const int i) const {
111  const int col = i / 4;
112  const int row = i % 4;
113  return FindElem(row, FindColumn(col));
114  }
115 
116  inline float& operator[](const int i) {
117  const int col = i / 4;
118  const int row = i % 4;
119  return FindElem(row, FindColumn(col));
120  }
121 
122  inline void Pack(VectorPacked<float, 4>* const vector) const {
123  simd4f_ustore4(data_.simd_matrix.x, vector[0].data);
124  simd4f_ustore4(data_.simd_matrix.y, vector[1].data);
125  simd4f_ustore4(data_.simd_matrix.z, vector[2].data);
126  simd4f_ustore4(data_.simd_matrix.w, vector[3].data);
127  }
128 
129  inline Matrix<float, 4> operator-() const {
130  Matrix<float, 4> m(0.f);
131  simd4x4f_sub(&m.data_.simd_matrix, &data_.simd_matrix,
132  &m.data_.simd_matrix);
133  return m;
134  }
135 
136  inline Matrix<float, 4> operator+(const Matrix<float, 4>& m) const {
137  Matrix<float, 4> return_m;
138  simd4x4f_add(&data_.simd_matrix, &m.data_.simd_matrix,
139  &return_m.data_.simd_matrix);
140  return return_m;
141  }
142 
143  inline Matrix<float, 4> operator-(const Matrix<float, 4>& m) const {
144  Matrix<float, 4> return_m;
145  simd4x4f_sub(&data_.simd_matrix, &m.data_.simd_matrix,
146  &return_m.data_.simd_matrix);
147  return return_m;
148  }
149 
150  inline Matrix<float, 4> operator*(const float& s) const {
151  Matrix<float, 4> m(s);
152  simd4x4f_mul(&m.data_.simd_matrix, &data_.simd_matrix,
153  &m.data_.simd_matrix);
154  return m;
155  }
156 
157  inline Matrix<float, 4> operator/(const float& s) const {
158  Matrix<float, 4> m(1 / s);
159  simd4x4f_mul(&m.data_.simd_matrix, &data_.simd_matrix,
160  &m.data_.simd_matrix);
161  return m;
162  }
163 
164  inline Vector<float, 3> operator*(const Vector<float, 3>& v) const {
165  Vector<float, 3> return_v;
166  Simd4fUnion temp_v;
167 #ifdef MATHFU_COMPILE_WITH_PADDING
168  temp_v.simd = v.data_.simd;
169  temp_v.float_array[3] = 1;
170  simd4x4f_matrix_vector_mul(&data_.simd_matrix, &temp_v.simd,
171  &return_v.data_.simd);
172  return_v *= (1 / return_v.data_.float_array[3]);
173 #else
174  temp_v.simd = simd4f_create(v[0], v[1], v[2], 1.0f);
175  simd4x4f_matrix_vector_mul(&data_.simd_matrix, &temp_v.simd, &temp_v.simd);
176  simd4f_mul(temp_v.simd, simd4f_splat(temp_v.float_array[3]));
177  MATHFU_VECTOR3_STORE3(temp_v.simd, return_v.data_);
178 #endif // MATHFU_COMPILE_WITH_PADDING
179  return return_v;
180  }
181 
182  inline Vector<float, 4> operator*(const Vector<float, 4>& v) const {
183  Vector<float, 4> return_v;
184  simd4x4f_matrix_vector_mul(&data_.simd_matrix, &v.data_.simd,
185  &return_v.data_.simd);
186  return return_v;
187  }
188 
189  inline Vector<float, 4> VecMatTimes(const Vector<float, 4>& v) const {
190  return Vector<float, 4>(
191  simd4f_dot3_scalar(v.data_.simd, data_.simd_matrix.x),
192  simd4f_dot3_scalar(v.data_.simd, data_.simd_matrix.y),
193  simd4f_dot3_scalar(v.data_.simd, data_.simd_matrix.z),
194  simd4f_dot3_scalar(v.data_.simd, data_.simd_matrix.w));
195  }
196 
197  inline Matrix<float, 4> operator*(const Matrix<float, 4>& m) const {
198  Matrix<float, 4> return_m;
199  simd4x4f_matrix_mul(&data_.simd_matrix, &m.data_.simd_matrix,
200  &return_m.data_.simd_matrix);
201  return return_m;
202  }
203 
204  inline Matrix<float, 4> Inverse() const {
205  Matrix<float, 4> return_m;
206  simd4x4f_inverse(&data_.simd_matrix, &return_m.data_.simd_matrix);
207  return return_m;
208  }
209 
210  inline bool InverseWithDeterminantCheck(
211  Matrix<float, 4, 4>* const inverse) const {
212  return fabs(simd4f_get_x(simd4x4f_inverse(&data_.simd_matrix,
213  &inverse->data_.simd_matrix))) >=
215  }
216 
217  /// Calculate the transpose of matrix.
218  /// @return The transpose of the specified matrix.
219  inline Matrix<float, 4, 4> Transpose() const {
220  Matrix<float, 4, 4> transpose;
221  simd4x4f_transpose(&data_.simd_matrix, &transpose.data_.simd_matrix);
222  return transpose;
223  }
224 
225  inline Vector<float, 3> TranslationVector3D() const {
226  Vector<float, 3> return_v;
227  MATHFU_VECTOR3_STORE3(FindColumn(3).simd, return_v.data_);
228  return return_v;
229  }
230 
231  inline Matrix<float, 4>& operator+=(const Matrix<float, 4>& m) {
232  simd4x4f_add(&data_.simd_matrix, &m.data_.simd_matrix, &data_.simd_matrix);
233  return *this;
234  }
235 
236  inline Matrix<float, 4>& operator-=(const Matrix<float, 4>& m) {
237  simd4x4f_sub(&data_.simd_matrix, &m.data_.simd_matrix, &data_.simd_matrix);
238  return *this;
239  }
240 
241  inline Matrix<float, 4>& operator*=(const float& s) {
242  Matrix<float, 4> m(s);
243  simd4x4f_mul(&m.data_.simd_matrix, &data_.simd_matrix, &data_.simd_matrix);
244  return *this;
245  }
246 
247  inline Matrix<float, 4>& operator/=(const float& s) {
248  Matrix<float, 4> m(1 / s);
249  simd4x4f_mul(&m.data_.simd_matrix, &data_.simd_matrix, &data_.simd_matrix);
250  return *this;
251  }
252 
253  inline Matrix<float, 4> operator*=(const Matrix<float, 4>& m) {
254  Matrix<float, 4> copy_of_this(*this);
255  simd4x4f_matrix_mul(&copy_of_this.data_.simd_matrix, &m.data_.simd_matrix,
256  &data_.simd_matrix);
257  return *this;
258  }
259 
260  template <typename CompatibleT>
261  static inline Matrix<float, 4> FromType(const CompatibleT& compatible) {
262  return FromTypeHelper<float, 4, 4, CompatibleT>(compatible);
263  }
264 
265  template <typename CompatibleT>
266  static inline CompatibleT ToType(const Matrix<float, 4>& m) {
267  return ToTypeHelper<float, 4, 4, CompatibleT>(m);
268  }
269 
270  static inline Matrix<float, 4> OuterProduct(const Vector<float, 4>& v1,
271  const Vector<float, 4>& v2) {
272  Matrix<float, 4> m;
273  m.data_.simd_matrix =
274  simd4x4f_create(simd4f_mul(v1.data_.simd, simd4f_splat(v2[0])),
275  simd4f_mul(v1.data_.simd, simd4f_splat(v2[1])),
276  simd4f_mul(v1.data_.simd, simd4f_splat(v2[2])),
277  simd4f_mul(v1.data_.simd, simd4f_splat(v2[3])));
278  return m;
279  }
280 
281  static inline Matrix<float, 4> HadamardProduct(const Matrix<float, 4>& m1,
282  const Matrix<float, 4>& m2) {
283  Matrix<float, 4> return_m;
284  simd4x4f_mul(&m1.data_.simd_matrix, &m2.data_.simd_matrix,
285  &return_m.data_.simd_matrix);
286  return return_m;
287  }
288 
289  static inline Matrix<float, 4> Identity() {
290  Matrix<float, 4> return_m;
291  simd4x4f_identity(&return_m.data_.simd_matrix);
292  return return_m;
293  }
294 
295  static inline Matrix<float, 4> FromTranslationVector(
296  const Vector<float, 3>& v) {
297  return Matrix<float, 4>(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, v[0], v[1],
298  v[2], 1);
299  }
300 
301  static inline Matrix<float, 4> FromScaleVector(const Vector<float, 3>& v) {
302  return Matrix<float, 4>(v[0], 0, 0, 0, 0, v[1], 0, 0, 0, 0, v[2], 0, 0, 0,
303  0, 1);
304  }
305 
306  static inline Matrix<float, 4> FromRotationMatrix(const Matrix<float, 3>& m) {
307  return Matrix<float, 4>(m[0], m[1], m[2], 0, m[3], m[4], m[5], 0, m[6],
308  m[7], m[8], 0, 0, 0, 0, 1);
309  }
310 
311  /// @brief Constructs a Matrix<float, 4> from an AffineTransform.
312  ///
313  /// @param affine An AffineTransform reference to be used to construct
314  /// a Matrix<float, 4> by adding in the 'w' row of [0, 0, 0, 1].
315  static inline Matrix<float, 4> FromAffineTransform(
316  const AffineTransform& affine) {
317  Matrix<float, 4> m;
318  m.data_.simd_matrix.x = simd4f_uload4(&affine[0]);
319  m.data_.simd_matrix.y = simd4f_uload4(&affine[4]);
320  m.data_.simd_matrix.z = simd4f_uload4(&affine[8]);
321  m.data_.simd_matrix.w = simd4f_uload4(&kAffineWColumn[0]);
322  return m.Transpose();
323  }
324 
325  /// @brief Converts a Matrix<float, 4> into an AffineTransform.
326  ///
327  /// @param m A Matrix<float, 4> reference to be converted into an
328  /// AffineTransform by dropping the fixed 'w' row.
329  ///
330  /// @return Returns an AffineTransform that contains the essential
331  /// transformation data from the Matrix<float, 4>.
332  static inline AffineTransform ToAffineTransform(const Matrix<float, 4>& m) {
333  AffineTransform affine;
334  const Matrix<float, 4> mt = m.Transpose();
335  simd4f_ustore4(mt.data_.simd_matrix.x, &affine[0]);
336  simd4f_ustore4(mt.data_.simd_matrix.y, &affine[4]);
337  simd4f_ustore4(mt.data_.simd_matrix.z, &affine[8]);
338  return affine;
339  }
340 
341  /// Create a 4x4 perpective matrix.
342  /// @handedness: 1.0f for RH, -1.0f for LH
343  static inline Matrix<float, 4, 4> Perspective(float fovy, float aspect,
344  float znear, float zfar,
345  float handedness = 1.0f) {
346  return PerspectiveHelper(fovy, aspect, znear, zfar, handedness);
347  }
348 
349  /// Create a 4x4 orthographic matrix.
350  /// @param handedness 1.0f for RH, -1.0f for LH
351  static inline Matrix<float, 4, 4> Ortho(float left, float right, float bottom,
352  float top, float znear, float zfar,
353  float handedness = 1.0f) {
354  return OrthoHelper(left, right, bottom, top, znear, zfar, handedness);
355  }
356 
357  /// Create a 3-dimensional camera matrix.
358  /// @param at The look-at target of the camera.
359  /// @param eye The position of the camera.
360  /// @param up The up vector in the world, for example (0, 1, 0) if the
361  /// @handedness: 1.0f for RH, -1.0f for LH
362  /// TODO: Change default handedness to 1.0f, to match Perspective().
363  /// y-axis is up.
364  static inline Matrix<float, 4, 4> LookAt(const Vector<float, 3>& at,
365  const Vector<float, 3>& eye,
366  const Vector<float, 3>& up,
367  float handedness = -1.0f) {
368  return LookAtHelper(at, eye, up, handedness);
369  }
370 
371  /// @brief Get the 3D position in object space from a window coordinate.
372  ///
373  /// @param window_coord The window coordinate. The z value is for depth.
374  /// A window coordinate on the near plane will have 0 as the z value.
375  /// And a window coordinate on the far plane will have 1 as the z value.
376  /// z value should be with in [0, 1] here.
377  /// @param model_view The Model View matrix.
378  /// @param projection The projection matrix.
379  /// @param window_width Width of the window.
380  /// @param window_height Height of the window.
381  /// @return the mapped 3D position in object space.
382  static inline Vector<float, 3> UnProject(
383  const Vector<float, 3>& window_coord,
384  const Matrix<float, 4, 4>& model_view,
385  const Matrix<float, 4, 4>& projection, const float window_width,
386  const float window_height) {
387  Vector<float, 3> result;
388  UnProjectHelper(window_coord, model_view, projection, window_width,
389  window_height, result);
390  return result;
391  }
392 
393  // Dimensions of the matrix.
394  /// Number of rows in the matrix.
395  static const int kRows = 4;
396  /// Number of columns in the matrix.
397  static const int kColumns = 4;
398  /// Total number of elements in the matrix.
399  static const int kElements = 4 * 4;
400 
402 
403  private:
404  inline const Simd4fUnion& FindColumn(const int i) const {
405  return data_.simd4f_union_array[i];
406  }
407 
408  inline Simd4fUnion& FindColumn(const int i) {
409  return data_.simd4f_union_array[i];
410  }
411 
412  static inline const float& FindElem(const int i, const Simd4fUnion& column) {
413  return column.float_array[i];
414  }
415 
416  static inline float& FindElem(const int i, Simd4fUnion& column) {
417  return column.float_array[i];
418  }
419 
420  // Contents of the Matrix in different representations to work around
421  // strict aliasing rules.
422  union {
423  simd4x4f simd_matrix;
424  Simd4fUnion simd4f_union_array[4];
425  float float_array[16];
426  } data_;
427 };
428 
429 inline Matrix<float, 4> operator*(const float& s, const Matrix<float, 4>& m) {
430  return m * s;
431 }
432 
433 inline Vector<float, 4> operator*(const Vector<float, 4>& v,
434  const Matrix<float, 4>& m) {
435  return m.VecMatTimes(v);
436 }
437 /// @endcond
438 #endif // MATHFU_COMPILE_WITH_SIMD
439 } // namespace mathfu
440 
441 #endif // MATHFU_MATRIX_4X4_SIMD_H_
Matrix< T, rows, columns > Inverse() const
Calculate the inverse of this Matrix.
Definition: matrix.h:511
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, 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
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 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
MATHFU_DEFINE_CLASS_SIMD_AWARE_NEW_DELETE T data_[d]
Elements of the vector.
Definition: vector.h:495
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< 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
Vector< T, d > operator*(const Vector< T, d > &lhs, const Vector< T, d > &rhs)
Multiply a vector by another Vector.
Definition: vector.h:589
static Matrix< T, rows, columns > FromType(const CompatibleT &compatible)
Load from any byte-wise compatible external matrix.
Definition: matrix.h:585
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 class and functions.
static const int kColumns
Number of columns in the matrix.
Definition: matrix.h:851
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
const T & operator[](const int i) const
Access an element of the Matrix.
Definition: matrix.h:328
Matrix< T, rows, columns > & operator-=(const Matrix< T, rows, columns > &m)
Subtract a Matrix from this Matrix (in-place).
Definition: matrix.h:458
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
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
static Matrix< T, 4, 3 > ToAffineTransform(const Matrix< T, 4 > &m)
Converts a Matrix<float, 4> into an AffineTransform.
Definition: matrix.h:711
Matrix< T, columns, rows > Transpose() const
Calculate the transpose of this Matrix.
Definition: matrix.h:540
static const int kRows
Number of rows in the matrix.
Definition: matrix.h:849