Gamedev Framework (gf)  0.5.0
A C++11 framework for 2D games
Matrix.h
1 /*
2  * Gamedev Framework (gf)
3  * Copyright (C) 2016-2017 Julien Bernard
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 #ifndef GF_MATRIX_H
22 #define GF_MATRIX_H
23 
24 #include <cstddef>
25 #include <algorithm>
26 
27 #include "Portability.h"
28 #include "Vector.h"
29 
30 namespace gf {
31 #ifndef DOXYGEN_SHOULD_SKIP_THIS
32 inline namespace v1 {
33 #endif
34 
58  template<typename T, std::size_t ROWS, std::size_t COLS>
59  struct Matrix {
60  #ifndef DOXYGEN_SHOULD_SKIP_THIS
61  static_assert(ROWS > 0, "ROWS must be strictly positive");
62  static_assert(COLS > 0, "COLS must be strictly positive");
63  #endif
64 
68  using value_type = T;
69 
73  static constexpr std::size_t Rows = ROWS;
74 
78  static constexpr std::size_t Cols = COLS;
79 
83  Matrix() = default;
84 
88  explicit Matrix(T val) {
89  std::fill_n(data, ROWS * COLS, val);
90  }
91 
95  union {
96  T grid[ROWS][COLS];
97  T data[ROWS * COLS];
98  };
99  };
100 
118  template<typename T>
119  struct Matrix<T, 2, 2> {
123  using value_type = T;
124 
128  static constexpr std::size_t Rows = 2;
129 
133  static constexpr std::size_t Cols = 2;
134 
138  Matrix() = default;
139 
148  constexpr Matrix(T xx, T xy, T yx, T yy)
149  : data{xx, xy, yx, yy}
150  {
151 
152  }
153 
157  union {
158  T grid[2][2];
159  T data[4];
160  struct {
161  T xx, xy;
162  T yx, yy;
163  };
164  };
165  };
166 
184  template<typename T>
185  struct Matrix<T, 3, 3> {
189  using value_type = T;
190 
194  static constexpr std::size_t Rows = 3;
195 
199  static constexpr std::size_t Cols = 3;
200 
204  Matrix() = default;
205 
219  constexpr Matrix(T xx, T xy, T xz, T yx, T yy, T yz, T zx, T zy, T zz)
220  : data{xx, xy, xz, yx, yy, yz, zx, zy, zz}
221  {
222 
223  }
224 
228  union {
229  T grid[3][3];
230  T data[9];
231  struct {
232  T xx, xy, xz;
233  T yx, yy, yz;
234  T zx, zy, zz;
235  };
236  };
237  };
238 
254  template<typename T>
255  struct Matrix<T, 4, 4> {
259  using value_type = T;
260 
264  static constexpr std::size_t Rows = 4;
265 
269  static constexpr std::size_t Cols = 4;
270 
291  constexpr Matrix(T xx, T xy, T xz, T xw, T yx, T yy, T yz, T yw, T zx, T zy, T zz, T zw, T wx, T wy, T wz, T ww)
292  : data{xx, xy, xz, xw, yx, yy, yz, yw, zx, zy, zz, zw, wx, wy, wz, ww}
293  {
294 
295  }
296 
300  union {
301  T grid[4][4];
302  T data[16];
303  struct {
304  T xx, xy, xz, xw;
305  T yx, yy, yz, yw;
306  T zx, zy, zz, zw;
307  T wx, wy, wz, ww;
308  };
309  };
310  };
311 
319 
327 
335 
336 // MSVC does not like extern template
337 #ifndef _MSC_VER
338  extern template struct Matrix<float, 2, 2>;
339  extern template struct Matrix<float, 3, 3>;
340  extern template struct Matrix<float, 4, 4>;
341 #endif
342 
343  /*
344  * equality operations
345  */
346 
351  template<typename T, std::size_t ROWS, std::size_t COLS>
352  inline
354  for (std::size_t i = 0; i < ROWS; ++i) {
355  for (std::size_t j = 0; j < COLS; ++j) {
356  if (lhs.grid[i][j] != rhs.grid[i][j]) {
357  return false;
358  }
359  }
360  }
361 
362  return true;
363  }
364 
369  template<typename T, std::size_t ROWS, std::size_t COLS>
370  inline
372  return !(lhs == rhs);
373  }
374 
375  /*
376  * unary operators
377  */
378 
383  template<typename T, std::size_t ROWS, std::size_t COLS>
384  inline
387 
388  for (std::size_t i = 0; i < ROWS; ++i) {
389  for (std::size_t j = 0; j < COLS; ++j) {
390  out.grid[i][j] = - val.grid[i][j];
391  }
392  }
393 
394  return out;
395  }
396 
397  /*
398  * arithmetic component-wise operations
399  */
400 
405  template<typename T, std::size_t ROWS, std::size_t COLS>
406  inline
409 
410  for (std::size_t i = 0; i < ROWS; ++i) {
411  for (std::size_t j = 0; j < COLS; ++j) {
412  out.grid[i][j] = lhs.grid[i][j] + rhs.grid[i][j];
413  }
414  }
415 
416  return out;
417  }
418 
423  template<typename T, std::size_t ROWS, std::size_t COLS>
424  inline
426  for (std::size_t i = 0; i < ROWS; ++i) {
427  for (std::size_t j = 0; j < COLS; ++j) {
428  lhs.grid[i][j] += rhs.grid[i][j];
429  }
430  }
431 
432  return lhs;
433  }
434 
435 
440  template<typename T, std::size_t ROWS, std::size_t COLS>
441  inline
444 
445  for (std::size_t i = 0; i < ROWS; ++i) {
446  for (std::size_t j = 0; j < COLS; ++j) {
447  out.grid[i][j] = lhs.grid[i][j] - rhs.grid[i][j];
448  }
449  }
450 
451  return out;
452  }
453 
458  template<typename T, std::size_t ROWS, std::size_t COLS>
459  inline
461  for (std::size_t i = 0; i < ROWS; ++i) {
462  for (std::size_t j = 0; j < COLS; ++j) {
463  lhs.grid[i][j] -= rhs.grid[i][j];
464  }
465  }
466 
467  return lhs;
468  }
469 
470  /*
471  * multiplication and division
472  */
473 
478  template<typename T, std::size_t ROWS, std::size_t COLS>
479  inline
482 
483  for (std::size_t i = 0; i < ROWS; ++i) {
484  for (std::size_t j = 0; j < COLS; ++j) {
485  out.grid[i][j] = lhs.grid[i][j] * rhs;
486  }
487  }
488 
489  return out;
490  }
491 
496  template<typename T, std::size_t ROWS, std::size_t COLS>
497  inline
499  for (std::size_t i = 0; i < ROWS; ++i) {
500  for (std::size_t j = 0; j < COLS; ++j) {
501  lhs.grid[i][j] *= rhs;
502  }
503  }
504 
505  return lhs;
506  }
507 
512  template<typename T, std::size_t ROWS, std::size_t COLS>
513  inline
516 
517  for (std::size_t i = 0; i < ROWS; ++i) {
518  for (std::size_t j = 0; j < COLS; ++j) {
519  out.grid[i][j] = lhs * rhs.grid[i][j];
520  }
521  }
522 
523  return out;
524  }
525 
530  template<typename T, std::size_t ROWS, std::size_t COLS>
531  inline
534 
535  for (std::size_t i = 0; i < ROWS; ++i) {
536  for (std::size_t j = 0; j < COLS; ++j) {
537  out.grid[i][j] = lhs.grid[i][j] / rhs;
538  }
539  }
540 
541  return out;
542  }
543 
548  template<typename T, std::size_t ROWS, std::size_t COLS>
549  inline
551  for (std::size_t i = 0; i < ROWS; ++i) {
552  for (std::size_t j = 0; j < COLS; ++j) {
553  lhs.grid[i][j] /= rhs;
554  }
555  }
556 
557  return lhs;
558  }
559 
564  template<typename T, std::size_t S1, std::size_t S2>
565  inline
567  Vector<T, S1> out;
568 
569  for (std::size_t i = 0; i < S1; ++i) {
570  T val{0};
571 
572  for (std::size_t j = 0; j < S2; ++j) {
573  val += lhs.grid[i][j] * rhs.data[j];
574  }
575 
576  out.data[i] = val;
577  }
578 
579  return out;
580  }
581 
586  template<typename T, std::size_t S1, std::size_t S2>
587  inline
589  Vector<T, S2> out;
590 
591  for (std::size_t j = 0; j < S2; ++j) {
592  T val{0};
593 
594  for (std::size_t i = 0; i < S1; ++i) {
595  val += lhs.data[i] * rhs.grid[i][j];
596  }
597 
598  out.data[j] = val;
599  }
600 
601  return out;
602  }
603 
604 
609  template<typename T, std::size_t S1, std::size_t S2, std::size_t S3>
610  inline
612  Matrix<T, S1, S3> out;
613 
614  for (std::size_t i = 0; i < S1; ++i) {
615  for (std::size_t j = 0; j < S3; ++j) {
616  T val{0};
617 
618  for (std::size_t k = 0; k < S2; ++k) {
619  val += lhs.grid[i][k] * rhs.grid[k][j];
620  }
621 
622  out.grid[i][j] = val;
623  }
624  }
625 
626  return out;
627  }
628 
635  template<typename T, std::size_t N>
636  inline
638  lhs = lhs * rhs;
639  return lhs;
640  }
641 
642  /*
643  * usual operations
644  */
645 
652  template<typename MatrixType>
653  inline
654  MatrixType identity() {
655  static_assert(MatrixType::Rows == MatrixType::Cols, "identity() is only defined for square matrices.");
656 
657  MatrixType out;
658 
659  typedef typename MatrixType::value_type value_type;
660 
661  for (std::size_t i = 0; i < MatrixType::Rows; ++i) {
662  for (std::size_t j = 0; j < MatrixType::Cols; ++j) {
663  out.grid[i][j] = (i == j) ? value_type{1} : value_type{0};
664  }
665  }
666 
667  return out;
668  }
669 
674  template<typename T, std::size_t S1, std::size_t S2>
675  inline
677  Matrix<T, S2, S1> out;
678 
679  for (std::size_t i = 0; i < S1; ++i) {
680  for (std::size_t j = 0; j < S2; ++j) {
681  out.grid[j][i] = mat.grid[i][j];
682  }
683  }
684 
685  return out;
686  }
687 
688  // https://en.wikipedia.org/wiki/Invertible_matrix
689 
694  template<typename T>
695  inline
697  Matrix<T, 2, 2> out;
698 
699  out.xx = mat.yy;
700  out.xy = - mat.xy;
701  out.yx = - mat.yx;
702  out.yy = mat.xx;
703 
704  T det = mat.xx * mat.yy - mat.yx * mat.xy;
705  out /= det;
706  return out;
707  }
708 
713  template<typename T>
714  inline
716  Matrix<T, 3, 3> out;
717 
718  out.xx = mat.yy * mat.zz - mat.zy * mat.yz;
719  out.xy = - (mat.xy * mat.zz - mat.zy * mat.xz);
720  out.xz = mat.xy * mat.yz - mat.yy * mat.xz;
721  out.yx = - (mat.yx * mat.zz - mat.zx * mat.yz);
722  out.yy = mat.xx * mat.zz - mat.zx * mat.xz;
723  out.yz = - (mat.xx * mat.yz - mat.yx * mat.xz);
724  out.zx = mat.yx * mat.zy - mat.zx * mat.yy;
725  out.zy = - (mat.xx * mat.zy - mat.zx * mat.xy);
726  out.zz = mat.xx * mat.yy - mat.yx * mat.xy;
727 
728  T det = mat.xx * out.xx + mat.xy * out.yx + mat.xz * out.zx;
729  out /= det;
730  return out;
731  }
732 
733 #ifndef DOXYGEN_SHOULD_SKIP_THIS
734 }
735 #endif
736 }
737 
738 #endif // GAME_MATRIX_H
Matrix< T, 3, 3 > invert(const Matrix< T, 3, 3 > &mat)
Inversion of a 3x3 matrix.
Definition: Matrix.h:715
Matrix< T, S2, S1 > transpose(const Matrix< T, S1, S2 > &mat)
Transposition of a matrix.
Definition: Matrix.h:676
bool operator==(const Matrix< T, ROWS, COLS > &lhs, const Matrix< T, ROWS, COLS > &rhs)
Equality operator between two matrices.
Definition: Matrix.h:353
Matrix< T, ROWS, COLS > operator+(const Matrix< T, ROWS, COLS > &lhs, const Matrix< T, ROWS, COLS > &rhs)
Component-wise addition.
Definition: Matrix.h:407
T yx
Definition: Matrix.h:162
Matrix< T, ROWS, COLS > operator*(T lhs, const Matrix< T, ROWS, COLS > &rhs)
Left scalar multiplication.
Definition: Matrix.h:514
Matrix< T, 2, 2 > invert(const Matrix< T, 2, 2 > &mat)
Inversion of a 2x2 matrix.
Definition: Matrix.h:696
Matrix< T, ROWS, COLS > & operator/=(Matrix< T, ROWS, COLS > &lhs, T rhs)
Right scalar division and assignment.
Definition: Matrix.h:550
constexpr Matrix(T xx, T xy, T yx, T yy)
Constructor that takes all the elements.
Definition: Matrix.h:148
bool operator!=(const Matrix< T, ROWS, COLS > &lhs, const Matrix< T, ROWS, COLS > &rhs)
Inequality operator between two matrices.
Definition: Matrix.h:371
T zz
Definition: Matrix.h:234
T yy
Definition: Matrix.h:233
T wz
Definition: Matrix.h:307
T xx
Definition: Matrix.h:232
T grid[ROWS][COLS]
Grid representation.
Definition: Matrix.h:96
MatrixType identity()
Identity matrix.
Definition: Matrix.h:654
Vector< T, S2 > operator*(const Vector< T, S1 > &lhs, const Matrix< T, S1, S2 > &rhs)
Vector-matrix multiplication.
Definition: Matrix.h:588
T xy
Definition: Matrix.h:232
Matrix(T val)
Constructor that fills the matrix with a value.
Definition: Matrix.h:88
Matrix< T, ROWS, COLS > & operator-=(Matrix< T, ROWS, COLS > &lhs, const Matrix< T, ROWS, COLS > &rhs)
Component-wise substraction and assignment.
Definition: Matrix.h:460
Matrix< T, ROWS, COLS > operator-(const Matrix< T, ROWS, COLS > &lhs, const Matrix< T, ROWS, COLS > &rhs)
Component-wise substraction.
Definition: Matrix.h:442
Matrix< T, ROWS, COLS > operator/(const Matrix< T, ROWS, COLS > &lhs, T rhs)
Right scalar division.
Definition: Matrix.h:532
Vector< T, S1 > operator*(const Matrix< T, S1, S2 > &lhs, const Vector< T, S2 > &rhs)
Matrix-vector multiplication.
Definition: Matrix.h:566
Matrix< T, S1, S3 > operator*(const Matrix< T, S1, S2 > &lhs, const Matrix< T, S2, S3 > &rhs)
Matrix-matrix multiplication.
Definition: Matrix.h:611
T data[N]
The internal representation of the vector.
Definition: Vector.h:251
T xy
Definition: Matrix.h:161
T yy
Definition: Matrix.h:162
General purpose math matrix.
Definition: Matrix.h:59
T zy
Definition: Matrix.h:234
float value_type
The value type of the elements of the matrix.
Definition: Matrix.h:68
The namespace for gf classes.
Definition: Action.h:34
T yz
Definition: Matrix.h:305
T xz
Definition: Matrix.h:304
T value_type
The value type of the elements of the matrix.
Definition: Matrix.h:259
T xz
Definition: Matrix.h:232
Matrix< T, ROWS, COLS > & operator*=(Matrix< T, ROWS, COLS > &lhs, T rhs)
Right scalar multiplication and assignment.
Definition: Matrix.h:498
T xx
Definition: Matrix.h:161
constexpr Matrix(T xx, T xy, T xz, T yx, T yy, T yz, T zx, T zy, T zz)
Constructor that takes all the elements.
Definition: Matrix.h:219
T value_type
The value type of the elements of the matrix.
Definition: Matrix.h:123
T zx
Definition: Matrix.h:234
Matrix< T, N, N > & operator*=(Matrix< T, N, N > &lhs, const Matrix< T, N, N > &rhs)
Matrix-matrix multiplication and assignment.
Definition: Matrix.h:637
T yz
Definition: Matrix.h:233
T zz
Definition: Matrix.h:306
Matrix< T, ROWS, COLS > & operator+=(Matrix< T, ROWS, COLS > &lhs, const Matrix< T, ROWS, COLS > &rhs)
Component-wise addition and assignment.
Definition: Matrix.h:425
T value_type
The value type of the elements of the matrix.
Definition: Matrix.h:189
Matrix< T, ROWS, COLS > operator-(const Matrix< T, ROWS, COLS > &val)
Component-wise unary minus.
Definition: Matrix.h:385
General purpose math vector.
Definition: Vector.h:60
A 3x3 matrix.
Definition: Matrix.h:185
A 2x2 matrix.
Definition: Matrix.h:119
constexpr Matrix(T xx, T xy, T xz, T xw, T yx, T yy, T yz, T yw, T zx, T zy, T zz, T zw, T wx, T wy, T wz, T ww)
Constructor that takes all the elements.
Definition: Matrix.h:291
Matrix< T, ROWS, COLS > operator*(const Matrix< T, ROWS, COLS > &lhs, T rhs)
Right scalar multiplication.
Definition: Matrix.h:480
T yx
Definition: Matrix.h:233