TurtleBrains  0.3.5
High quality, portable, C++ framework for rapid 2D game development.
tb_matrix.hpp
1 
9 #ifndef TurtleBrains_Matrix_hpp
10 #define TurtleBrains_Matrix_hpp
11 
12 #include <turtle_brains/math/tb_vector.hpp>
13 #include <turtle_brains/math/tb_angle.hpp>
14 #include <turtle_brains/core/tb_error.hpp>
15 #include <turtle_brains/core/tb_defines.hpp>
16 
17 #include <cmath>
18 #include <cstring> //memcpy / memset
19 
20 // TODO: TurtleBrains: Make Identity() a constexpr static member function. Readup on constexpr
21 
22 //Pre-Multiply (vector on left), Bases Contiguous:
23 // Xx, Xy, Xz, 0
24 // Yx, Yy, Yz, 0
25 // Zx, Zy, Zz, 0
26 // Tx, Ty, Tz, 1
27 // Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1
28 
29 //
30 // The above is close to what I desire, but the data in matrix test kit is showing that we have something much different
31 // probably looking like (basis/rotation 3x3 unconfirmed): Xx, Xy, Xz, Tx, Yx, Yy, Yz, Ty, Zx, Zy Zz, Tz, 0, 0, 0, 1
32 // as that is how our test data is being shoved into the matrix object... 2020-11-25
33 //
34 // This was found because FastInverse() did not work in doing physics; FastInverse() was using the final COLUMN as the
35 // placement of translation/position and the above shows the final row being used. Changing FastInverse() breaks the
36 // previous tests, so what gives?
37 //
38 // To make this matter even more interesting, the CreateTranslation() function does put the position components in the
39 // final ROW as it shows in the above 'image'. The mat(1, 3) operator is specified by: column, row and memory is accessed
40 // by components[column + (row * 4)]; CreateTranslation() then puts translation at mat(0, 3), mat(1, 3), mat(2, 3) aka: Final row.
41 //
42 // Intrets says pre-multiply, vector*matrix, should have the translation on the last row.
43 //
44 // There was only a single instance of FastInverse() called in Rally of Rockets, and that instance didn't even use
45 // the positional data. This tells me that the test likely contains bad data and we just got really lucky in Rally of Rockets
46 // to use TransformNormal() instead of TransformCoordinate(). There were no occurances of FastInverse() in Turbo Boom!,
47 // Track Builder, and LudumDare47.
48 //
49 // 2020-11-26 - FastInverse() was fixed and the test data was also fixed. Essentially the 16 skeletal animation matrices
50 // provided by shakesoda had translation in the final column while our matrix actually does expect it in the final ROW.
51 // While I was adjust the translation data (only moving translation from final column to final row), shakesoda said this
52 // was suspect and I was doing it wrong, but never gave more information on why that was the case. Since every other test
53 // was passing except for the known broken FastInverse, moving translation data in those matrices fixed everything once
54 // FastInverse() was also fixed. (FastInverse had to swap final column for final row and also pre/post mulitply direction.
55 //
56 
57 namespace TurtleBrains
58 {
59  namespace Math
60  {
61  namespace Unstable
62  {
63  class Quaternion;
64  };
65 
66  enum ColumnMajorMatrix
67  {
68  ColumnMajor = 1,
69  };
70 
71  //Forward Declarations used in Matrix4 class.
72  class Matrix3;
73  class Matrix4;
74  Vector3* Vector3MatrixMultiply(Vector3* result, const Vector3* inputVector, const Matrix3* inputMatrix);
75  Vector3* MatrixVector3Multiply(Vector3* result, const Matrix3* inputMatrix, const Vector3* inputVector);
76  Matrix3* MatrixMultiply(Matrix3* result, const Matrix3* left, const Matrix3* right);
77  Matrix4* MatrixMultiply(Matrix4* result, const Matrix4* left, const Matrix4* right);
78  Matrix3* MatrixMultiply(Matrix3* result, const Matrix3* input, const float scalar);
79  Matrix4* MatrixMultiply(Matrix4* result, const Matrix4* input, const float scalar);
80 
81  Matrix3* MatrixComputeInverse(Matrix3* result, const Matrix3* input);
82  Matrix4* MatrixComputeInverse(Matrix4* result, const Matrix4* input);
83  Matrix3* MatrixFastInverse(Matrix3* result, const Matrix3* input);
84  Matrix4* MatrixFastInverse(Matrix4* result, const Matrix4* input);
85  Vector3* Vector3TransformCoordinate(Vector3* result, const Vector3* inputVector, const Matrix4* inputMatrix);
86  Vector3* Vector3TransformNormal(Vector3* result, const Vector3* inputVector, const Matrix4* inputMatrix);
87  Vector4* Vector4MatrixMultiply(Vector4* result, const Vector4* inputVector, const Matrix4* inputMatrix);
88  Vector4* MatrixVector4Multiply(Vector4* result, const Matrix4* inputMatrix, const Vector4* inputVector);
89 
90  Matrix4* MatrixCreateTranslation(Matrix4* result, const Vector3* translation);
91  Matrix4* MatrixCreateTranslation(Matrix4* result, const float translationX, const float translationY, const float translationZ);
92  Matrix3* MatrixCreateScale(Matrix3* result, const Vector3* scale);
93  Matrix4* MatrixCreateScale(Matrix4* result, const Vector3* scale);
94  Matrix3* MatrixCreateScale(Matrix3* result, const float scaleX, const float scaleY, const float scaleZ);
95  Matrix4* MatrixCreateScale(Matrix4* result, const float scaleX, const float scaleY, const float scaleZ);
96  Matrix3* MatrixCreateRotationX(Matrix3* result, const Angle rotation);
97  Matrix4* MatrixCreateRotationX(Matrix4* result, const Angle rotation);
98  Matrix3* MatrixCreateRotationY(Matrix3* result, const Angle rotation);
99  Matrix4* MatrixCreateRotationY(Matrix4* result, const Angle rotation);
100  Matrix3* MatrixCreateRotationZ(Matrix3* result, const Angle rotation);
101  Matrix4* MatrixCreateRotationZ(Matrix4* result, const Angle rotation);
102  Matrix3* MatrixCreateRotationA(Matrix3* result, const Vector3* rotationAxis, const Angle rotation);
103  Matrix4* MatrixCreateRotationA(Matrix4* result, const Vector3* rotationAxis, const Angle rotation);
104 
111  class Matrix3
112  {
113  public:
117  static Matrix3 Zero(void)
118  {
119  return Matrix3(
120  0.0f, 0.0f, 0.0f,
121  0.0f, 0.0f, 0.0f,
122  0.0f, 0.0f, 0.0f);
123  }
124 
129  static Matrix3 Identity(void)
130  {
131  return Matrix3(
132  1.0f, 0.0f, 0.0f,
133  0.0f, 1.0f, 0.0f,
134  0.0f, 0.0f, 1.0f);
135  }
136 
137  static Matrix3 Scale(const tbMath::Vector3& scale)
138  {
139  Matrix3 matrix(tbMath::kSkipInitialization);
140  tbMath::MatrixCreateScale(&matrix, &scale);
141  return matrix;
142  }
143 
144  static Matrix3 Scale(const float scaleX, const float scaleY, const float scaleZ)
145  {
146  Matrix3 matrix(tbMath::kSkipInitialization);
147  tbMath::MatrixCreateScale(&matrix, scaleX, scaleY, scaleZ);
148  return matrix;
149  }
150 
151  static Matrix3 RotationX(const Angle& rotation)
152  {
153  Matrix3 matrix(tbMath::kSkipInitialization);
154  tbMath::MatrixCreateRotationX(&matrix, rotation);
155  return matrix;
156  }
157 
158  static Matrix3 RotationY(const Angle& rotation)
159  {
160  Matrix3 matrix(tbMath::kSkipInitialization);
161  tbMath::MatrixCreateRotationY(&matrix, rotation);
162  return matrix;
163  }
164 
165  static Matrix3 RotationZ(const Angle& rotation)
166  {
167  Matrix3 matrix(tbMath::kSkipInitialization);
168  tbMath::MatrixCreateRotationZ(&matrix, rotation);
169  return matrix;
170  }
171 
172  static Matrix3 RotationA(const tbMath::Vector3& rotationAxis, const Angle& rotation)
173  {
174  Matrix3 matrix(tbMath::kSkipInitialization);
175  tbMath::MatrixCreateRotationA(&matrix, &rotationAxis, rotation);
176  return matrix;
177  }
178 
179  //Defined in tb_matrix_quaternion.h
180  static Matrix3 FromQuaternion(const tbMath::Unstable::Quaternion& quaternion);
181 
182  union
183  {
184  float mComponents[9];
185 
186 #if defined(tb_visual_cpp)
187 #pragma warning(push)
188 #pragma warning(disable: 4201)
189  struct { //May be deprecating!?
190  float m_f11; float m_f21; float m_f31;
191  float m_f12; float m_f22; float m_f32;
192  float m_f13; float m_f23; float m_f33;
193  };
194 #pragma warning(pop)
195 #else
196  struct { //May be deprecating!?
197  float m_f11; float m_f21; float m_f31;
198  float m_f12; float m_f22; float m_f32;
199  float m_f13; float m_f23; float m_f33;
200  };
201 #endif
202  };
203 
207  inline Matrix3(void) :
208  mComponents{
209  1.0f, 0.0f, 0.0f,
210  0.0f, 1.0f, 0.0f,
211  0.0f, 0.0f, 1.0f }
212  {
213  }
214 
218  inline explicit Matrix3(float f11, float f21, float f31,
219  float f12, float f22, float f32,
220  float f13, float f23, float f33) :
221  mComponents{
222  f11, f21, f31,
223  f12, f22, f32,
224  f13, f23, f33 }
225  {
226  }
227 
233  inline explicit Matrix3(const float * const componentArray) :
234  mComponents{
235  componentArray[0], componentArray[1], componentArray[2],
236  componentArray[3], componentArray[4], componentArray[5],
237  componentArray[6], componentArray[7], componentArray[8] }
238  {
239  }
240 
247  inline explicit Matrix3(const SkipInitialization& fastAndStupid)
248  {
249  tb_unused(fastAndStupid);
250  }
251 
255  inline Matrix3(const Matrix3& other) :
256  mComponents{
257  other.mComponents[0], other.mComponents[1], other.mComponents[2],
258  other.mComponents[3], other.mComponents[4], other.mComponents[5],
259  other.mComponents[6], other.mComponents[7], other.mComponents[8]}
260  {
261  }
262 
266  inline Matrix3& operator=(const Matrix3& other)
267  {
268  memcpy(mComponents, other.mComponents, sizeof(float) * 9);
269  return (*this);
270  }
271 
282  inline bool operator==(const Matrix3& other) const
283  {
284  for (size_t index(0); index < 9; ++index)
285  {
286  if (false == IsEqual(mComponents[index], other[index]))
287  {
288  return false;
289  }
290  }
291 
292  return true;
293  }
294 
300  inline bool operator!=(const Matrix3& other) const
301  {
302  for (size_t index(0); index < 9; ++index)
303  {
304  if (false == IsEqual(mComponents[index], other[index]))
305  {
306  return true;
307  }
308  }
309 
310  return false;
311  }
312 
317  inline const float& operator[](const int& index) const { return mComponents[index]; }
318 
324  inline float& operator[](const int& index) { return mComponents[index]; }
325 
330  inline const float& operator()(const size_t& column, const size_t& row) const { return mComponents[column + (row * 3)]; }
331 
337  inline float& operator()(const size_t& column, const size_t& row) { return mComponents[column + (row * 3)]; }
338 
343  inline const float& operator()(int column, int row) const { return mComponents[column + (row * 3)]; }
344 
350  inline float& operator()(int column, int row) { return mComponents[column + (row * 3)]; }
351 
359  inline explicit operator float*(void) { return mComponents; }
360 
364  inline explicit operator const float*(void) const { return mComponents; }
365 
373  inline const Vector3 GetBasis(const size_t& basisIndex) const { return Vector3(&mComponents[basisIndex * 3]); }
374 
381  inline void SetBasis(const size_t& basisIndex, const Vector3 &basis) { *((Vector3*)&mComponents[basisIndex * 3]) = basis; }
382 
391  inline void SetBasis(const size_t& basisIndex, float basisX, float basisY, float basisZ)
392  {
393  mComponents[(basisIndex * 3) + 0] = basisX;
394  mComponents[(basisIndex * 3) + 1] = basisY;
395  mComponents[(basisIndex * 3) + 2] = basisZ;
396  }
397 
398  inline Vector3 Transform(const Vector3& inputVector) const
399  {
400  Vector3 result;
401  Vector3MatrixMultiply(&result, &inputVector, this);
402  return result;
403  }
404 
405 #if defined(tb_with_math_operators)
406  inline Matrix3 operator+(const Matrix3& rightSide) const
410  {
411  const Matrix3& leftSide(*this);
412  return Matrix3(
413  leftSide(0, 0) + rightSide(0, 0), leftSide(1, 0) + rightSide(1, 0), leftSide(2, 0) + rightSide(2, 0),
414  leftSide(0, 1) + rightSide(0, 1), leftSide(1, 1) + rightSide(1, 1), leftSide(2, 1) + rightSide(2, 1),
415  leftSide(0, 2) + rightSide(0, 2), leftSide(1, 2) + rightSide(1, 2), leftSide(2, 2) + rightSide(2, 2));
416  }
417 
422  inline Matrix3& operator+=(const Matrix3& rightSide)
423  {
424  for (size_t index = 0; index < 9; ++index)
425  {
426  (*this)[index] += rightSide[index];
427  }
428  return *this;
429  }
430 
434  inline Matrix3 operator-(const Matrix3& rightSide) const
435  {
436  const Matrix3& leftSide(*this);
437  return Matrix3(
438  leftSide(0, 0) - rightSide(0, 0), leftSide(1, 0) - rightSide(1, 0), leftSide(2, 0) - rightSide(2, 0),
439  leftSide(0, 1) - rightSide(0, 1), leftSide(1, 1) - rightSide(1, 1), leftSide(2, 1) - rightSide(2, 1),
440  leftSide(0, 2) - rightSide(0, 2), leftSide(1, 2) - rightSide(1, 2), leftSide(2, 2) - rightSide(2, 2));
441  }
442 
446  inline Matrix3& operator-=(const Matrix3& rightSide)
447  {
448  for (size_t index = 0; index < 9; ++index)
449  {
450  (*this)[index] -= rightSide[index];
451  }
452  return *this;
453  }
454 
455 
459  inline Matrix3 operator*(const Matrix3& rightSide) const
460  {
461  Matrix3 result;
462  MatrixMultiply(&result, this, &rightSide);
463  return result;
464  }
465 
469  inline Matrix3 operator*=(const Matrix3& rightSide)
470  {
471  Matrix3 leftSide = *this;
472  MatrixMultiply(this, &leftSide, &rightSide);
473  return *this;
474  }
475 
479  inline Matrix3 GetTransposed(void) const
480  {
481  const Matrix3& self(*this);
482  return Matrix3(
483  self(0, 0), self(0, 1), self(0, 2),
484  self(1, 0), self(1, 1), self(1, 2),
485  self(2, 0), self(2, 1), self(2, 2));
486  }
487 
493  inline Matrix3 ComputeInverse(void) const
494  {
495  Matrix3 result;
496  MatrixComputeInverse(&result, this);
497  return result;
498  }
499 
504  inline Matrix3 FastInverse(void) const
505  {
506  Matrix3 result;
507  MatrixFastInverse(&result, this);
508  return result;
509  }
510 #endif
511  };
512 
516 
527  class Matrix4
528  {
529  public:
533  static Matrix4 Zero(void)
534  {
535  return Matrix4(
536  0.0f, 0.0f, 0.0f, 0.0f,
537  0.0f, 0.0f, 0.0f, 0.0f,
538  0.0f, 0.0f, 0.0f, 0.0f,
539  0.0f, 0.0f, 0.0f, 0.0f);
540  }
541 
546  static Matrix4 Identity(void)
547  {
548  return Matrix4(
549  1.0f, 0.0f, 0.0f, 0.0f,
550  0.0f, 1.0f, 0.0f, 0.0f,
551  0.0f, 0.0f, 1.0f, 0.0f,
552  0.0f, 0.0f, 0.0f, 1.0f);
553  }
554 
556  static Matrix4 Translation(const tbMath::Vector3& translation)
557  {
558  Matrix4 matrix(tbMath::kSkipInitialization);
559  tbMath::MatrixCreateTranslation(&matrix, &translation);
560  return matrix;
561  }
562 
563  static Matrix4 Translation(const float translationX, const float translationY, const float translationZ)
564  {
565  Matrix4 matrix(tbMath::kSkipInitialization);
566  tbMath::MatrixCreateTranslation(&matrix, translationX, translationY, translationZ);
567  return matrix;
568  }
569 
570  static Matrix4 Scale(const tbMath::Vector3& scale)
571  {
572  Matrix4 matrix(tbMath::kSkipInitialization);
573  tbMath::MatrixCreateScale(&matrix, &scale);
574  return matrix;
575  }
576 
577  static Matrix4 Scale(const float scaleX, const float scaleY, const float scaleZ)
578  {
579  Matrix4 matrix(tbMath::kSkipInitialization);
580  tbMath::MatrixCreateScale(&matrix, scaleX, scaleY, scaleZ);
581  return matrix;
582  }
583 
584  static Matrix4 RotationX(const Angle& rotation)
585  {
586  Matrix4 matrix(tbMath::kSkipInitialization);
587  tbMath::MatrixCreateRotationX(&matrix, rotation);
588  return matrix;
589  }
590 
591  static Matrix4 RotationY(const Angle& rotation)
592  {
593  Matrix4 matrix(tbMath::kSkipInitialization);
594  tbMath::MatrixCreateRotationY(&matrix, rotation);
595  return matrix;
596  }
597 
598  static Matrix4 RotationZ(const Angle& rotation)
599  {
600  Matrix4 matrix(tbMath::kSkipInitialization);
601  tbMath::MatrixCreateRotationZ(&matrix, rotation);
602  return matrix;
603  }
604 
605  static Matrix4 RotationA(const tbMath::Vector3& rotationAxis, const Angle& rotation)
606  {
607  Matrix4 matrix(tbMath::kSkipInitialization);
608  tbMath::MatrixCreateRotationA(&matrix, &rotationAxis, rotation);
609  return matrix;
610  }
611 
612  //Defined in tb_matrix_quaternion.h
613  static Matrix4 FromQuaternion(const tbMath::Unstable::Quaternion& quaternion, const tbMath::Vector3& translation);
615 
616  union
617  {
618  float mComponents[16];
619 
620 #if defined(tb_visual_cpp)
621 #pragma warning(push)
622 #pragma warning(disable: 4201)
623 #endif
624  struct {
625  float xx; float xy; float xz; float hx;
626  float yx; float yy; float yz; float hy;
627  float zx; float zy; float zz; float hz;
628  float tx; float ty; float tz; float ht;
629  };
630 #if defined(tb_visual_cpp)
631 #pragma warning(pop)
632 #endif
633  };
634 
638  inline Matrix4(void) :
639  mComponents{
640  1.0f, 0.0f, 0.0f, 0.0f,
641  0.0f, 1.0f, 0.0f, 0.0f,
642  0.0f, 0.0f, 1.0f, 0.0f,
643  0.0f, 0.0f, 0.0f, 1.0f}
644  {
645  }
646 
650  inline explicit Matrix4(
651  float f11, float f21, float f31, float f41,
652  float f12, float f22, float f32, float f42,
653  float f13, float f23, float f33, float f43,
654  float f14, float f24, float f34, float f44) :
655  mComponents{
656  f11, f21, f31, f41,
657  f12, f22, f32, f42,
658  f13, f23, f33, f43,
659  f14, f24, f34, f44}
660  {
661  }
662 
669  inline explicit Matrix4(
670  float f11, float f21, float f31, float f41,
671  float f12, float f22, float f32, float f42,
672  float f13, float f23, float f33, float f43,
673  float f14, float f24, float f34, float f44, const ColumnMajorMatrix& columnMajor) :
674  mComponents{
675  f11, f12, f13, f14,
676  f21, f22, f23, f24,
677  f31, f32, f33, f34,
678  f41, f42, f43, f44 }
679  {
680  tb_unused(columnMajor);
681  }
682 
688  inline explicit Matrix4(const float* const componentArray) :
689  mComponents{
690  componentArray[0], componentArray[1], componentArray[2], componentArray[3],
691  componentArray[4], componentArray[5], componentArray[6], componentArray[7],
692  componentArray[8], componentArray[9], componentArray[10], componentArray[11],
693  componentArray[12], componentArray[13], componentArray[14], componentArray[15] }
694  {
695  }
696 
704  inline explicit Matrix4(const float* const componentArray, const ColumnMajorMatrix& columnMajor) :
705  mComponents{
706  componentArray[0], componentArray[4], componentArray[8], componentArray[12],
707  componentArray[1], componentArray[5], componentArray[9], componentArray[13],
708  componentArray[2], componentArray[6], componentArray[10], componentArray[14],
709  componentArray[3], componentArray[7], componentArray[11], componentArray[15] }
710  {
711  tb_unused(columnMajor);
712  }
713 
720  inline explicit Matrix4(const SkipInitialization& fastAndStupid)
721  {
722  tb_unused(fastAndStupid);
723  }
724 
728  inline Matrix4(const Matrix4& other) :
729  mComponents{
730  other.mComponents[0], other.mComponents[1], other.mComponents[2], other.mComponents[3],
731  other.mComponents[4], other.mComponents[5], other.mComponents[6], other.mComponents[7],
732  other.mComponents[8], other.mComponents[9], other.mComponents[10], other.mComponents[11],
733  other.mComponents[12], other.mComponents[13], other.mComponents[14], other.mComponents[15]
734  }
735  {
736  }
737 
741  inline Matrix4& operator=(const Matrix4& other)
742  {
743  memcpy(mComponents, other.mComponents, sizeof(float) << 4); //Same as (sizeof(float) * 16)
744  return (*this);
745  }
746 
757  inline bool operator==(const Matrix4& other) const
758  {
759  for (size_t index(0); index < 16; ++index)
760  {
761  if (false == IsEqual(mComponents[index], other[index]))
762  {
763  return false;
764  }
765  }
766 
767  return true;
768  }
769 
775  inline bool operator!=(const Matrix4& other) const
776  {
777  for (size_t index(0); index < 16; ++index)
778  {
779  if (false == IsEqual(mComponents[index], other[index]))
780  {
781  return true;
782  }
783  }
784 
785  return false;
786  }
787 
792  inline const float& operator[](const size_t& index) const { return mComponents[index]; }
793 
799  inline float& operator[](const size_t& index) { return mComponents[index]; }
800 
805  inline const float& operator()(const size_t& column, const size_t& row) const { return mComponents[column + (row << 2)]; }
806 
812  inline float& operator()(const size_t& column, const size_t& row) { return mComponents[column + (row << 2)]; }
813 
818  inline const float& operator()(int column, int row) const { return mComponents[column + (row << 2)]; }
819 
825  inline float& operator()(int column, int row) { return mComponents[column + (row << 2)]; }
826 
827 
835  inline explicit operator float*(void) { return mComponents; }
836 
840  inline explicit operator const float*(void) const { return mComponents; }
841 
849  inline Vector3 GetBasis(const size_t& basisIndex) const { return Vector3(&mComponents[basisIndex<<2]); }
850 
857  inline void SetBasis(const size_t& basisIndex, const Vector3 &basis) { *((Vector3*)&mComponents[basisIndex<<2]) = basis; }
858 
867  inline void SetBasis(const size_t& basisIndex, float basisX, float basisY, float basisZ)
868  {
869  mComponents[(basisIndex<<2) + 0] = basisX;
870  mComponents[(basisIndex<<2) + 1] = basisY;
871  mComponents[(basisIndex<<2) + 2] = basisZ;
872  }
873 
879  inline Vector3 GetPosition(void) const
880  {
881  return Vector3(&mComponents[12]);
882  }
883 
888  inline void SetPosition(const Vector3& position)
889  {
890  (*this)(0, 3) = position.x;
891  (*this)(1, 3) = position.y;
892  (*this)(2, 3) = position.z;
893  }
894 
899  inline void SetPosition(const float x, const float y, const float z)
900  {
901  (*this)(0, 3) = x;
902  (*this)(1, 3) = y;
903  (*this)(2, 3) = z;
904  }
905 
906 #if defined(tb_with_math_operators)
907  inline Matrix4 operator+(const Matrix4& rightSide) const
911  {
912  const Matrix4& leftSide(*this);
913  return Matrix4(
914  leftSide(0, 0) + rightSide(0, 0), leftSide(1, 0) + rightSide(1, 0), leftSide(2, 0) + rightSide(2, 0), leftSide(3, 0) + rightSide(3, 0),
915  leftSide(0, 1) + rightSide(0, 1), leftSide(1, 1) + rightSide(1, 1), leftSide(2, 1) + rightSide(2, 1), leftSide(3, 1) + rightSide(3, 1),
916  leftSide(0, 2) + rightSide(0, 2), leftSide(1, 2) + rightSide(1, 2), leftSide(2, 2) + rightSide(2, 2), leftSide(3, 2) + rightSide(3, 2),
917  leftSide(0, 3) + rightSide(0, 3), leftSide(1, 3) + rightSide(1, 3), leftSide(2, 3) + rightSide(2, 3), leftSide(3, 3) + rightSide(3, 3));
918  }
919 
924  inline Matrix4& operator+=(const Matrix4& rightSide)
925  {
926  for (size_t index = 0; index < 16; ++index)
927  {
928  (*this)[index] += rightSide[index];
929  }
930  return *this;
931  }
932 
936  inline Matrix4 operator-(const Matrix4& rightSide) const
937  {
938  const Matrix4& leftSide(*this);
939  return Matrix4(
940  leftSide(0, 0) - rightSide(0, 0), leftSide(1, 0) - rightSide(1, 0), leftSide(2, 0) - rightSide(2, 0), leftSide(3, 0) - rightSide(3, 0),
941  leftSide(0, 1) - rightSide(0, 1), leftSide(1, 1) - rightSide(1, 1), leftSide(2, 1) - rightSide(2, 1), leftSide(3, 1) - rightSide(3, 1),
942  leftSide(0, 2) - rightSide(0, 2), leftSide(1, 2) - rightSide(1, 2), leftSide(2, 2) - rightSide(2, 2), leftSide(3, 2) - rightSide(3, 2),
943  leftSide(0, 3) - rightSide(0, 3), leftSide(1, 3) - rightSide(1, 3), leftSide(2, 3) - rightSide(2, 3), leftSide(3, 3) - rightSide(3, 3));
944  }
945 
949  inline Matrix4& operator-=(const Matrix4& rightSide)
950  {
951  for (size_t index = 0; index < 16; ++index)
952  {
953  (*this)[index] -= rightSide[index];
954  }
955  return *this;
956  }
957 
961  inline Matrix4 operator*(const Matrix4& rightSide) const
962  {
963  Matrix4 result;
964  MatrixMultiply(&result, this, &rightSide);
965  return result;
966  }
967 
971  inline Matrix4 operator*=(const Matrix4& rightSide)
972  {
973  Matrix4 leftSide = *this;
974  MatrixMultiply(this, &leftSide, &rightSide);
975  return *this;
976  }
977 
981  inline Matrix4 GetTransposed(void) const
982  {
983  Matrix4 temp;
984  const Matrix4& self(*this);
985  temp(0, 0) = self(0, 0); temp(0, 1) = self(1, 0); temp(0, 2) = self(2, 0); temp(0, 3) = self(3, 0);
986  temp(1, 0) = self(0, 1); temp(1, 1) = self(1, 1); temp(1, 2) = self(2, 1); temp(1, 3) = self(3, 1);
987  temp(2, 0) = self(0, 2); temp(2, 1) = self(1, 2); temp(2, 2) = self(2, 2); temp(2, 3) = self(3, 2);
988  temp(3, 0) = self(0, 3); temp(3, 1) = self(1, 3); temp(3, 2) = self(2, 3); temp(3, 3) = self(3, 3);
989  return temp;
990  }
991 
997  inline Matrix4 ComputeInverse(void) const
998  {
999  Matrix4 result;
1000  MatrixComputeInverse(&result, this);
1001  return result;
1002  }
1003 
1010  inline Matrix4 FastInverse(void) const
1011  {
1012  Matrix4 result;
1013  MatrixFastInverse(&result, this);
1014  return result;
1015  }
1016 
1021  inline Vector3 TransformCoordinate(const Vector3& inputVector) const
1022  {
1023  Vector3 result;
1024  Vector3TransformCoordinate(&result, &inputVector, this);
1025  return result;
1026  }
1027 
1032  inline Vector3 TransformNormal(const Vector3& inputVector) const
1033  {
1034  Vector3 result;
1035  Vector3TransformNormal(&result, &inputVector, this);
1036  return result;
1037  }
1038 
1042  inline Vector4 Transform(const Vector4& inputVector) const
1043  {
1044  Vector4 result;
1045  Vector4MatrixMultiply(&result, &inputVector, this);
1046  return result;
1047  }
1048 
1049 #endif /* tb_with_math_operators */
1050  };
1051 
1052 #if defined(tb_with_math_operators)
1053 
1057  inline Matrix3 operator*(const float leftSide, const Matrix3& rightSide)
1058  {
1059  tbMath::Matrix3 result;
1060  MatrixMultiply(&result, &rightSide, leftSide);
1061  return result;
1062  }
1063 
1067  inline Matrix3 operator*(const Matrix3& leftSide, const float rightSide)
1068  {
1069  tbMath::Matrix3 result;
1070  MatrixMultiply(&result, &leftSide, rightSide);
1071  return result;
1072  }
1073 
1077  inline Matrix4 operator*(const float leftSide, const Matrix4& rightSide)
1078  {
1079  tbMath::Matrix4 result;
1080  MatrixMultiply(&result, &rightSide, leftSide);
1081  return result;
1082  }
1083 
1087  inline Matrix4 operator*(const Matrix4& leftSide, const float rightSide)
1088  {
1089  tbMath::Matrix4 result;
1090  MatrixMultiply(&result, &leftSide, rightSide);
1091  return result;
1092  }
1093 
1098  inline Vector3 operator*(const Vector3& leftSide, const Matrix3& rightSide)
1099  {
1100  tbMath::Vector3 result;
1101  Vector3MatrixMultiply(&result, &leftSide, &rightSide);
1102  return result;
1103  }
1104 
1109  inline Vector3 operator*(const Matrix3& leftSide, const Vector3& rightSide)
1110  {
1111  tbMath::Vector3 result;
1112  MatrixVector3Multiply(&result, &leftSide, &rightSide);
1113  return result;
1114  }
1115 
1120  inline Vector4 operator*(const Vector4& leftSide, const Matrix4& rightSide)
1121  {
1122  tbMath::Vector4 result;
1123  Vector4MatrixMultiply(&result, &leftSide, &rightSide);
1124  return result;
1125  }
1126 
1131  inline Vector4 operator*(const Matrix4& leftSide, const Vector4& rightSide)
1132  {
1133  tbMath::Vector4 result;
1134  MatrixVector4Multiply(&result, &leftSide, &rightSide);
1135  return result;
1136  }
1137 
1138 #endif /* tb_with_math_operators */
1139 
1143 
1149 
1151  {
1152  *result = Matrix3::Identity();
1153  return result;
1154  }
1155 
1160  {
1161  *result = Matrix4::Identity();
1162  return result;
1163  }
1164 
1174  inline Matrix4* MatrixCreateLookAt(Matrix4* result, const Vector3& eyePosition, const Vector3& targetPosition, const Vector3& unitUp)
1175  {
1176  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter; Expected result to be valid pointer.");
1177 
1178  Vector3 right, finalUp, forward;
1179  Vector3Subtract(&forward, &eyePosition, &targetPosition);
1180  Vector3Normalize(&forward, &forward);
1181 
1182 #if defined(tb_debug_build) //Going to refer to these as the Math Idiot proofing tests.
1183  tb_error_if(eyePosition == targetPosition, "tbExternalError: Invalid parameter; This would result in looking directly at eye position.");
1184  tb_error_if(fabsf(Vector3Magnitude(&unitUp) - 1.0f) > 0.00001f, "tbExternalError: Invalid unitUp, this is not a unit length vector.");
1185  tb_error_if(fabsf(Vector3DotProduct(&forward, &unitUp)) > 0.9999f, "tbExternalError: Invalid looking direction, parallel to unitUp.");
1186 #endif
1187 
1188  Vector3CrossProduct(&right, &unitUp, &forward);
1189  Vector3Normalize(&right, &right);
1190 
1191  Vector3CrossProduct(&finalUp, &forward, &right);
1192 
1193  //result->SetBasis(0, right);
1194  //result->SetBasis(1, finalUp);
1195  //result->SetBasis(2, forward);
1196  result->SetBasis(0, right.x, finalUp.x, forward.x);
1197  result->SetBasis(1, right.y, finalUp.y, forward.y);
1198  result->SetBasis(2, right.z, finalUp.z, forward.z);
1199 
1200  (*result)(0, 3) = -(eyePosition.x * (*result)(0, 0) + eyePosition.y * (*result)(0, 1) + eyePosition.z * (*result)(0, 2));
1201  (*result)(1, 3) = -(eyePosition.x * (*result)(1, 0) + eyePosition.y * (*result)(1, 1) + eyePosition.z * (*result)(1, 2));
1202  (*result)(2, 3) = -(eyePosition.x * (*result)(2, 0) + eyePosition.y * (*result)(2, 1) + eyePosition.z * (*result)(2, 2));
1203 
1204  return result;
1205  }
1206 
1213  inline Matrix4* MatrixCreateTranslation(Matrix4* result, const Vector3* translation)
1214  { //Changed September 19, 2010, changed back March 22nd, 2018, changed again (to bottom row) May 9th 2018
1215  MatrixCreateIdentity(result);
1216  (*result)(0, 3) = translation->x;
1217  (*result)(1, 3) = translation->y;
1218  (*result)(2, 3) = translation->z;
1219  return result;
1220  }
1221 
1231  inline Matrix4* MatrixCreateTranslation(Matrix4* result, const float translationX, const float translationY, const float translationZ)
1232  { //Changed September 19, 2010, changed back March 22nd, 2018, changed again (to bottom row) May 9th 2018
1233  MatrixCreateIdentity(result);
1234  (*result)(0, 3) = translationX;
1235  (*result)(1, 3) = translationY;
1236  (*result)(2, 3) = translationZ;
1237  return result;
1238  }
1239 
1247  inline Matrix3* MatrixCreateScale(Matrix3* result, const Vector3* scale)
1248  {
1249  memset(result->mComponents, 0, sizeof(float) * 9);
1250  (*result)(0, 0) = scale->x;
1251  (*result)(1, 1) = scale->y;
1252  (*result)(2, 2) = scale->z;
1253  return result;
1254  }
1255 
1259  inline Matrix4* MatrixCreateScale(Matrix4* result, const Vector3* scale)
1260  {
1261  memset(result->mComponents, 0, sizeof(float) << 4);
1262  (*result)(0, 0) = scale->x;
1263  (*result)(1, 1) = scale->y;
1264  (*result)(2, 2) = scale->z;
1265  (*result)(3, 3) = 1.0f;
1266  return result;
1267  }
1268 
1278  inline Matrix3* MatrixCreateScale(Matrix3* result, const float scaleX, const float scaleY, const float scaleZ)
1279  {
1280  memset(result->mComponents, 0, sizeof(float) * 9);
1281  (*result)(0, 0) = scaleX;
1282  (*result)(1, 1) = scaleY;
1283  (*result)(2, 2) = scaleZ;
1284  return result;
1285  }
1286 
1290  inline Matrix4* MatrixCreateScale(Matrix4* result, const float scaleX, const float scaleY, const float scaleZ)
1291  {
1292  memset(result->mComponents, 0, sizeof(float) << 4);
1293  (*result)(0, 0) = scaleX;
1294  (*result)(1, 1) = scaleY;
1295  (*result)(2, 2) = scaleZ;
1296  (*result)(3, 3) = 1.0f;
1297  return result;
1298  }
1299 
1307  inline Matrix3* MatrixCreateRotationX(Matrix3* result, const Angle rotation)
1308  {
1309  MatrixCreateIdentity(result);
1310  const float sinOfRotation = sinf(rotation.AsRadians());
1311  const float cosOfRotation = cosf(rotation.AsRadians());
1312  (*result)(1, 1) = cosOfRotation;
1313  (*result)(2, 1) = -sinOfRotation;
1314  (*result)(1, 2) = sinOfRotation;
1315  (*result)(2, 2) = cosOfRotation;
1316  return result;
1317  }
1318 
1322  inline Matrix4* MatrixCreateRotationX(Matrix4* result, const Angle rotation)
1323  {
1324  MatrixCreateIdentity(result);
1325  const float sinOfRotation = sinf(rotation.AsRadians());
1326  const float cosOfRotation = cosf(rotation.AsRadians());
1327  (*result)(1, 1) = cosOfRotation;
1328  (*result)(2, 1) = -sinOfRotation;
1329  (*result)(1, 2) = sinOfRotation;
1330  (*result)(2, 2) = cosOfRotation;
1331  return result;
1332  }
1333 
1341  inline Matrix3* MatrixCreateRotationY(Matrix3* result, const Angle rotation)
1342  {
1343  MatrixCreateIdentity(result);
1344  const float sinOfRotation = sinf(rotation.AsRadians());
1345  const float cosOfRotation = cosf(rotation.AsRadians());
1346  (*result)(0, 0) = cosOfRotation;
1347  (*result)(2, 0) = sinOfRotation;
1348  (*result)(0, 2) = -sinOfRotation;
1349  (*result)(2, 2) = cosOfRotation;
1350  return result;
1351  }
1352 
1356  inline Matrix4* MatrixCreateRotationY(Matrix4* result, const Angle rotation)
1357  {
1358  MatrixCreateIdentity(result);
1359  const float sinOfRotation = sinf(rotation.AsRadians());
1360  const float cosOfRotation = cosf(rotation.AsRadians());
1361  (*result)(0, 0) = cosOfRotation;
1362  (*result)(2, 0) = sinOfRotation;
1363  (*result)(0, 2) = -sinOfRotation;
1364  (*result)(2, 2) = cosOfRotation;
1365  return result;
1366  }
1367 
1375  inline Matrix3* MatrixCreateRotationZ(Matrix3* result, const Angle rotation)
1376  {
1377  MatrixCreateIdentity(result);
1378  const float sinOfRotation = sinf(rotation.AsRadians());
1379  const float cosOfRotation = cosf(rotation.AsRadians());
1380  (*result)(0, 0) = cosOfRotation;
1381  (*result)(1, 0) = -sinOfRotation;
1382  (*result)(0, 1) = sinOfRotation;
1383  (*result)(1, 1) = cosOfRotation;
1384  return result;
1385  }
1386 
1390  inline Matrix4* MatrixCreateRotationZ(Matrix4* result, const Angle rotation)
1391  {
1392  MatrixCreateIdentity(result);
1393  const float sinOfRotation = sinf(rotation.AsRadians());
1394  const float cosOfRotation = cosf(rotation.AsRadians());
1395  (*result)(0, 0) = cosOfRotation;
1396  (*result)(1, 0) = -sinOfRotation;
1397  (*result)(0, 1) = sinOfRotation;
1398  (*result)(1, 1) = cosOfRotation;
1399  return result;
1400  }
1401 
1410  inline Matrix3* MatrixCreateRotationA(Matrix3* result, const Vector3* rotationAxis, const Angle rotation)
1411  {
1412  const float s = sinf(rotation.AsRadians());
1413  const float c = cosf(rotation.AsRadians());
1414  const float t = 1.0f - c;
1415 
1416  const auto av = rotationAxis->GetNormalized();
1417  const auto tv = tbMath::Vector3(av * t);
1418  const auto sv = tbMath::Vector3(av * s);
1419 
1420  (*result)(0, 0) = c + tv.x * av.x;
1421  (*result)(0, 1) = tv.x * av.y + sv.z;
1422  (*result)(0, 2) = tv.x * av.z - sv.y;
1423 
1424  (*result)(1, 0) = tv.y * av.x - sv.z;
1425  (*result)(1, 1) = c + tv.y * av.y;
1426  (*result)(1, 2) = tv.y * av.z + sv.x;
1427 
1428  (*result)(2, 0) = tv.z * av.x + sv.y;
1429  (*result)(2, 1) = tv.z * av.y - sv.x;
1430  (*result)(2, 2) = c + tv.z * av.z;
1431 
1432  return result;
1433  }
1434 
1438  inline Matrix4* MatrixCreateRotationA(Matrix4* result, const Vector3* rotationAxis, const Angle rotation)
1439  {
1440  const float s = sinf(rotation.AsRadians());
1441  const float c = cosf(rotation.AsRadians());
1442  const float t = 1.0f - c;
1443 
1444  const auto av = rotationAxis->GetNormalized();
1445  const auto tv = tbMath::Vector3(av * t);
1446  const auto sv = tbMath::Vector3(av * s);
1447 
1448  (*result)(0, 0) = c + tv.x * av.x;
1449  (*result)(0, 1) = tv.x * av.y + sv.z;
1450  (*result)(0, 2) = tv.x * av.z - sv.y;
1451  (*result)(0, 3) = 0.0f;
1452 
1453  (*result)(1, 0) = tv.y * av.x - sv.z;
1454  (*result)(1, 1) = c + tv.y * av.y;
1455  (*result)(1, 2) = tv.y * av.z + sv.x;
1456  (*result)(1, 3) = 0.0f;
1457 
1458  (*result)(2, 0) = tv.z * av.x + sv.y;
1459  (*result)(2, 1) = tv.z * av.y - sv.x;
1460  (*result)(2, 2) = c + tv.z * av.z;
1461  (*result)(2, 3) = 0.0f;
1462 
1463  (*result)(3, 0) = 0.0f;
1464  (*result)(3, 1) = 0.0f;
1465  (*result)(3, 2) = 0.0f;
1466  (*result)(3, 3) = 1.0f;
1467 
1468  return result;
1469  }
1470 
1483  inline Matrix4* MatrixCreatePerspectiveRH(Matrix4* result, const float fieldOfView, const float aspectRatio,
1484  const float nearPlane, const float farPlane)
1485  {
1486  memset(result->mComponents, 0, sizeof(float) << 4);
1487 
1488  //From GLM, https://pastebin.com/Gen40yLY except flipped for row-major.
1489  //Remember that GLM accesses Y, X (row, column)...
1490  const float t = tan(fieldOfView / 2.0f);
1491  (*result)(0, 0) = 1.0f / (aspectRatio * t);
1492  (*result)(1, 1) = 1.0f / t;
1493  (*result)(2, 2) = -(farPlane + nearPlane) / (farPlane - nearPlane);
1494  (*result)(3, 2) = -1.0f;
1495  (*result)(2, 3) = -(2.0f * farPlane * nearPlane) / (farPlane - nearPlane);
1496 
1497  return result;
1498  }
1499 
1512  inline Matrix4* MatrixCreatePerspectiveLH(Matrix4* result, const float fieldOfView, const float aspectRatio,
1513  const float nearPlane, const float farPlane)
1514  {
1515  memset(result->mComponents, 0, sizeof(float) << 4);
1516 
1517  //From GLM, https://pastebin.com/Gen40yLY except flipped for row-major.
1518  //Remember that GLM accesses Y, X (row, column)...
1519  const float t = tan(fieldOfView / 2.0f);
1520  (*result)(0, 0) = 1.0f / (aspectRatio * t);
1521  (*result)(1, 1) = 1.0f / t;
1522  (*result)(2, 2) = (farPlane + nearPlane) / (farPlane - nearPlane);
1523  (*result)(3, 2) = 1.0f;
1524  (*result)(2, 3) = -(2.0f * farPlane * nearPlane) / (farPlane - nearPlane);
1525 
1526  return result;
1527  }
1528 
1544  inline Matrix4* MatrixCreateOrthoRH(Matrix4* result, const float left, const float right,
1545  const float top, const float bottom, const float nearPlane, const float farPlane)
1546  {
1547  tbMath::Matrix4& output(*result);
1548  memset(result->mComponents, 0, sizeof(float) << 4);
1549 
1550  output(0, 0) = 2.0f / (right - left);
1551  output(1, 1) = 2.0f / (top - bottom);
1552  output(2, 2) = -2.0f / (farPlane - nearPlane);
1553  output(3, 3) = 1.0f;
1554  output(0, 3) = -(right + left) / (right - left);
1555  output(1, 3) = -(top + bottom) / (top - bottom);
1556  output(2, 3) = -((farPlane + nearPlane) / (farPlane - nearPlane));
1557 
1558  return result;
1559  }
1560 
1576  inline Matrix4* MatrixCreateOrthoLH(Matrix4* result, const float left, const float right,
1577  const float top, const float bottom, const float nearPlane, const float farPlane)
1578  {
1579  tbMath::Matrix4& output(*result);
1580  memset(result->mComponents, 0, sizeof(float) << 4);
1581 
1582  output(0, 0) = 2.0f / (right - left);
1583  output(1, 1) = 2.0f / (top - bottom);
1584  output(2, 2) = 2.0f / (farPlane - nearPlane);
1585  output(3, 3) = 1.0f;
1586  output(0, 3) = -(right + left) / (right - left);
1587  output(1, 3) = -(top + bottom) / (top - bottom);
1588  output(2, 3) = -(farPlane + nearPlane) / (farPlane - nearPlane);
1589 
1590  return result;
1591  }
1592 
1600  inline Matrix3* MatrixAdd(Matrix3* result, const Matrix3* leftSide, const Matrix3* rightSide)
1601  {
1602  float *r = result->mComponents;
1603  const float *m1 = leftSide->mComponents;
1604  const float *m2 = rightSide->mComponents;
1605 
1606  r[0] = m1[0] + m2[0]; r[1] = m1[1] + m2[1]; r[2] = m1[2] + m2[2];
1607  r[3] = m1[3] + m2[3]; r[4] = m1[4] + m2[4]; r[5] = m1[5] + m2[5];
1608  r[6] = m1[6] + m2[6]; r[7] = m1[7] + m2[7]; r[8] = m1[8] + m2[8];
1609  return result;
1610  }
1611 
1615  inline Matrix4* MatrixAdd(Matrix4* result, const Matrix4* leftSide, const Matrix4* rightSide)
1616  {
1617  float *r = result->mComponents;
1618  const float *m1 = leftSide->mComponents;
1619  const float *m2 = rightSide->mComponents;
1620 
1621  r[0] = m1[0] + m2[0]; r[1] = m1[1] + m2[1]; r[2] = m1[2] + m2[2]; r[3] = m1[3] + m2[3];
1622  r[4] = m1[4] + m2[4]; r[5] = m1[5] + m2[5]; r[6] = m1[6] + m2[6]; r[7] = m1[7] + m2[7];
1623  r[8] = m1[8] + m2[8]; r[9] = m1[9] + m2[9]; r[10] = m1[10] + m2[10]; r[11] = m1[11] + m2[11];
1624  r[12] = m1[12] + m2[12]; r[13] = m1[13] + m2[13]; r[14] = m1[14] + m2[14]; r[15] = m1[15] + m2[15];
1625  return result;
1626  }
1627 
1635 
1636  inline Matrix3* MatrixSubtract(Matrix3* result, const Matrix3* leftSide, const Matrix3* rightSide)
1637  {
1638  float *r = result->mComponents;
1639  const float *m1 = leftSide->mComponents;
1640  const float *m2 = rightSide->mComponents;
1641 
1642  r[0] = m1[0] - m2[0]; r[1] = m1[1] - m2[1]; r[2] = m1[2] - m2[2];
1643  r[3] = m1[3] - m2[3]; r[4] = m1[4] - m2[4]; r[5] = m1[5] - m2[5];
1644  r[6] = m1[6] - m2[6]; r[7] = m1[7] - m2[7]; r[8] = m1[8] - m2[8];
1645  return result;
1646  }
1647 
1651  inline Matrix4* MatrixSubtract(Matrix4* result, const Matrix4* leftSide, const Matrix4* rightSide)
1652  {
1653  float *r = result->mComponents;
1654  const float *m1 = leftSide->mComponents;
1655  const float *m2 = rightSide->mComponents;
1656 
1657  r[0] = m1[0] - m2[0]; r[1] = m1[1] - m2[1]; r[2] = m1[2] - m2[2]; r[3] = m1[3] - m2[3];
1658  r[4] = m1[4] - m2[4]; r[5] = m1[5] - m2[5]; r[6] = m1[6] - m2[6]; r[7] = m1[7] - m2[7];
1659  r[8] = m1[8] - m2[8]; r[9] = m1[9] - m2[9]; r[10] = m1[10] - m2[10]; r[11] = m1[11] - m2[11];
1660  r[12] = m1[12] - m2[12]; r[13] = m1[13] - m2[13]; r[14] = m1[14] - m2[14]; r[15] = m1[15] - m2[15];
1661  return result;
1662  }
1663 
1670  inline Matrix3* MatrixTranspose(Matrix3* result, const Matrix3* input)
1671  {
1672  tb_error_if(result == input, "tbExternalError: Invalid parameter; expected result to be different than input");
1673 
1674  Matrix3& a(*result);
1675  const Matrix3& b(*input);
1676  a(0, 0) = b(0, 0); a(0, 1) = b(1, 0); a(0, 2) = b(2, 0);
1677  a(1, 0) = b(0, 1); a(1, 1) = b(1, 1); a(1, 2) = b(2, 1);
1678  a(2, 0) = b(0, 2); a(2, 1) = b(1, 2); a(2, 2) = b(2, 2);
1679  return result;
1680  }
1681 
1688  inline Matrix4* MatrixTranspose(Matrix4* result, const Matrix4* input)
1689  {
1690  tb_error_if(result == input, "tbExternalError: Invalid parameter; expected result to be different than input");
1691 
1692  Matrix4& a(*result);
1693  const Matrix4& b(*input);
1694  a(0, 0) = b(0, 0); a(0, 1) = b(1, 0); a(0, 2) = b(2, 0); a(0, 3) = b(3, 0);
1695  a(1, 0) = b(0, 1); a(1, 1) = b(1, 1); a(1, 2) = b(2, 1); a(1, 3) = b(3, 1);
1696  a(2, 0) = b(0, 2); a(2, 1) = b(1, 2); a(2, 2) = b(2, 2); a(2, 3) = b(3, 2);
1697  a(3, 0) = b(0, 3); a(3, 1) = b(1, 3); a(3, 2) = b(2, 3); a(3, 3) = b(3, 3);
1698  return result;
1699  }
1700 
1711  inline Matrix3* MatrixMultiply(Matrix3* result, const Matrix3* leftSide, const Matrix3* rightSide)
1712  {
1713  tb_error_if(result == leftSide || result == rightSide, "tbExternalError: Invalid parameter; expected result to be different than leftSide and rightSide");
1714 
1715  const tbMath::Matrix3& a = *leftSide;
1716  const tbMath::Matrix3& b = *rightSide;
1717 
1718  (*result)(0, 0) = a(0, 0) * b(0, 0) + a(1, 0) * b(0, 1) + a(2, 0) * b(0, 2);
1719  (*result)(1, 0) = a(0, 0) * b(1, 0) + a(1, 0) * b(1, 1) + a(2, 0) * b(1, 2);
1720  (*result)(2, 0) = a(0, 0) * b(2, 0) + a(1, 0) * b(2, 1) + a(2, 0) * b(2, 2);
1721  (*result)(0, 1) = a(0, 1) * b(0, 0) + a(1, 1) * b(0, 1) + a(2, 1) * b(0, 2);
1722  (*result)(1, 1) = a(0, 1) * b(1, 0) + a(1, 1) * b(1, 1) + a(2, 1) * b(1, 2);
1723  (*result)(2, 1) = a(0, 1) * b(2, 0) + a(1, 1) * b(2, 1) + a(2, 1) * b(2, 2);
1724  (*result)(0, 2) = a(0, 2) * b(0, 0) + a(1, 2) * b(0, 1) + a(2, 2) * b(0, 2);
1725  (*result)(1, 2) = a(0, 2) * b(1, 0) + a(1, 2) * b(1, 1) + a(2, 2) * b(1, 2);
1726  (*result)(2, 2) = a(0, 2) * b(2, 0) + a(1, 2) * b(2, 1) + a(2, 2) * b(2, 2);
1727 
1728  return result;
1729  }
1730 
1734  inline Matrix4* MatrixMultiply(Matrix4* result, const Matrix4* leftSide, const Matrix4* rightSide)
1735  {
1736  tb_error_if(result == leftSide || result == rightSide, "tbExternalError: Invalid parameter; expected result to be different than leftSide and rightSide");
1737 
1738  const tbMath::Matrix4& a = *leftSide;
1739  const tbMath::Matrix4& b = *rightSide;
1740 
1741  (*result)(0, 0) = a(0, 0) * b(0, 0) + a(1, 0) * b(0, 1) + a(2, 0) * b(0, 2) + a(3, 0) * b(0, 3);
1742  (*result)(1, 0) = a(0, 0) * b(1, 0) + a(1, 0) * b(1, 1) + a(2, 0) * b(1, 2) + a(3, 0) * b(1, 3);
1743  (*result)(2, 0) = a(0, 0) * b(2, 0) + a(1, 0) * b(2, 1) + a(2, 0) * b(2, 2) + a(3, 0) * b(2, 3);
1744  (*result)(3, 0) = a(0, 0) * b(3, 0) + a(1, 0) * b(3, 1) + a(2, 0) * b(3, 2) + a(3, 0) * b(3, 3);
1745  (*result)(0, 1) = a(0, 1) * b(0, 0) + a(1, 1) * b(0, 1) + a(2, 1) * b(0, 2) + a(3, 1) * b(0, 3);
1746  (*result)(1, 1) = a(0, 1) * b(1, 0) + a(1, 1) * b(1, 1) + a(2, 1) * b(1, 2) + a(3, 1) * b(1, 3);
1747  (*result)(2, 1) = a(0, 1) * b(2, 0) + a(1, 1) * b(2, 1) + a(2, 1) * b(2, 2) + a(3, 1) * b(2, 3);
1748  (*result)(3, 1) = a(0, 1) * b(3, 0) + a(1, 1) * b(3, 1) + a(2, 1) * b(3, 2) + a(3, 1) * b(3, 3);
1749  (*result)(0, 2) = a(0, 2) * b(0, 0) + a(1, 2) * b(0, 1) + a(2, 2) * b(0, 2) + a(3, 2) * b(0, 3);
1750  (*result)(1, 2) = a(0, 2) * b(1, 0) + a(1, 2) * b(1, 1) + a(2, 2) * b(1, 2) + a(3, 2) * b(1, 3);
1751  (*result)(2, 2) = a(0, 2) * b(2, 0) + a(1, 2) * b(2, 1) + a(2, 2) * b(2, 2) + a(3, 2) * b(2, 3);
1752  (*result)(3, 2) = a(0, 2) * b(3, 0) + a(1, 2) * b(3, 1) + a(2, 2) * b(3, 2) + a(3, 2) * b(3, 3);
1753  (*result)(0, 3) = a(0, 3) * b(0, 0) + a(1, 3) * b(0, 1) + a(2, 3) * b(0, 2) + a(3, 3) * b(0, 3);
1754  (*result)(1, 3) = a(0, 3) * b(1, 0) + a(1, 3) * b(1, 1) + a(2, 3) * b(1, 2) + a(3, 3) * b(1, 3);
1755  (*result)(2, 3) = a(0, 3) * b(2, 0) + a(1, 3) * b(2, 1) + a(2, 3) * b(2, 2) + a(3, 3) * b(2, 3);
1756  (*result)(3, 3) = a(0, 3) * b(3, 0) + a(1, 3) * b(3, 1) + a(2, 3) * b(3, 2) + a(3, 3) * b(3, 3);
1757 
1758  return result;
1759  }
1760 
1770  inline Matrix3* MatrixMultiply(Matrix3* result, const Matrix3* input, const float scalar)
1771  {
1772  float* resultComponents = result->mComponents;
1773  const float* inputComponents = input->mComponents;
1774  for (size_t index = 0; index < 9; ++index)
1775  {
1776  resultComponents[index] = inputComponents[index] * scalar;
1777  }
1778  return result;
1779  }
1780 
1790  inline Matrix4* MatrixMultiply(Matrix4* result, const Matrix4* input, const float scalar)
1791  {
1792  float* resultComponents = result->mComponents;
1793  const float* inputComponents = input->mComponents;
1794  for (size_t index = 0; index < 16; ++index)
1795  {
1796  resultComponents[index] = inputComponents[index] * scalar;
1797  }
1798  return result;
1799  }
1800 
1810  //inline Vector3* Vector3MatrixMultiply(Vector3* result, const Vector3* inputVector, const Matrix3* inputMatrix)
1811  //{
1812  // tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
1813  // result->x = (inputVector->x * inputMatrix->m_f11) + (inputVector->y * inputMatrix->m_f12) + (inputVector->z * inputMatrix->m_f13);
1814  // result->y = (inputVector->x * inputMatrix->m_f21) + (inputVector->y * inputMatrix->m_f22) + (inputVector->z * inputMatrix->m_f23);
1815  // result->z = (inputVector->x * inputMatrix->m_f31) + (inputVector->y * inputMatrix->m_f32) + (inputVector->z * inputMatrix->m_f33);
1816  // return result;
1817  //}
1818 
1819 
1820 
1821 
1833  inline Vector3* MatrixVector3Multiply(Vector3* result, const Matrix3* inputMatrix, const Vector3* inputVector)
1834  {
1835  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
1836  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(1, 0)) + (inputVector->z * (*inputMatrix)(2, 0));
1837  result->y = (inputVector->x * (*inputMatrix)(0, 1)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(2, 1));
1838  result->z = (inputVector->x * (*inputMatrix)(0, 2)) + (inputVector->y * (*inputMatrix)(1, 2)) + (inputVector->z * (*inputMatrix)(2, 2));
1839  return result;
1840  }
1841 
1853  inline Vector3* Vector3MatrixMultiply(Vector3* result, const Vector3* inputVector, const Matrix3* inputMatrix)
1854  {
1855  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
1856  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(0, 1)) + (inputVector->z * (*inputMatrix)(0, 2));
1857  result->y = (inputVector->x * (*inputMatrix)(1, 0)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(1, 2));
1858  result->z = (inputVector->x * (*inputMatrix)(2, 0)) + (inputVector->y * (*inputMatrix)(2, 1)) + (inputVector->z * (*inputMatrix)(2, 2));
1859  return result;
1860  }
1861 
1873  inline Vector4* MatrixVector4Multiply(Vector4* result, const Matrix4* inputMatrix, const Vector4* inputVector)
1874  {
1875  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
1876  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(1, 0)) + (inputVector->z * (*inputMatrix)(2, 0)) + (inputVector->w * (*inputMatrix)(3, 0));
1877  result->y = (inputVector->x * (*inputMatrix)(0, 1)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(2, 1)) + (inputVector->w * (*inputMatrix)(3, 1));
1878  result->z = (inputVector->x * (*inputMatrix)(0, 2)) + (inputVector->y * (*inputMatrix)(1, 2)) + (inputVector->z * (*inputMatrix)(2, 2)) + (inputVector->w * (*inputMatrix)(3, 2));
1879  result->w = (inputVector->x * (*inputMatrix)(0, 3)) + (inputVector->y * (*inputMatrix)(1, 3)) + (inputVector->z * (*inputMatrix)(2, 3)) + (inputVector->w * (*inputMatrix)(3, 3));
1880  return result;
1881  }
1882 
1894  inline Vector4* Vector4MatrixMultiply(Vector4* result, const Vector4* inputVector, const Matrix4* inputMatrix)
1895  {
1896  tb_error_if(result == inputVector , "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
1897  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(0, 1)) + (inputVector->z * (*inputMatrix)(0, 2)) + (inputVector->w * (*inputMatrix)(0, 3));
1898  result->y = (inputVector->x * (*inputMatrix)(1, 0)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(1, 2)) + (inputVector->w * (*inputMatrix)(1, 3));
1899  result->z = (inputVector->x * (*inputMatrix)(2, 0)) + (inputVector->y * (*inputMatrix)(2, 1)) + (inputVector->z * (*inputMatrix)(2, 2)) + (inputVector->w * (*inputMatrix)(2, 3));
1900  result->w = (inputVector->x * (*inputMatrix)(3, 0)) + (inputVector->y * (*inputMatrix)(3, 1)) + (inputVector->z * (*inputMatrix)(3, 2)) + (inputVector->w * (*inputMatrix)(3, 3));
1901  return result;
1902  }
1903 
1914  inline Vector3* Vector3TransformCoordinate(Vector3* result, const Vector3* inputVector, const Matrix4* inputMatrix)
1915  {
1916  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector");
1917 
1918  const Matrix4& matrix(*inputMatrix);
1919  result->x = (inputVector->x * matrix(0, 0)) + (inputVector->y * matrix(0, 1)) + (inputVector->z * matrix(0, 2)) + matrix(0, 3);
1920  result->y = (inputVector->x * matrix(1, 0)) + (inputVector->y * matrix(1, 1)) + (inputVector->z * matrix(1, 2)) + matrix(1, 3);
1921  result->z = (inputVector->x * matrix(2, 0)) + (inputVector->y * matrix(2, 1)) + (inputVector->z * matrix(2, 2)) + matrix(2, 3);
1922  return result;
1923  }
1924 
1936  inline Vector3* Vector3TransformNormal(Vector3* result, const Vector3* inputVector, const Matrix4* inputMatrix)
1937  {
1938  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector");
1939 
1940  const Matrix4& matrix(*inputMatrix);
1941  result->x = (inputVector->x * matrix(0, 0)) + (inputVector->y * matrix(0, 1)) + (inputVector->z * matrix(0, 2));
1942  result->y = (inputVector->x * matrix(1, 0)) + (inputVector->y * matrix(1, 1)) + (inputVector->z * matrix(1, 2));
1943  result->z = (inputVector->x * matrix(2, 0)) + (inputVector->y * matrix(2, 1)) + (inputVector->z * matrix(2, 2));
1944  return result;
1945  }
1946 
1947  inline float Matrix2x2Determinant(const float f11, const float f12, const float f21, const float f22)
1948  {
1949  return f11 * f22 - f12 * f21;
1950  }
1951 
1956  inline float Matrix3x3Determinant(const float f11, const float f12, const float f13, const float f21, const float f22, const float f23, const float f31, const float f32, const float f33)
1957  {
1958  return f11 * (f22 * f33 - f32 * f23) - f12 * (f21 * f33 - f31 * f23) + f13 * (f21 * f32 - f31 * f22);
1959  }
1960 
1965  inline float MatrixDeterminant(const Matrix3* input)
1966  {
1967  const Matrix3& m(*input);
1968  return m(0, 0) * (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) - m(0, 1) * (m(1, 0) * m(2, 2) - m(2, 0) * m(1, 2)) + m(0, 2) * (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1));
1969  }
1970 
1975  inline float MatrixDeterminant(const Matrix4* input)
1976  {
1977  const Matrix4& m(*input);
1978  return (m(0, 0) * Matrix3x3Determinant(m(1, 1), m(2, 1), m(3, 1), m(1, 2), m(2, 2), m(3, 2), m(1, 3), m(2, 3), m(3, 3))) -
1979  (m(1, 0) * Matrix3x3Determinant(m(0, 1), m(2, 1), m(3, 1), m(0, 2), m(2, 2), m(3, 2), m(0, 3), m(2, 3), m(3, 3))) +
1980  (m(2, 0) * Matrix3x3Determinant(m(0, 1), m(1, 1), m(3, 1), m(0, 2), m(1, 2), m(3, 2), m(0, 3), m(1, 3), m(3, 3))) -
1981  (m(3, 0) * Matrix3x3Determinant(m(0, 1), m(1, 1), m(2, 1), m(0, 2), m(1, 2), m(2, 2), m(0, 3), m(1, 3), m(2, 3)));
1982  }
1983 
1987  inline Matrix3* MatrixComputeInverse(Matrix3* result, const Matrix3* input)
1988  {
1989  //tb_error("This is not yet implemented in full, use the FastInverse which requires certain ... matrices.");
1990 
1991  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
1992  const float determinant = MatrixDeterminant(input);
1993  if (true == IsZero(determinant))
1994  {
1995  *result = *input;
1996  return result;
1997  }
1998 
1999  const float inverseDeterminant = 1.0f / determinant;
2000 
2001  const Matrix3& m(*input);
2002  (*result)(0, 0) = Matrix2x2Determinant(m(1, 1), m(1, 2), m(2, 1), m(2, 2)) * inverseDeterminant;
2003  (*result)(1, 0) = -Matrix2x2Determinant(m(1, 0), m(1, 2), m(2, 0), m(2, 2)) * inverseDeterminant;
2004  (*result)(2, 0) = Matrix2x2Determinant(m(1, 0), m(1, 1), m(2, 0), m(2, 1)) * inverseDeterminant;
2005  (*result)(0, 1) = -Matrix2x2Determinant(m(0, 1), m(0, 2), m(2, 1), m(2, 2)) * inverseDeterminant;
2006  (*result)(1, 1) = Matrix2x2Determinant(m(0, 0), m(0, 2), m(2, 0), m(2, 2)) * inverseDeterminant;
2007  (*result)(2, 1) = -Matrix2x2Determinant(m(0, 0), m(0, 1), m(2, 0), m(2, 1)) * inverseDeterminant;
2008  (*result)(0, 2) = Matrix2x2Determinant(m(0, 1), m(0, 2), m(1, 1), m(1, 2)) * inverseDeterminant;
2009  (*result)(1, 2) = -Matrix2x2Determinant(m(0, 0), m(0, 2), m(1, 0), m(1, 2)) * inverseDeterminant;
2010  (*result)(2, 2) = Matrix2x2Determinant(m(0, 0), m(0, 1), m(1, 0), m(1, 1)) * inverseDeterminant;
2011  return result;
2012  }
2013 
2025  inline Matrix4* MatrixComputeInverse(Matrix4* result, const Matrix4* input)
2026  {
2027  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
2028  const float determinant = MatrixDeterminant(input);
2029  if (true == IsZero(determinant))
2030  {
2031  *result = *input;
2032  return result;
2033  }
2034 
2035  const float inverseDeterminant = 1.0f / determinant;
2036  const Matrix4& m(*input);
2037  (*result)(0, 0) = Matrix3x3Determinant (m(1,1), m(2,1), m(3,1), m(1,2), m(2,2), m(3,2), m(1,3), m(2,3), m(3,3)) * inverseDeterminant;
2038  (*result)(1, 0) = -Matrix3x3Determinant(m(1,0), m(2,0), m(3,0), m(1,2), m(2,2), m(3,2), m(1,3), m(2,3), m(3,3)) * inverseDeterminant;
2039  (*result)(2, 0) = Matrix3x3Determinant (m(1,0), m(2,0), m(3,0), m(1,1), m(2,1), m(3,1), m(1,3), m(2,3), m(3,3)) * inverseDeterminant;
2040  (*result)(3, 0) = -Matrix3x3Determinant(m(1,0), m(2,0), m(3,0), m(1,1), m(2,1), m(3,1), m(1,2), m(2,2), m(3,2)) * inverseDeterminant;
2041  (*result)(0, 1) = -Matrix3x3Determinant(m(0,1), m(2,1), m(3,1), m(0,2), m(2,2), m(3,2), m(0,3), m(2,3), m(3,3)) * inverseDeterminant;
2042  (*result)(1, 1) = Matrix3x3Determinant (m(0,0), m(2,0), m(3,0), m(0,2), m(2,2), m(3,2), m(0,3), m(2,3), m(3,3)) * inverseDeterminant;
2043  (*result)(2, 1) = -Matrix3x3Determinant(m(0,0), m(2,0), m(3,0), m(0,1), m(2,1), m(3,1), m(0,3), m(2,3), m(3,3)) * inverseDeterminant;
2044  (*result)(3, 1) = Matrix3x3Determinant (m(0,0), m(2,0), m(3,0), m(0,1), m(2,1), m(3,1), m(0,2), m(2,2), m(3,2)) * inverseDeterminant;
2045  (*result)(0, 2) = Matrix3x3Determinant (m(0,1), m(1,1), m(3,1), m(0,2), m(1,2), m(3,2), m(0,3), m(1,3), m(3,3)) * inverseDeterminant;
2046  (*result)(1, 2) = -Matrix3x3Determinant(m(0,0), m(1,0), m(3,0), m(0,2), m(1,2), m(3,2), m(0,3), m(1,3), m(3,3)) * inverseDeterminant;
2047  (*result)(2, 2) = Matrix3x3Determinant (m(0,0), m(1,0), m(3,0), m(0,1), m(1,1), m(3,1), m(0,3), m(1,3), m(3,3)) * inverseDeterminant;
2048  (*result)(3, 2) = -Matrix3x3Determinant(m(0,0), m(1,0), m(3,0), m(0,1), m(1,1), m(3,1), m(0,2), m(1,2), m(3,2)) * inverseDeterminant;
2049  (*result)(0, 3) = -Matrix3x3Determinant(m(0,1), m(1,1), m(2,1), m(0,2), m(1,2), m(2,2), m(0,3), m(1,3), m(2,3)) * inverseDeterminant;
2050  (*result)(1, 3) = Matrix3x3Determinant (m(0,0), m(1,0), m(2,0), m(0,2), m(1,2), m(2,2), m(0,3), m(1,3), m(2,3)) * inverseDeterminant;
2051  (*result)(2, 3) = -Matrix3x3Determinant(m(0,0), m(1,0), m(2,0), m(0,1), m(1,1), m(2,1), m(0,3), m(1,3), m(2,3)) * inverseDeterminant;
2052  (*result)(3, 3) = Matrix3x3Determinant (m(0,0), m(1,0), m(2,0), m(0,1), m(1,1), m(2,1), m(0,2), m(1,2), m(2,2)) * inverseDeterminant;
2053  return result;
2054  }
2055 
2064  inline Matrix3* MatrixFastInverse(Matrix3* result, const Matrix3* input)
2065  {
2066  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
2067 
2068  (*result)(0, 0) = (*input)(0, 0); //Diagonal is equal
2069  (*result)(1, 1) = (*input)(1, 1);
2070  (*result)(2, 2) = (*input)(2, 2);
2071 
2072  (*result)(1, 0) = (*input)(0, 1); //Rotation is transposed
2073  (*result)(2, 0) = (*input)(0, 2);
2074  (*result)(0, 1) = (*input)(1, 0);
2075  (*result)(2, 1) = (*input)(1, 2);
2076  (*result)(0, 2) = (*input)(2, 0);
2077  (*result)(1, 2) = (*input)(2, 1);
2078 
2079  return result;
2080  }
2081 
2097  inline Matrix4* MatrixFastInverse(Matrix4* result, const Matrix4* input)
2098  {
2099  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
2100 
2101  (*result)(0, 0) = (*input)(0, 0); //Diagonal is equal
2102  (*result)(1, 1) = (*input)(1, 1);
2103  (*result)(2, 2) = (*input)(2, 2);
2104  (*result)(3, 3) = (*input)(3, 3);
2105 
2106  (*result)(1, 0) = (*input)(0, 1); //Rotation is transposed
2107  (*result)(2, 0) = (*input)(0, 2);
2108  (*result)(0, 1) = (*input)(1, 0);
2109  (*result)(2, 1) = (*input)(1, 2);
2110  (*result)(0, 2) = (*input)(2, 0);
2111  (*result)(1, 2) = (*input)(2, 1);
2112 
2113  //This was the 'old' way that worked with translation in final COLUMN; it was a discrepency with where it
2114  //should have been; the test data changed 2020-11-26 and this will now succeed in the new way below. See
2115  //the comment at the very top of file for more information.
2116  //
2117  //const tbMath::Matrix4& inversed(*result); //Translation is multiplied by inversed 3x3, then negated.
2118  //(*result)(3, 0) = -((*input)(3, 0) * inversed(0, 0) + (*input)(3, 1) * inversed(1, 0) + (*input)(3, 2) * inversed(2, 0));
2119  //(*result)(3, 1) = -((*input)(3, 0) * inversed(0, 1) + (*input)(3, 1) * inversed(1, 1) + (*input)(3, 2) * inversed(2, 1));
2120  //(*result)(3, 2) = -((*input)(3, 0) * inversed(0, 2) + (*input)(3, 1) * inversed(1, 2) + (*input)(3, 2) * inversed(2, 2));
2121 
2122  //(*result)(0, 3) = 0.0f;
2123  //(*result)(1, 3) = 0.0f;
2124  //(*result)(2, 3) = 0.0f;
2125 
2126  const tbMath::Matrix4& inversed(*result); //Translation is multiplied by inversed 3x3, then negated.
2127  (*result)(0, 3) = -((*input)(0, 3) * inversed(0, 0) + (*input)(1, 3) * inversed(0, 1) + (*input)(2, 3) * inversed(0, 2));
2128  (*result)(1, 3) = -((*input)(0, 3) * inversed(1, 0) + (*input)(1, 3) * inversed(1, 1) + (*input)(2, 3) * inversed(1, 2));
2129  (*result)(2, 3) = -((*input)(0, 3) * inversed(2, 0) + (*input)(1, 3) * inversed(2, 1) + (*input)(2, 3) * inversed(2, 2));
2130 
2131  (*result)(3, 0) = 0.0f;
2132  (*result)(3, 1) = 0.0f;
2133  (*result)(3, 2) = 0.0f;
2134 
2135  return result;
2136  }
2137 
2138  namespace Unstable
2139  {
2140  inline Matrix4 Translate(const Matrix4& originalMatrix, const Vector3& translation)
2141  {
2142  Matrix4 outputMatrix(kSkipInitialization);
2143  Matrix4 translationMatrix(kSkipInitialization);
2144 
2145  MatrixCreateTranslation(&translationMatrix, &translation);
2146  MatrixMultiply(&outputMatrix, &translationMatrix, &originalMatrix);
2147 
2148  return outputMatrix;
2149  }
2150 
2151  inline Matrix4 Translate(const Matrix4& originalMatrix, float x, float y, float z)
2152  {
2153  return Translate(originalMatrix, tbMath::Vector3(x, y, z));
2154  }
2155 
2159  inline Matrix4 TranslateLocal(const Matrix4& originalMatrix, const Vector3& translation)
2160  {
2161  Matrix4 outputMatrix(kSkipInitialization);
2162  Matrix4 translationMatrix(kSkipInitialization);
2163 
2164  MatrixCreateTranslation(&translationMatrix, &translation);
2165  MatrixMultiply(&outputMatrix, &originalMatrix, &translationMatrix);
2166 
2167  return outputMatrix;
2168  }
2169 
2170  inline Matrix4 TranslateLocal(const Matrix4& originalMatrix, float x, float y, float z)
2171  {
2172  return TranslateLocal(originalMatrix, tbMath::Vector3(x, y, z));
2173  }
2174 
2178  inline Matrix3 Rotate(const Matrix3& originalMatrix, const Vector3& aroundAxis, const tbMath::Angle angle)
2179  {
2180  Matrix3 outputMatrix(kSkipInitialization);
2181  Matrix3 rotationMatrix(kSkipInitialization);
2182 
2183  //TODO: TurtleBrains: MathKit: Consistency check, do we negate here. CW / CCW seems to depend on the
2184  //handedness of the world rather than the negation here.
2185  MatrixCreateRotationA(&rotationMatrix, &aroundAxis, angle);
2186  MatrixMultiply(&outputMatrix, &rotationMatrix, &originalMatrix);
2187 
2188  return outputMatrix;
2189  }
2190 
2191  inline Matrix3 Rotate(const size_t& axisIndex, const Matrix3& originalMatrix, const tbMath::Angle angle)
2192  {
2193  return Rotate(originalMatrix, originalMatrix.GetBasis(axisIndex), angle);
2194  }
2195 
2199  inline Matrix4 Rotate(const Matrix4& originalMatrix, const Vector3& aroundAxis, const tbMath::Angle angle)
2200  {
2201  Matrix4 outputMatrix(kSkipInitialization);
2202  Matrix4 rotationMatrix(kSkipInitialization);
2203 
2204  //TODO: TurtleBrains: MathKit: Consistency check, do we negate here. CW / CCW seems to depend on the
2205  //handedness of the world rather than the negation here.
2206  MatrixCreateRotationA(&rotationMatrix, &aroundAxis, angle);
2207  MatrixMultiply(&outputMatrix, &rotationMatrix, &originalMatrix);
2208 
2209  return outputMatrix;
2210  }
2211 
2212  inline Matrix4 Rotate(const size_t& axisIndex, const Matrix4& originalMatrix, const tbMath::Angle angle)
2213  {
2214  return Rotate(originalMatrix, originalMatrix.GetBasis(axisIndex), angle);
2215  }
2216 
2217  //TODO: TurtleBrains: MathKit: Does RotateWorldSpace make sense, it is a little odd because of: Translate vs TranslateLocal
2218  // and here is using Rotate vs RotateWorld. Consistency concerns.
2219  inline Matrix4 RotateWorldSpace(const size_t& axisIndex, const Matrix4& originalMatrix, const tbMath::Angle angle)
2220  {
2221  Matrix4 outputMatrix(kSkipInitialization);
2222  Matrix4 rotationMatrix(kSkipInitialization);
2223 
2224  //Negating here for positive rotationInDegrees to spin clockwise around the axis.
2225  //TODO: TurtleBrains: MathKit: Consistency check, do we negate here. CW / CCW seems to depend on the
2226  //handedness of the world rather than the negation here.
2227  const tbMath::Vector3 worldAxis(Matrix4::Identity().GetBasis(axisIndex));
2228  MatrixCreateRotationA(&rotationMatrix, &worldAxis, -angle);
2229  const Matrix4 rotationTransposed(rotationMatrix.GetTransposed());
2230  MatrixMultiply(&outputMatrix, &originalMatrix, &rotationTransposed);
2231 
2232  return outputMatrix;
2233  }
2234 
2235  inline Matrix3 Scale(const Matrix3& originalMatrix, const Vector3& scale)
2236  {
2237  Matrix3 outputMatrix(kSkipInitialization);
2238  Matrix3 scalingMatrix(kSkipInitialization);
2239 
2240  MatrixCreateScale(&scalingMatrix, &scale);
2241  MatrixMultiply(&outputMatrix, &scalingMatrix, &originalMatrix);
2242 
2243  return outputMatrix;
2244  }
2245 
2246  inline Matrix3 Scale(const Matrix3 originalMatrix, float x, float y, float z)
2247  {
2248  return Scale(originalMatrix, Vector3(x, y, z));
2249  }
2250 
2251  inline Matrix4 Scale(const Matrix4& originalMatrix, const Vector3& scale)
2252  {
2253  Matrix4 outputMatrix(kSkipInitialization);
2254  Matrix4 scalingMatrix(kSkipInitialization);
2255 
2256  MatrixCreateScale(&scalingMatrix, &scale);
2257  MatrixMultiply(&outputMatrix, &scalingMatrix, &originalMatrix);
2258 
2259  return outputMatrix;
2260  }
2261 
2262  inline Matrix4 Scale(const Matrix4& originalMatrix, float x, float y, float z)
2263  {
2264  return Scale(originalMatrix, Vector3(x, y, z));
2265  }
2266 
2267  }; /* namespace Unstable */
2268 
2269  }; /* namespace Math */
2270 }; /* namespace TurtleBrains */
2271 
2272 namespace tbMath = TurtleBrains::Math;
2273 
2274 #endif /* TurtleBrains_Matrix_hpp */
Matrix4 * MatrixCreateScale(Matrix4 *result, const float scaleX, const float scaleY, const float scaleZ)
Definition: tb_matrix.hpp:1290
Matrix3 * MatrixFastInverse(Matrix3 *result, const Matrix3 *input)
Definition: tb_matrix.hpp:2064
static Matrix4 Identity(void)
Definition: tb_matrix.hpp:546
AngleType< float > Angle
Definition: tb_angle.hpp:154
static Matrix3 Identity(void)
Definition: tb_matrix.hpp:129
const float & operator()(int column, int row) const
Definition: tb_matrix.hpp:343
Type AsRadians(void) const
Definition: tb_angle.hpp:79
Matrix4 * MatrixCreateTranslation(Matrix4 *result, const Vector3 *translation)
Definition: tb_matrix.hpp:1213
Vector3 * MatrixVector3Multiply(Vector3 *result, const Matrix3 *inputMatrix, const Vector3 *inputVector)
Definition: tb_matrix.hpp:1833
Contains objects and functions for dealing with Vector and Matrix math.
static Matrix4 Zero(void)
Definition: tb_matrix.hpp:533
Matrix4(void)
Definition: tb_matrix.hpp:638
Matrix3(float f11, float f21, float f31, float f12, float f22, float f32, float f13, float f23, float f33)
Definition: tb_matrix.hpp:218
float & operator[](const int &index)
Definition: tb_matrix.hpp:324
const float & operator()(const size_t &column, const size_t &row) const
Definition: tb_matrix.hpp:805
bool operator!=(const Matrix3 &other) const
Definition: tb_matrix.hpp:300
Matrix3 * MatrixCreateRotationZ(Matrix3 *result, const Angle rotation)
Definition: tb_matrix.hpp:1375
Definition: tb_vector.hpp:317
Definition: tb_matrix.hpp:111
Matrix3 * MatrixTranspose(Matrix3 *result, const Matrix3 *input)
Definition: tb_matrix.hpp:1670
Matrix4 * MatrixCreateRotationA(Matrix4 *result, const Vector3 *rotationAxis, const Angle rotation)
Definition: tb_matrix.hpp:1438
Matrix3 * MatrixCreateIdentity(Matrix3 *result)
Definition: tb_matrix.hpp:1150
Matrix3 * MatrixMultiply(Matrix3 *result, const Matrix3 *left, const Matrix3 *right)
Definition: tb_matrix.hpp:1711
bool IsZero(const Type &value)
Definition: tb_math.hpp:53
float & operator()(int column, int row)
Definition: tb_matrix.hpp:825
float Matrix3x3Determinant(const float f11, const float f12, const float f13, const float f21, const float f22, const float f23, const float f31, const float f32, const float f33)
Definition: tb_matrix.hpp:1956
Matrix3 * MatrixComputeInverse(Matrix3 *result, const Matrix3 *input)
Definition: tb_matrix.hpp:1987
bool operator!=(const Matrix4 &other) const
Definition: tb_matrix.hpp:775
Here is some information about the primary namespace.
Definition: tb_application_dialog.hpp:21
Matrix3 * MatrixCreateRotationX(Matrix3 *result, const Angle rotation)
Definition: tb_matrix.hpp:1307
Matrix4(float f11, float f21, float f31, float f41, float f12, float f22, float f32, float f42, float f13, float f23, float f33, float f43, float f14, float f24, float f34, float f44, const ColumnMajorMatrix &columnMajor)
Definition: tb_matrix.hpp:669
#define tb_unused(parameter)
Definition: tb_defines.hpp:25
void SetPosition(const float x, const float y, const float z)
Definition: tb_matrix.hpp:899
Matrix4(float f11, float f21, float f31, float f41, float f12, float f22, float f32, float f42, float f13, float f23, float f33, float f43, float f14, float f24, float f34, float f44)
Definition: tb_matrix.hpp:650
Matrix4 * MatrixCreateRotationZ(Matrix4 *result, const Angle rotation)
Definition: tb_matrix.hpp:1390
Vector3 * Vector3Normalize(Vector3 *result, const Vector3 *input)
Definition: tb_vector.hpp:1341
Definition: tb_matrix.hpp:527
SkipInitialization
Definition: tb_vector.hpp:30
bool IsEqual(const Type &leftValue, const Type &rightValue)
Definition: tb_math.hpp:30
Matrix4 * MatrixCreateRotationY(Matrix4 *result, const Angle rotation)
Definition: tb_matrix.hpp:1356
float & operator[](const size_t &index)
Definition: tb_matrix.hpp:799
Matrix3(const Matrix3 &other)
Definition: tb_matrix.hpp:255
float & operator()(const size_t &column, const size_t &row)
Definition: tb_matrix.hpp:812
Vector4 * Vector4MatrixMultiply(Vector4 *result, const Vector4 *inputVector, const Matrix4 *inputMatrix)
Definition: tb_matrix.hpp:1894
Vector3 GetPosition(void) const
Definition: tb_matrix.hpp:879
const float & operator[](const int &index) const
Definition: tb_matrix.hpp:317
Matrix3(void)
Definition: tb_matrix.hpp:207
Matrix4 * MatrixCreateOrthoRH(Matrix4 *result, const float left, const float right, const float top, const float bottom, const float nearPlane, const float farPlane)
Definition: tb_matrix.hpp:1544
Matrix4 * MatrixCreateLookAt(Matrix4 *result, const Vector3 &eyePosition, const Vector3 &targetPosition, const Vector3 &unitUp)
Definition: tb_matrix.hpp:1174
Matrix4 * MatrixCreatePerspectiveLH(Matrix4 *result, const float fieldOfView, const float aspectRatio, const float nearPlane, const float farPlane)
Definition: tb_matrix.hpp:1512
Matrix4 * MatrixCreatePerspectiveRH(Matrix4 *result, const float fieldOfView, const float aspectRatio, const float nearPlane, const float farPlane)
Definition: tb_matrix.hpp:1483
bool operator==(const Matrix3 &other) const
Definition: tb_matrix.hpp:282
Vector3 * Vector3Subtract(Vector3 *result, const Vector3 *leftSide, const Vector3 *rightSide)
Definition: tb_vector.hpp:1015
Matrix4(const float *const componentArray)
Definition: tb_matrix.hpp:688
void SetBasis(const size_t &basisIndex, float basisX, float basisY, float basisZ)
Definition: tb_matrix.hpp:391
Matrix4(const float *const componentArray, const ColumnMajorMatrix &columnMajor)
Definition: tb_matrix.hpp:704
bool operator==(const Matrix4 &other) const
Definition: tb_matrix.hpp:757
Matrix4 * MatrixCreateOrthoLH(Matrix4 *result, const float left, const float right, const float top, const float bottom, const float nearPlane, const float farPlane)
Definition: tb_matrix.hpp:1576
Matrix4 * MatrixCreateRotationX(Matrix4 *result, const Angle rotation)
Definition: tb_matrix.hpp:1322
Matrix3 * MatrixCreateRotationA(Matrix3 *result, const Vector3 *rotationAxis, const Angle rotation)
Definition: tb_matrix.hpp:1410
Matrix4 & operator=(const Matrix4 &other)
Definition: tb_matrix.hpp:741
float Vector3DotProduct(const Vector3 *leftSide, const Vector3 *rightSide)
Definition: tb_vector.hpp:1204
void SetBasis(const size_t &basisIndex, const Vector3 &basis)
Definition: tb_matrix.hpp:381
const float & operator()(int column, int row) const
Definition: tb_matrix.hpp:818
static Matrix3 Zero(void)
Definition: tb_matrix.hpp:117
Matrix3(const SkipInitialization &fastAndStupid)
Definition: tb_matrix.hpp:247
Vector3 * Vector3CrossProduct(Vector3 *result, const Vector3 *leftSide, const Vector3 *rightSide)
Definition: tb_vector.hpp:1234
Matrix3 & operator=(const Matrix3 &other)
Definition: tb_matrix.hpp:266
float MatrixDeterminant(const Matrix3 *input)
Definition: tb_matrix.hpp:1965
float & operator()(const size_t &column, const size_t &row)
Definition: tb_matrix.hpp:337
Definition: tb_angle.hpp:34
Vector4 * MatrixVector4Multiply(Vector4 *result, const Matrix4 *inputMatrix, const Vector4 *inputVector)
Definition: tb_matrix.hpp:1873
Matrix3 * MatrixAdd(Matrix3 *result, const Matrix3 *leftSide, const Matrix3 *rightSide)
Definition: tb_matrix.hpp:1600
Vector3 * Vector3TransformNormal(Vector3 *result, const Vector3 *inputVector, const Matrix4 *inputMatrix)
Definition: tb_matrix.hpp:1936
Matrix3 * MatrixSubtract(Matrix3 *result, const Matrix3 *leftSide, const Matrix3 *rightSide)
Definition: tb_matrix.hpp:1636
const float & operator()(const size_t &column, const size_t &row) const
Definition: tb_matrix.hpp:330
Matrix3 * MatrixCreateScale(Matrix3 *result, const Vector3 *scale)
Definition: tb_matrix.hpp:1247
void SetBasis(const size_t &basisIndex, const Vector3 &basis)
Definition: tb_matrix.hpp:857
void SetBasis(const size_t &basisIndex, float basisX, float basisY, float basisZ)
Definition: tb_matrix.hpp:867
#define tb_error_if(errorTest, message,...)
Definition: tb_error.hpp:42
Matrix4(const Matrix4 &other)
Definition: tb_matrix.hpp:728
Vector3 GetBasis(const size_t &basisIndex) const
Definition: tb_matrix.hpp:849
Matrix4 * MatrixCreateTranslation(Matrix4 *result, const float translationX, const float translationY, const float translationZ)
Definition: tb_matrix.hpp:1231
float & operator()(int column, int row)
Definition: tb_matrix.hpp:350
const float & operator[](const size_t &index) const
Definition: tb_matrix.hpp:792
Vector3 * Vector3TransformCoordinate(Vector3 *result, const Vector3 *inputVector, const Matrix4 *inputMatrix)
Definition: tb_matrix.hpp:1914
void SetPosition(const Vector3 &position)
Definition: tb_matrix.hpp:888
float Vector3Magnitude(const Vector3 *input)
Definition: tb_vector.hpp:1264
Matrix3(const float *const componentArray)
Definition: tb_matrix.hpp:233
Definition: tb_vector.hpp:626
const Vector3 GetBasis(const size_t &basisIndex) const
Definition: tb_matrix.hpp:373
Vector3 * Vector3MatrixMultiply(Vector3 *result, const Vector3 *inputVector, const Matrix3 *inputMatrix)
Definition: tb_matrix.hpp:1853
Matrix4(const SkipInitialization &fastAndStupid)
Definition: tb_matrix.hpp:720
Matrix3 * MatrixCreateRotationY(Matrix3 *result, const Angle rotation)
Definition: tb_matrix.hpp:1341