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 #include <turtle_brains/core/tb_string.hpp>
17 
18 #include <cmath>
19 #include <cstring> //memcpy / memset
20 #include <iostream>
21 
22 // TODO: TurtleBrains: Make Identity() a constexpr static member function. Readup on constexpr
23 
24 //Pre-Multiply (vector on left), Bases Contiguous:
25 // Xx, Xy, Xz, 0
26 // Yx, Yy, Yz, 0
27 // Zx, Zy, Zz, 0
28 // Tx, Ty, Tz, 1
29 //
30 // Xx, Xy, Xz, 0, Yx, Yy, Yz, 0, Zx, Zy, Zz, 0, Tx, Ty, Tz, 1
31 
32 //
33 // The above is close to what I desire, but the data in matrix test kit is showing that we have something much different
34 // probably looking like (basis/rotation 3x3 unconfirmed): Xx, Xy, Xz, Tx, Yx, Yy, Yz, Ty, Zx, Zy Zz, Tz, 0, 0, 0, 1
35 // as that is how our test data is being shoved into the matrix object... 2020-11-25
36 //
37 // This was found because FastInverse() did not work in doing physics; FastInverse() was using the final COLUMN as the
38 // placement of translation/position and the above shows the final row being used. Changing FastInverse() breaks the
39 // previous tests, so what gives?
40 //
41 // To make this matter even more interesting, the CreateTranslation() function does put the position components in the
42 // final ROW as it shows in the above 'image'. The mat(1, 3) operator is specified by: column, row and memory is accessed
43 // by components[column + (row * 4)]; CreateTranslation() then puts translation at mat(0, 3), mat(1, 3), mat(2, 3) aka: Final row.
44 //
45 // Intrets says pre-multiply, vector*matrix, should have the translation on the last row.
46 //
47 // There was only a single instance of FastInverse() called in Rally of Rockets, and that instance didn't even use
48 // the positional data. This tells me that the test likely contains bad data and we just got really lucky in Rally of Rockets
49 // to use TransformNormal() instead of TransformCoordinate(). There were no occurances of FastInverse() in Turbo Boom!,
50 // Track Builder, and LudumDare47.
51 //
52 // 2020-11-26 - FastInverse() was fixed and the test data was also fixed. Essentially the 16 skeletal animation matrices
53 // provided by shakesoda had translation in the final column while our matrix actually does expect it in the final ROW.
54 // While I was adjust the translation data (only moving translation from final column to final row), shakesoda said this
55 // was suspect and I was doing it wrong, but never gave more information on why that was the case. Since every other test
56 // was passing except for the known broken FastInverse, moving translation data in those matrices fixed everything once
57 // FastInverse() was also fixed. (FastInverse had to swap final column for final row and also pre/post mulitply direction.
58 //
59 // 2022-07-21: Another thing of note that should be defined clearly is the access of elements is column, row. This goes
60 // against some conventions where access is defined row, column - but I feel it keeps things much more consistent with
61 // battleship, grids and all the other conventions of life, or coordinate systems conventions where access is X then Y
62 // and here X chooses which column, Y chooses which row just like columns and pixels on a screen...
63 //
64 //
65 //
66 // 2024-10-15: tsjost says we can't rotate and translate a point at the same time using a single matrix. I'm not entirely
67 // sure what that actually means in practice, since we have a whole 3D world and haven't really messed with matrices in
68 // YEARS. The following test "fails" but I don't know why that is important;
69 // http://www.mathforengineers.com/math-calculators/3D-point-rotation-calculator.html
70 //
71 // 10 degree rotation around the Y
72 //Matrix4 tsjostToWorld = Matrix4::Identity();
73 //tsjostToWorld.SetBasis(0, Vector3(0.98480775304683922902, 0, 0.17364817747052722591));
74 //tsjostToWorld.SetBasis(1, Vector3::Up());
75 //tsjostToWorld.SetBasis(2, Vector3(-0.17364817747052722591, 0, 0.98480775304683922902));
77 
79 //tsjostToWorld[3] = 2;
80 //tsjostToWorld[7] = 3;
81 //tsjostToWorld[11] = 4;
82 
85 
86 //Vector4 vectorInTsjost(5, 16, 9, 1);
87 //Vector4 vectorInWorld = vectorInTsjost * tsjostToWorld;
88 //Vector4 otherVector = tsjostToWorld * vectorInTsjost;
89 //rand();
90 
91 
92 namespace TurtleBrains
93 {
94  namespace Math
95  {
96 
97  enum ColumnMajorMatrix
98  {
99  ColumnMajor = 1,
100  };
101 
102  //Forward Declarations used in TypedMatrix4 class.
103  template<typename Type> class TypedVector3;
104  template<typename Type> class TypedVector4;
105  template<typename Type> class TypedMatrix3;
106  template<typename Type> class TypedMatrix4;
107  template<typename Type> class TypedQuaternion;
108 
109  typedef TypedMatrix3<float> Matrix3;
110  typedef TypedMatrix4<float> Matrix4;
111 
112  //Forward Declarations used in Matrix4 class.
113 
114  template<typename Type> TypedVector3<Type>* Vector3MatrixMultiply(TypedVector3<Type>* result,
115  const TypedVector3<Type>* inputVector, const TypedMatrix3<Type>* inputMatrix);
116 
117  template<typename Type> TypedVector3<Type>* MatrixVector3Multiply(TypedVector3<Type>* result,
118  const TypedMatrix3<Type>* inputMatrix, const TypedVector3<Type>* inputVector);
119 
120  template<typename Type> TypedMatrix3<Type>* MatrixMultiply(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* input, const Type& scalar);
121  template<typename Type> TypedMatrix4<Type>* MatrixMultiply(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* input, const Type& scalar);
122  template<typename Type> TypedMatrix3<Type>* MatrixMultiply(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* leftSide, const TypedMatrix3<Type>* rightSide);
123  template<typename Type> TypedMatrix4<Type>* MatrixMultiply(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* leftSide, const TypedMatrix4<Type>* rightSide);
124 
125  template<typename Type> TypedVector4<Type>* MatrixVector4Multiply(TypedVector4<Type>* result, const TypedMatrix4<Type>* inputMatrix, const TypedVector4<Type>* inputVector);
126  template<typename Type> TypedVector4<Type>* Vector4MatrixMultiply(TypedVector4<Type>* result, const TypedVector4<Type>* inputVector, const TypedMatrix4<Type>* inputMatrix);
127  template<typename Type> TypedVector3<Type>* Vector3TransformCoordinate(TypedVector3<Type>* result, const TypedVector3<Type>* inputVector, const TypedMatrix4<Type>* inputMatrix);
128  template<typename Type> TypedVector3<Type>* Vector3TransformNormal(TypedVector3<Type>* result, const TypedVector3<Type>* inputVector, const TypedMatrix4<Type>* inputMatrix);
129  template<typename Type> TypedMatrix3<Type>* MatrixComputeInverse(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* input);
130  template<typename Type> TypedMatrix4<Type>* MatrixComputeInverse(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* input);
131  template<typename Type> TypedMatrix3<Type>* MatrixFastInverse(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* input);
132  template<typename Type> TypedMatrix4<Type>* MatrixFastInverse(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* input);
133 
134  template<typename Type> TypedMatrix4<Type>* MatrixCreateTranslation(TypedMatrix4<Type>* result, const TypedVector3<Type>* translation);
135  template<typename Type> TypedMatrix4<Type>* MatrixCreateTranslation(TypedMatrix4<Type>* result, const Type translationX, const Type translationY, const Type translationZ);
136  template<typename Type> TypedMatrix3<Type>* MatrixCreateScale(TypedMatrix3<Type>* result, const TypedVector3<Type>* scale);
137  template<typename Type> TypedMatrix4<Type>* MatrixCreateScale(TypedMatrix4<Type>* result, const TypedVector3<Type>* scale);
138  template<typename Type> TypedMatrix3<Type>* MatrixCreateScale(TypedMatrix3<Type>* result, const Type scaleX, const Type scaleY, const Type scaleZ);
139  template<typename Type> TypedMatrix4<Type>* MatrixCreateScale(TypedMatrix4<Type>* result, const Type scaleX, const Type scaleY, const Type scaleZ);
140  template<typename Type> TypedMatrix3<Type>* MatrixCreateRotationX(TypedMatrix3<Type>* result, const TypedAngle<Type> rotation);
141  template<typename Type> TypedMatrix4<Type>* MatrixCreateRotationX(TypedMatrix4<Type>* result, const TypedAngle<Type> rotation);
142  template<typename Type> TypedMatrix3<Type>* MatrixCreateRotationY(TypedMatrix3<Type>* result, const TypedAngle<Type> rotation);
143  template<typename Type> TypedMatrix4<Type>* MatrixCreateRotationY(TypedMatrix4<Type>* result, const TypedAngle<Type> rotation);
144  template<typename Type> TypedMatrix3<Type>* MatrixCreateRotationZ(TypedMatrix3<Type>* result, const TypedAngle<Type> rotation);
145  template<typename Type> TypedMatrix4<Type>* MatrixCreateRotationZ(TypedMatrix4<Type>* result, const TypedAngle<Type> rotation);
146  template<typename Type> TypedMatrix3<Type>* MatrixCreateRotationA(TypedMatrix3<Type>* result, const TypedVector3<Type>* rotationAxis, const TypedAngle<Type> rotation);
147  template<typename Type> TypedMatrix4<Type>* MatrixCreateRotationA(TypedMatrix4<Type>* result, const TypedVector3<Type>* rotationAxis, const TypedAngle<Type> rotation);
148 
155  template<typename Type> class TypedMatrix3
156  {
157  public:
161  static TypedMatrix3 Zero(void)
162  {
163  return TypedMatrix3(
164  Type(0), Type(0), Type(0),
165  Type(0), Type(0), Type(0),
166  Type(0), Type(0), Type(0));
167  }
168 
173  static TypedMatrix3 Identity(void)
174  {
175  return TypedMatrix3(
176  Type(1), Type(0), Type(0),
177  Type(0), Type(1), Type(0),
178  Type(0), Type(0), Type(1));
179  }
180 
181  static TypedMatrix3 Scale(const tbMath::Vector3& scale)
182  {
183  TypedMatrix3 matrix(tbMath::kSkipInitialization);
184  tbMath::MatrixCreateScale(&matrix, &scale);
185  return matrix;
186  }
187 
188  static TypedMatrix3 Scale(const float scaleX, const float scaleY, const float scaleZ)
189  {
190  TypedMatrix3 matrix(tbMath::kSkipInitialization);
191  tbMath::MatrixCreateScale(&matrix, scaleX, scaleY, scaleZ);
192  return matrix;
193  }
194 
195  static TypedMatrix3 RotationX(const TypedAngle<Type>& rotation)
196  {
197  TypedMatrix3 matrix(tbMath::kSkipInitialization);
198  tbMath::MatrixCreateRotationX(&matrix, rotation);
199  return matrix;
200  }
201 
202  static TypedMatrix3 RotationY(const TypedAngle<Type>& rotation)
203  {
204  TypedMatrix3 matrix(tbMath::kSkipInitialization);
205  tbMath::MatrixCreateRotationY(&matrix, rotation);
206  return matrix;
207  }
208 
209  static TypedMatrix3 RotationZ(const TypedAngle<Type>& rotation)
210  {
211  TypedMatrix3 matrix(tbMath::kSkipInitialization);
212  tbMath::MatrixCreateRotationZ(&matrix, rotation);
213  return matrix;
214  }
215 
216  static TypedMatrix3 RotationA(const TypedVector3<Type>& rotationAxis, const tbMath::TypedAngle<Type>& rotation)
217  {
218  TypedMatrix3 matrix(kSkipInitialization);
219  MatrixCreateRotationA<Type>(&matrix, &rotationAxis, rotation);
220  return matrix;
221  }
222 
223  //Defined in tb_matrix_quaternion.h
224  static TypedMatrix3 FromQuaternion(const TypedQuaternion<Type>& quaternion);
225 
226  union
227  {
228  Type mComponents[9];
229 
230 #if defined(tb_visual_cpp)
231 #pragma warning(push)
232 #pragma warning(disable: 4201)
233  struct { //May be deprecating!?
234  Type m_f11; Type m_f21; Type m_f31;
235  Type m_f12; Type m_f22; Type m_f32;
236  Type m_f13; Type m_f23; Type m_f33;
237  };
238 #pragma warning(pop)
239 #else
240  struct { //May be deprecating!?
241  Type m_f11; Type m_f21; Type m_f31;
242  Type m_f12; Type m_f22; Type m_f32;
243  Type m_f13; Type m_f23; Type m_f33;
244  };
245 #endif
246  };
247 
251  inline TypedMatrix3(void) :
252  mComponents{
253  Type(1), Type(0), Type(0),
254  Type(0), Type(1), Type(0),
255  Type(0), Type(0), Type(1) }
256  {
257  }
258 
262  inline explicit TypedMatrix3(Type f11, Type f21, Type f31,
263  Type f12, Type f22, Type f32,
264  Type f13, Type f23, Type f33) :
265  mComponents{
266  f11, f21, f31,
267  f12, f22, f32,
268  f13, f23, f33 }
269  {
270  }
271 
277  inline explicit TypedMatrix3(const Type* const componentArray) :
278  mComponents{
279  componentArray[0], componentArray[1], componentArray[2],
280  componentArray[3], componentArray[4], componentArray[5],
281  componentArray[6], componentArray[7], componentArray[8] }
282  {
283  }
284 
291 #if defined(tb_visual_cpp)
292 #pragma warning(push)
293 #pragma warning(disable: 26495)
294  inline explicit TypedMatrix3(const SkipInitialization& fastAndStupid)
295  {
296  tb_unused(fastAndStupid);
297  }
298 #pragma warning(pop)
299 #else
300  inline explicit TypedMatrix3(const SkipInitialization& fastAndStupid)
301  {
302  tb_unused(fastAndStupid);
303  }
304 #endif
305 
309  TypedMatrix3(const TypedMatrix3& other) = default;
310 
311  template<typename FromType> explicit TypedMatrix3(const TypedMatrix3<FromType>& other) :
312  mComponents{
313  static_cast<Type>(other.mComponents[0]), static_cast<Type>(other.mComponents[1]), static_cast<Type>(other.mComponents[2]),
314  static_cast<Type>(other.mComponents[3]), static_cast<Type>(other.mComponents[4]), static_cast<Type>(other.mComponents[5]),
315  static_cast<Type>(other.mComponents[6]), static_cast<Type>(other.mComponents[7]), static_cast<Type>(other.mComponents[8])
316  }
317  {
318  }
319 
320  ~TypedMatrix3(void) = default;
321 
325  TypedMatrix3& operator=(const TypedMatrix3& other) = default;
326 
337  inline bool operator==(const TypedMatrix3& other) const
338  {
339  for (size_t index(0); index < 9; ++index)
340  {
341  if (false == IsEqual(mComponents[index], other[index]))
342  {
343  return false;
344  }
345  }
346 
347  return true;
348  }
349 
355  inline bool operator!=(const TypedMatrix3& other) const
356  {
357  for (size_t index(0); index < 9; ++index)
358  {
359  if (false == IsEqual(mComponents[index], other[index]))
360  {
361  return true;
362  }
363  }
364 
365  return false;
366  }
367 
372  inline const Type& operator[](const int& index) const { return mComponents[index]; }
373  inline const Type& operator[](const std::size_t& index) const { return mComponents[index]; }
374 
380  inline Type& operator[](const int& index) { return mComponents[index]; }
381  inline Type& operator[](const std::size_t& index) { return mComponents[index]; }
382 
387  inline const Type& operator()(const size_t& column, const size_t& row) const { return mComponents[column + (row * 3)]; }
388 
394  inline Type& operator()(const size_t& column, const size_t& row) { return mComponents[column + (row * 3)]; }
395 
400  inline const Type& operator()(int column, int row) const { return mComponents[column + (row * 3)]; }
401 
407  inline Type& operator()(int column, int row) { return mComponents[column + (row * 3)]; }
408 
416  inline explicit operator Type* (void) { return mComponents; }
417 
421  inline explicit operator const Type* (void) const { return mComponents; }
422 
426  template<typename ToType> explicit operator TypedMatrix3<ToType>(void) const
427  {
428  return TypedMatrix3<ToType>(
429  static_cast<ToType>(m_f11), static_cast<ToType>(m_f21), static_cast<ToType>(m_f31),
430  static_cast<ToType>(m_f12), static_cast<ToType>(m_f22), static_cast<ToType>(m_f32),
431  static_cast<ToType>(m_f13), static_cast<ToType>(m_f23), static_cast<ToType>(m_f33));
432  }
433 
441  inline const TypedVector3<Type> GetBasis(const size_t& basisIndex) const { return TypedVector3<Type>(&mComponents[basisIndex * 3]); }
442 
449  inline void SetBasis(const size_t& basisIndex, const TypedVector3<Type>& basis) { *((TypedVector3<Type>*) & mComponents[basisIndex * 3]) = basis; }
450 
459  inline void SetBasis(const size_t& basisIndex, Type basisX, Type basisY, Type basisZ)
460  {
461  mComponents[(basisIndex * 3) + 0] = basisX;
462  mComponents[(basisIndex * 3) + 1] = basisY;
463  mComponents[(basisIndex * 3) + 2] = basisZ;
464  }
465 
466  inline TypedVector3<Type>Transform(const TypedVector3<Type>& inputVector) const
467  {
468  TypedVector3<Type> result;
469  Vector3MatrixMultiply(&result, &inputVector, this);
470  return result;
471  }
472 
473 #if defined(tb_with_math_operators)
477  inline TypedMatrix3 operator+(const TypedMatrix3& rightSide) const
478  {
479  const TypedMatrix3& leftSide(*this);
480  return TypedMatrix3(
481  leftSide(0, 0) + rightSide(0, 0), leftSide(1, 0) + rightSide(1, 0), leftSide(2, 0) + rightSide(2, 0),
482  leftSide(0, 1) + rightSide(0, 1), leftSide(1, 1) + rightSide(1, 1), leftSide(2, 1) + rightSide(2, 1),
483  leftSide(0, 2) + rightSide(0, 2), leftSide(1, 2) + rightSide(1, 2), leftSide(2, 2) + rightSide(2, 2));
484  }
485 
490  inline TypedMatrix3& operator+=(const TypedMatrix3& rightSide)
491  {
492  for (size_t index = 0; index < 9; ++index)
493  {
494  (*this)[index] += rightSide[index];
495  }
496  return *this;
497  }
498 
502  inline TypedMatrix3 operator-(const TypedMatrix3& rightSide) const
503  {
504  const TypedMatrix3& leftSide(*this);
505  return TypedMatrix3(
506  leftSide(0, 0) - rightSide(0, 0), leftSide(1, 0) - rightSide(1, 0), leftSide(2, 0) - rightSide(2, 0),
507  leftSide(0, 1) - rightSide(0, 1), leftSide(1, 1) - rightSide(1, 1), leftSide(2, 1) - rightSide(2, 1),
508  leftSide(0, 2) - rightSide(0, 2), leftSide(1, 2) - rightSide(1, 2), leftSide(2, 2) - rightSide(2, 2));
509  }
510 
514  inline TypedMatrix3& operator-=(const TypedMatrix3& rightSide)
515  {
516  for (size_t index = 0; index < 9; ++index)
517  {
518  (*this)[index] -= rightSide[index];
519  }
520  return *this;
521  }
522 
523 
527  inline TypedMatrix3 operator*(const TypedMatrix3& rightSide) const
528  {
529  TypedMatrix3 result;
530  MatrixMultiply(&result, this, &rightSide);
531  return result;
532  }
533 
537  inline TypedMatrix3 operator*=(const TypedMatrix3& rightSide)
538  {
539  TypedMatrix3 leftSide = *this;
540  MatrixMultiply(this, &leftSide, &rightSide);
541  return *this;
542  }
543 
547  inline TypedMatrix3 GetTransposed(void) const
548  {
549  const TypedMatrix3& self(*this);
550  return TypedMatrix3(
551  self(0, 0), self(0, 1), self(0, 2),
552  self(1, 0), self(1, 1), self(1, 2),
553  self(2, 0), self(2, 1), self(2, 2));
554  }
555 
561  inline TypedMatrix3 ComputeInverse(void) const
562  {
563  TypedMatrix3 result;
564  MatrixComputeInverse(&result, this);
565  return result;
566  }
567 
572  inline TypedMatrix3 FastInverse(void) const
573  {
574  TypedMatrix3 result;
575  MatrixFastInverse(&result, this);
576  return result;
577  }
578 #endif
579  };
580 
584 
595  template<typename Type> class TypedMatrix4
596  {
597  public:
601  static TypedMatrix4 Zero(void)
602  {
603  return TypedMatrix4(
604  Type(0), Type(0), Type(0), Type(0),
605  Type(0), Type(0), Type(0), Type(0),
606  Type(0), Type(0), Type(0), Type(0),
607  Type(0), Type(0), Type(0), Type(0));
608  }
609 
614  static TypedMatrix4 Identity(void)
615  {
616  return TypedMatrix4(
617  Type(1), Type(0), Type(0), Type(0),
618  Type(0), Type(1), Type(0), Type(0),
619  Type(0), Type(0), Type(1), Type(0),
620  Type(0), Type(0), Type(0), Type(1));
621  }
622 
624  static TypedMatrix4 Translation(const TypedVector3<Type>& translation)
625  {
626  TypedMatrix4 matrix(tbMath::kSkipInitialization);
627  MatrixCreateTranslation(&matrix, &translation);
628  return matrix;
629  }
630 
631  static TypedMatrix4 Translation(const Type translationX, const Type translationY, const Type translationZ)
632  {
633  TypedMatrix4 matrix(tbMath::kSkipInitialization);
634  MatrixCreateTranslation(&matrix, translationX, translationY, translationZ);
635  return matrix;
636  }
637 
638  static TypedMatrix4 Scale(const TypedVector3<Type>& scale)
639  {
640  TypedMatrix4 matrix(kSkipInitialization);
641  MatrixCreateScale(&matrix, &scale);
642  return matrix;
643  }
644 
645  static TypedMatrix4 Scale(const Type scaleX, const Type scaleY, const Type scaleZ)
646  {
647  TypedMatrix4 matrix(kSkipInitialization);
648  MatrixCreateScale(&matrix, scaleX, scaleY, scaleZ);
649  return matrix;
650  }
651 
652  static TypedMatrix4 RotationX(const tbMath::TypedAngle<Type>& rotation)
653  {
654  TypedMatrix4 matrix(kSkipInitialization);
655  MatrixCreateRotationX(&matrix, rotation);
656  return matrix;
657  }
658 
659  static TypedMatrix4 RotationY(const tbMath::TypedAngle<Type>& rotation)
660  {
661  TypedMatrix4 matrix(kSkipInitialization);
662  MatrixCreateRotationY(&matrix, rotation);
663  return matrix;
664  }
665 
666  static TypedMatrix4 RotationZ(const tbMath::TypedAngle<Type>& rotation)
667  {
668  TypedMatrix4 matrix(kSkipInitialization);
669  MatrixCreateRotationZ(&matrix, rotation);
670  return matrix;
671  }
672 
673  static TypedMatrix4 RotationA(const TypedVector3<Type>& rotationAxis, const tbMath::TypedAngle<Type>& rotation)
674  {
675  TypedMatrix4 matrix(kSkipInitialization);
676  MatrixCreateRotationA<Type>(&matrix, &rotationAxis, rotation);
677  return matrix;
678  }
679 
680  static TypedMatrix4 FromTransform(const TypedVector3<Type>& position, const TypedMatrix3<Type>& orientation, const TypedVector3<Type>& scale)
681  {
682  TypedMatrix4 matrix = Identity();
683  matrix.Compose(position, orientation, scale);
684  return matrix;
685  }
686 
687  //Defined in tb_matrix_quaternion.hpp
688  static TypedMatrix4 FromQuaternion(const tbMath::TypedQuaternion<Type>& quaternion, const TypedVector3<Type>& translation);
689 
691 
692  union
693  {
694  Type mComponents[16];
695 
696 #if defined(tb_visual_cpp)
697 #pragma warning(push)
698 #pragma warning(disable: 4201)
699 #endif
700  struct {
701  Type xx; Type xy; Type xz; Type hx;
702  Type yx; Type yy; Type yz; Type hy;
703  Type zx; Type zy; Type zz; Type hz;
704  Type tx; Type ty; Type tz; Type ht;
705  };
706 #if defined(tb_visual_cpp)
707 #pragma warning(pop)
708 #endif
709  };
710 
714  inline TypedMatrix4(void) :
715  mComponents{
716  Type(1), Type(0), Type(0), Type(0),
717  Type(0), Type(1), Type(0), Type(0),
718  Type(0), Type(0), Type(1), Type(0),
719  Type(0), Type(0), Type(0), Type(1) }
720  {
721  }
722 
726  inline explicit TypedMatrix4(
727  Type f11, Type f21, Type f31, Type f41,
728  Type f12, Type f22, Type f32, Type f42,
729  Type f13, Type f23, Type f33, Type f43,
730  Type f14, Type f24, Type f34, Type f44) :
731  mComponents{
732  f11, f21, f31, f41,
733  f12, f22, f32, f42,
734  f13, f23, f33, f43,
735  f14, f24, f34, f44 }
736  {
737  }
738 
745  inline explicit TypedMatrix4(
746  Type f11, Type f21, Type f31, Type f41,
747  Type f12, Type f22, Type f32, Type f42,
748  Type f13, Type f23, Type f33, Type f43,
749  Type f14, Type f24, Type f34, Type f44, const ColumnMajorMatrix& columnMajor) :
750  mComponents{
751  f11, f12, f13, f14,
752  f21, f22, f23, f24,
753  f31, f32, f33, f34,
754  f41, f42, f43, f44 }
755  {
756  tb_unused(columnMajor);
757  }
758 
764  inline explicit TypedMatrix4(const Type* const componentArray) :
765  mComponents{
766  componentArray[0], componentArray[1], componentArray[2], componentArray[3],
767  componentArray[4], componentArray[5], componentArray[6], componentArray[7],
768  componentArray[8], componentArray[9], componentArray[10], componentArray[11],
769  componentArray[12], componentArray[13], componentArray[14], componentArray[15] }
770  {
771  }
772 
780  inline explicit TypedMatrix4(const Type* const componentArray, const ColumnMajorMatrix& columnMajor) :
781  mComponents{
782  componentArray[0], componentArray[4], componentArray[8], componentArray[12],
783  componentArray[1], componentArray[5], componentArray[9], componentArray[13],
784  componentArray[2], componentArray[6], componentArray[10], componentArray[14],
785  componentArray[3], componentArray[7], componentArray[11], componentArray[15] }
786  {
787  tb_unused(columnMajor);
788  }
789 
796 #if defined(tb_visual_cpp)
797 #pragma warning(push)
798 #pragma warning(disable: 26495)
799  inline explicit TypedMatrix4(const SkipInitialization& fastAndStupid)
800  {
801  tb_unused(fastAndStupid);
802  }
803 #pragma warning(pop)
804 #else
805  inline explicit TypedMatrix4(const SkipInitialization& fastAndStupid)
806  {
807  tb_unused(fastAndStupid);
808  }
809 #endif
810 
814  TypedMatrix4(const TypedMatrix4& other) = default;
815 
816  template<typename FromType> explicit TypedMatrix4(const TypedMatrix4<FromType>& other) :
817  mComponents{
818  static_cast<Type>(other.mComponents[0]), static_cast<Type>(other.mComponents[1]), static_cast<Type>(other.mComponents[2]), static_cast<Type>(other.mComponents[3]),
819  static_cast<Type>(other.mComponents[4]), static_cast<Type>(other.mComponents[5]), static_cast<Type>(other.mComponents[6]), static_cast<Type>(other.mComponents[7]),
820  static_cast<Type>(other.mComponents[8]), static_cast<Type>(other.mComponents[9]), static_cast<Type>(other.mComponents[10]), static_cast<Type>(other.mComponents[11]),
821  static_cast<Type>(other.mComponents[12]), static_cast<Type>(other.mComponents[13]), static_cast<Type>(other.mComponents[14]), static_cast<Type>(other.mComponents[15])
822  }
823  {
824  }
825 
826  ~TypedMatrix4(void) = default;
827 
831  TypedMatrix4& operator=(const TypedMatrix4& other) = default;
832 
843  inline bool operator==(const TypedMatrix4& other) const
844  {
845  for (size_t index(0); index < 16; ++index)
846  {
847  if (false == IsEqual(mComponents[index], other[index]))
848  {
849  return false;
850  }
851  }
852 
853  return true;
854  }
855 
861  inline bool operator!=(const TypedMatrix4& other) const
862  {
863  for (size_t index(0); index < 16; ++index)
864  {
865  if (false == IsEqual(mComponents[index], other[index]))
866  {
867  return true;
868  }
869  }
870 
871  return false;
872  }
873 
878  inline const Type& operator[](const int index) const { return mComponents[index]; }
879  inline const Type& operator[](const size_t& index) const { return mComponents[index]; }
880 
886  inline Type& operator[](const int index) { return mComponents[index]; }
887  inline Type& operator[](const size_t& index) { return mComponents[index]; }
888 
893  inline const Type& operator()(const size_t& column, const size_t& row) const { return mComponents[column + (row << 2)]; }
894 
900  inline Type& operator()(const size_t& column, const size_t& row) { return mComponents[column + (row << 2)]; }
901 
906  inline const Type& operator()(int column, int row) const { return mComponents[column + (row << 2)]; }
907 
913  inline Type& operator()(int column, int row) { return mComponents[column + (row << 2)]; }
914 
922  inline explicit operator Type* (void) { return mComponents; }
923 
927  inline explicit operator const Type* (void) const { return mComponents; }
928 
932  template<typename ToType> explicit operator TypedMatrix4<ToType>(void) const
933  {
934  return TypedMatrix4<ToType>(
935  static_cast<ToType>(mComponents[0]), static_cast<ToType>(mComponents[1]), static_cast<ToType>(mComponents[2]), static_cast<ToType>(mComponents[3]),
936  static_cast<ToType>(mComponents[4]), static_cast<ToType>(mComponents[5]), static_cast<ToType>(mComponents[6]), static_cast<ToType>(mComponents[7]),
937  static_cast<ToType>(mComponents[8]), static_cast<ToType>(mComponents[9]), static_cast<ToType>(mComponents[10]), static_cast<ToType>(mComponents[11]),
938  static_cast<ToType>(mComponents[12]), static_cast<ToType>(mComponents[13]), static_cast<ToType>(mComponents[14]), static_cast<ToType>(mComponents[15]));
939  }
940 
948  inline TypedVector3<Type> GetBasis(const size_t& basisIndex) const { return TypedVector3<Type>(&mComponents[basisIndex << 2]); }
949 
956  inline void SetBasis(const size_t& basisIndex, const TypedVector3<Type>& basis) { *((TypedVector3<Type>*) & mComponents[basisIndex << 2]) = basis; }
957 
966  inline void SetBasis(const size_t& basisIndex, Type basisX, Type basisY, Type basisZ)
967  {
968  mComponents[(basisIndex << 2) + 0] = basisX;
969  mComponents[(basisIndex << 2) + 1] = basisY;
970  mComponents[(basisIndex << 2) + 2] = basisZ;
971  }
972 
978  inline TypedVector3<Type> GetPosition(void) const
979  {
980  return TypedVector3<Type>(&mComponents[12]);
981  }
982 
987  inline void SetPosition(const TypedVector3<Type>& position)
988  {
989  (*this)(0, 3) = position.x;
990  (*this)(1, 3) = position.y;
991  (*this)(2, 3) = position.z;
992  }
993 
998  inline void SetPosition(const Type x, const Type y, const Type z)
999  {
1000  (*this)(0, 3) = x;
1001  (*this)(1, 3) = y;
1002  (*this)(2, 3) = z;
1003  }
1004 
1010  {
1011  TypedMatrix3<Type> orientation(kSkipInitialization);
1012  orientation.SetBasis(0, GetBasis(0).GetNormalized());
1013  orientation.SetBasis(1, GetBasis(1).GetNormalized());
1014  orientation.SetBasis(2, GetBasis(2).GetNormalized());
1015  return orientation;
1016  }
1017 
1022  inline void SetOrientation(const TypedMatrix3<Type>& orientation)
1023  {
1024  const TypedVector3<Type> scale = GetScale();
1025  SetBasis(0, orientation.GetBasis(0) * scale.x);
1026  SetBasis(1, orientation.GetBasis(1) * scale.y);
1027  SetBasis(2, orientation.GetBasis(2) * scale.z);
1028  }
1029 
1030  inline TypedVector3<Type> GetScale(void) const
1031  {
1032  return TypedVector3<Type>(GetBasis(0).Magnitude(), GetBasis(1).Magnitude(), GetBasis(2).Magnitude());
1033  }
1034 
1035  inline void SetScale(const TypedVector3<Type>& scale)
1036  {
1037  Vector3 basis;
1038 
1039  basis = GetBasis(0); basis.SetLength(scale.x); SetBasis(0, basis);
1040  basis = GetBasis(1); basis.SetLength(scale.y); SetBasis(1, basis);
1041  basis = GetBasis(2); basis.SetLength(scale.z); SetBasis(2, basis);
1042  }
1043 
1044  void Compose(const TypedVector3<Type>& position, const TypedMatrix3<Type>& orientation, const TypedVector3<Type>& scale)
1045  {
1046  SetPosition(position);
1047 
1048  SetBasis(0, orientation.GetBasis(0) * scale.x);
1049  SetBasis(1, orientation.GetBasis(1) * scale.y);
1050  SetBasis(2, orientation.GetBasis(2) * scale.z);
1051  }
1052 
1053  void Decompose(TypedVector3<Type>& position, TypedMatrix3<Type>& orientation, TypedVector3<Type>& scale) const
1054  {
1055  position = GetPosition();
1056 
1057  orientation.SetBasis(0, GetBasis(0).GetNormalized(scale.x));
1058  orientation.SetBasis(1, GetBasis(1).GetNormalized(scale.y));
1059  orientation.SetBasis(2, GetBasis(2).GetNormalized(scale.z));
1060  }
1061 
1062 #if defined(tb_with_math_operators)
1066  inline TypedMatrix4<Type> operator+(const TypedMatrix4<Type>& rightSide) const
1067  {
1068  const TypedMatrix4& leftSide(*this);
1069  return TypedMatrix4(
1070  leftSide(0, 0) + rightSide(0, 0), leftSide(1, 0) + rightSide(1, 0), leftSide(2, 0) + rightSide(2, 0), leftSide(3, 0) + rightSide(3, 0),
1071  leftSide(0, 1) + rightSide(0, 1), leftSide(1, 1) + rightSide(1, 1), leftSide(2, 1) + rightSide(2, 1), leftSide(3, 1) + rightSide(3, 1),
1072  leftSide(0, 2) + rightSide(0, 2), leftSide(1, 2) + rightSide(1, 2), leftSide(2, 2) + rightSide(2, 2), leftSide(3, 2) + rightSide(3, 2),
1073  leftSide(0, 3) + rightSide(0, 3), leftSide(1, 3) + rightSide(1, 3), leftSide(2, 3) + rightSide(2, 3), leftSide(3, 3) + rightSide(3, 3));
1074  }
1075 
1080  inline TypedMatrix4<Type>& operator+=(const TypedMatrix4<Type>& rightSide)
1081  {
1082  for (size_t index = 0; index < 16; ++index)
1083  {
1084  (*this)[index] += rightSide[index];
1085  }
1086  return *this;
1087  }
1088 
1092  inline TypedMatrix4<Type> operator-(const TypedMatrix4<Type>& rightSide) const
1093  {
1094  const TypedMatrix4<Type>& leftSide(*this);
1095  return TypedMatrix4<Type>(
1096  leftSide(0, 0) - rightSide(0, 0), leftSide(1, 0) - rightSide(1, 0), leftSide(2, 0) - rightSide(2, 0), leftSide(3, 0) - rightSide(3, 0),
1097  leftSide(0, 1) - rightSide(0, 1), leftSide(1, 1) - rightSide(1, 1), leftSide(2, 1) - rightSide(2, 1), leftSide(3, 1) - rightSide(3, 1),
1098  leftSide(0, 2) - rightSide(0, 2), leftSide(1, 2) - rightSide(1, 2), leftSide(2, 2) - rightSide(2, 2), leftSide(3, 2) - rightSide(3, 2),
1099  leftSide(0, 3) - rightSide(0, 3), leftSide(1, 3) - rightSide(1, 3), leftSide(2, 3) - rightSide(2, 3), leftSide(3, 3) - rightSide(3, 3));
1100  }
1101 
1105  inline TypedMatrix4<Type>& operator-=(const TypedMatrix4<Type>& rightSide)
1106  {
1107  for (size_t index = 0; index < 16; ++index)
1108  {
1109  (*this)[index] -= rightSide[index];
1110  }
1111  return *this;
1112  }
1113 
1117  inline TypedMatrix4 operator*(const TypedMatrix4& rightSide) const
1118  {
1119  TypedMatrix4 result;
1120  MatrixMultiply<Type>(&result, this, &rightSide);
1121  return result;
1122  }
1123 
1127  inline TypedMatrix4 operator*=(const TypedMatrix4& rightSide)
1128  {
1129  TypedMatrix4 leftSide = *this;
1130  MatrixMultiply(this, &leftSide, &rightSide);
1131  return *this;
1132  }
1133 
1137  inline TypedMatrix4 GetTransposed(void) const
1138  {
1139  TypedMatrix4 temp;
1140  const TypedMatrix4& self(*this);
1141  temp(0, 0) = self(0, 0); temp(0, 1) = self(1, 0); temp(0, 2) = self(2, 0); temp(0, 3) = self(3, 0);
1142  temp(1, 0) = self(0, 1); temp(1, 1) = self(1, 1); temp(1, 2) = self(2, 1); temp(1, 3) = self(3, 1);
1143  temp(2, 0) = self(0, 2); temp(2, 1) = self(1, 2); temp(2, 2) = self(2, 2); temp(2, 3) = self(3, 2);
1144  temp(3, 0) = self(0, 3); temp(3, 1) = self(1, 3); temp(3, 2) = self(2, 3); temp(3, 3) = self(3, 3);
1145  return temp;
1146  }
1147 
1153  inline TypedMatrix4 ComputeInverse(void) const
1154  {
1155  TypedMatrix4 result;
1156  MatrixComputeInverse(&result, this);
1157  return result;
1158  }
1159 
1166  inline TypedMatrix4 FastInverse(void) const
1167  {
1168  TypedMatrix4 result;
1169  MatrixFastInverse(&result, this);
1170  return result;
1171  }
1172 
1177  inline TypedVector3<Type> TransformCoordinate(const TypedVector3<Type>& inputVector) const
1178  {
1179  TypedVector3<Type> result;
1180  Vector3TransformCoordinate(&result, &inputVector, this);
1181  return result;
1182  }
1183 
1188  inline TypedVector3<Type> TransformNormal(const TypedVector3<Type>& inputVector) const
1189  {
1190  TypedVector3<Type> result;
1191  Vector3TransformNormal(&result, &inputVector, this);
1192  return result;
1193  }
1194 
1198  inline TypedVector4<Type> Transform(const TypedVector4<Type>& inputVector) const
1199  {
1200  TypedVector4<Type> result;
1201  Vector4MatrixMultiply(&result, &inputVector, this);
1202  return result;
1203  }
1204 
1205 #endif /* tb_with_math_operators */
1206  };
1207 
1208 #if defined(tb_with_math_operators)
1209 
1213  template<typename Type> TypedMatrix3<Type> operator*(const Type leftSide, const TypedMatrix3<Type>& rightSide)
1214  {
1215  TypedMatrix3<Type> result;
1216  MatrixMultiply(&result, &rightSide, leftSide);
1217  return result;
1218  }
1219 
1223  template<typename Type> TypedMatrix3<Type> operator*(const TypedMatrix3<Type>& leftSide, const Type rightSide)
1224  {
1225  TypedMatrix3<Type> result;
1226  MatrixMultiply(&result, &leftSide, rightSide);
1227  return result;
1228  }
1229 
1233  template<typename Type> TypedMatrix4<Type> operator*(const Type leftSide, const TypedMatrix4<Type>& rightSide)
1234  {
1235  TypedMatrix4<Type> result;
1236  MatrixMultiply(&result, &rightSide, leftSide);
1237  return result;
1238  }
1239 
1243  template<typename Type> TypedMatrix4<Type> operator*(const TypedMatrix4<Type>& leftSide, const Type rightSide)
1244  {
1245  TypedMatrix4<Type> result;
1246  MatrixMultiply(&result, &leftSide, rightSide);
1247  return result;
1248  }
1249 
1254  template<typename Type> TypedVector3<Type> operator*(const TypedVector3<Type>& leftSide, const TypedMatrix3<Type>& rightSide)
1255  {
1256  TypedVector3<Type> result;
1257  Vector3MatrixMultiply(&result, &leftSide, &rightSide);
1258  return result;
1259  }
1260 
1265  template<typename Type> TypedVector3<Type> operator*(const TypedMatrix3<Type>& leftSide, const TypedVector3<Type>& rightSide)
1266  {
1267  TypedVector3<Type> result;
1268  MatrixVector3Multiply(&result, &leftSide, &rightSide);
1269  return result;
1270  }
1271 
1276  template<typename Type> TypedVector4<Type> operator*(const TypedVector4<Type>& leftSide, const TypedMatrix4<Type>& rightSide)
1277  {
1278  TypedVector4<Type> result;
1279  Vector4MatrixMultiply(&result, &leftSide, &rightSide);
1280  return result;
1281  }
1282 
1287  template<typename Type> TypedVector4<Type> operator*(const TypedMatrix4<Type>& leftSide, const TypedVector4<Type>& rightSide)
1288  {
1289  TypedVector4<Type> result;
1290  MatrixVector4Multiply(&result, &leftSide, &rightSide);
1291  return result;
1292  }
1293 
1294 #endif /* tb_with_math_operators */
1295 
1299 
1306  {
1307  *result = TypedMatrix3<Type>::Identity();
1308  return result;
1309  }
1310 
1315  {
1316  *result = TypedMatrix4<Type>::Identity();
1317  return result;
1318  }
1319 
1330  const TypedVector3<Type>& eyePosition, const TypedVector3<Type>& targetPosition, const TypedVector3<Type>& unitUp)
1331  {
1332  tb_error_if(nullptr == result, "tbExternalError: Invalid parameter; Expected result to be valid pointer.");
1333 
1334  TypedVector3<Type> right, finalUp, forward;
1335  Vector3Subtract(&forward, &eyePosition, &targetPosition);
1336  Vector3Normalize(&forward, &forward);
1337 
1338 #if defined(tb_debug_build) //Going to refer to these as the Math Idiot proofing tests.
1339  tb_error_if(eyePosition == targetPosition, "tbExternalError: Invalid parameter; This would result in looking directly at eye position.");
1340  tb_error_if(fabsf(Vector3Magnitude(&unitUp) - 1.0f) > 0.00001f, "tbExternalError: Invalid unitUp, this is not a unit length vector.");
1341  tb_error_if(fabsf(Vector3DotProduct(&forward, &unitUp)) > 0.9999f, "tbExternalError: Invalid looking direction, parallel to unitUp.");
1342 #endif
1343 
1344  Vector3CrossProduct(&right, &unitUp, &forward);
1345  Vector3Normalize(&right, &right);
1346 
1347  Vector3CrossProduct(&finalUp, &forward, &right);
1348 
1349  //result->SetBasis(0, right);
1350  //result->SetBasis(1, finalUp);
1351  //result->SetBasis(2, forward);
1352  result->SetBasis(0, right.x, finalUp.x, forward.x);
1353  result->SetBasis(1, right.y, finalUp.y, forward.y);
1354  result->SetBasis(2, right.z, finalUp.z, forward.z);
1355 
1356  (*result)(0, 3) = -(eyePosition.x * (*result)(0, 0) + eyePosition.y * (*result)(0, 1) + eyePosition.z * (*result)(0, 2));
1357  (*result)(1, 3) = -(eyePosition.x * (*result)(1, 0) + eyePosition.y * (*result)(1, 1) + eyePosition.z * (*result)(1, 2));
1358  (*result)(2, 3) = -(eyePosition.x * (*result)(2, 0) + eyePosition.y * (*result)(2, 1) + eyePosition.z * (*result)(2, 2));
1359 
1360  return result;
1361  }
1362 
1369  template<typename Type> TypedMatrix4<Type>* MatrixCreateTranslation(TypedMatrix4<Type>* result, const TypedVector3<Type>* translation)
1370  { //Changed September 19, 2010, changed back March 22nd, 2018, changed again (to bottom row) May 9th 2018
1371  MatrixCreateIdentity(result);
1372  (*result)(0, 3) = translation->x;
1373  (*result)(1, 3) = translation->y;
1374  (*result)(2, 3) = translation->z;
1375  return result;
1376  }
1377 
1388  const Type translationX, const Type translationY, const Type translationZ)
1389  { //Changed September 19, 2010, changed back March 22nd, 2018, changed again (to bottom row) May 9th 2018
1390  MatrixCreateIdentity(result);
1391  (*result)(0, 3) = translationX;
1392  (*result)(1, 3) = translationY;
1393  (*result)(2, 3) = translationZ;
1394  return result;
1395  }
1396 
1404  template<typename Type> TypedMatrix3<Type>* MatrixCreateScale(TypedMatrix3<Type>* result, const TypedVector3<Type>* scale)
1405  {
1406  memset(result->mComponents, 0, sizeof(Type) * 9);
1407  (*result)(0, 0) = scale->x;
1408  (*result)(1, 1) = scale->y;
1409  (*result)(2, 2) = scale->z;
1410  return result;
1411  }
1412 
1416  template<typename Type> TypedMatrix4<Type>* MatrixCreateScale(TypedMatrix4<Type>* result, const TypedVector3<Type>* scale)
1417  {
1418  memset(result->mComponents, 0, sizeof(Type) << 4);
1419  (*result)(0, 0) = scale->x;
1420  (*result)(1, 1) = scale->y;
1421  (*result)(2, 2) = scale->z;
1422  (*result)(3, 3) = 1.0f;
1423  return result;
1424  }
1425 
1435  template<typename Type> TypedMatrix3<Type>* MatrixCreateScale(TypedMatrix3<Type>* result,
1436  const Type scaleX, const Type scaleY, const Type scaleZ)
1437  {
1438  memset(result->mComponents, 0, sizeof(Type) * 9);
1439  (*result)(0, 0) = scaleX;
1440  (*result)(1, 1) = scaleY;
1441  (*result)(2, 2) = scaleZ;
1442  return result;
1443  }
1444 
1448  template<typename Type> TypedMatrix4<Type>* MatrixCreateScale(TypedMatrix4<Type>* result,
1449  const Type scaleX, const Type scaleY, const Type scaleZ)
1450  {
1451  memset(result->mComponents, 0, sizeof(Type) << 4);
1452  (*result)(0, 0) = scaleX;
1453  (*result)(1, 1) = scaleY;
1454  (*result)(2, 2) = scaleZ;
1455  (*result)(3, 3) = 1.0f;
1456  return result;
1457  }
1458 
1467  {
1468  MatrixCreateIdentity(result);
1469  const Type sinOfRotation = std::sin(rotation.AsRadians());
1470  const Type cosOfRotation = std::cos(rotation.AsRadians());
1471  (*result)(1, 1) = cosOfRotation;
1472  (*result)(2, 1) = sinOfRotation;
1473  (*result)(1, 2) = -sinOfRotation;
1474  (*result)(2, 2) = cosOfRotation;
1475  return result;
1476  }
1477 
1482  {
1483  MatrixCreateIdentity(result);
1484  const Type sinOfRotation = std::sin(rotation.AsRadians());
1485  const Type cosOfRotation = std::cos(rotation.AsRadians());
1486  (*result)(1, 1) = cosOfRotation;
1487  (*result)(2, 1) = sinOfRotation;
1488  (*result)(1, 2) = -sinOfRotation;
1489  (*result)(2, 2) = cosOfRotation;
1490  return result;
1491  }
1492 
1501  {
1502  MatrixCreateIdentity(result);
1503  const Type sinOfRotation = std::sin(rotation.AsRadians());
1504  const Type cosOfRotation = std::cos(rotation.AsRadians());
1505  (*result)(0, 0) = cosOfRotation;
1506  (*result)(2, 0) = -sinOfRotation;
1507  (*result)(0, 2) = sinOfRotation;
1508  (*result)(2, 2) = cosOfRotation;
1509  return result;
1510  }
1511 
1516  {
1517  MatrixCreateIdentity(result);
1518  const Type sinOfRotation = std::sin(rotation.AsRadians());
1519  const Type cosOfRotation = std::cos(rotation.AsRadians());
1520  (*result)(0, 0) = cosOfRotation;
1521  (*result)(2, 0) = -sinOfRotation;
1522  (*result)(0, 2) = sinOfRotation;
1523  (*result)(2, 2) = cosOfRotation;
1524  return result;
1525  }
1526 
1535  {
1536  MatrixCreateIdentity(result);
1537  const Type sinOfRotation = std::sin(rotation.AsRadians());
1538  const Type cosOfRotation = std::cos(rotation.AsRadians());
1539  (*result)(0, 0) = cosOfRotation;
1540  (*result)(1, 0) = sinOfRotation;
1541  (*result)(0, 1) = -sinOfRotation;
1542  (*result)(1, 1) = cosOfRotation;
1543  return result;
1544  }
1545 
1550  {
1551  MatrixCreateIdentity(result);
1552  const Type sinOfRotation = std::sin(rotation.AsRadians());
1553  const Type cosOfRotation = std::cos(rotation.AsRadians());
1554  (*result)(0, 0) = cosOfRotation;
1555  (*result)(1, 0) = sinOfRotation;
1556  (*result)(0, 1) = -sinOfRotation;
1557  (*result)(1, 1) = cosOfRotation;
1558  return result;
1559  }
1560 
1570  const TypedVector3<Type>* rotationAxis, const tbMath::TypedAngle<Type> rotation)
1571  {
1572  const Type s = -std::sin(rotation.AsRadians());
1573  const Type c = std::cos(rotation.AsRadians());
1574  const Type t = 1.0f - c;
1575 
1576  const auto av = rotationAxis->GetNormalized();
1577  const auto tv = TypedVector3<Type>(av * t);
1578  const auto sv = TypedVector3<Type>(av * s);
1579 
1580  (*result)(0, 0) = c + tv.x * av.x;
1581  (*result)(0, 1) = tv.x * av.y + sv.z;
1582  (*result)(0, 2) = tv.x * av.z - sv.y;
1583 
1584  (*result)(1, 0) = tv.y * av.x - sv.z;
1585  (*result)(1, 1) = c + tv.y * av.y;
1586  (*result)(1, 2) = tv.y * av.z + sv.x;
1587 
1588  (*result)(2, 0) = tv.z * av.x + sv.y;
1589  (*result)(2, 1) = tv.z * av.y - sv.x;
1590  (*result)(2, 2) = c + tv.z * av.z;
1591 
1592  return result;
1593  }
1594 
1599  const TypedVector3<Type>* rotationAxis, const tbMath::TypedAngle<Type> rotation)
1600  {
1601  const Type s = -std::sin(rotation.AsRadians());
1602  const Type c = std::cos(rotation.AsRadians());
1603  const Type t = 1.0f - c;
1604 
1605  const auto av = rotationAxis->GetNormalized();
1606  const auto tv = TypedVector3<Type>(av * t);
1607  const auto sv = TypedVector3<Type>(av * s);
1608 
1609  (*result)(0, 0) = c + tv.x * av.x;
1610  (*result)(0, 1) = tv.x * av.y + sv.z;
1611  (*result)(0, 2) = tv.x * av.z - sv.y;
1612  (*result)(0, 3) = 0.0f;
1613 
1614  (*result)(1, 0) = tv.y * av.x - sv.z;
1615  (*result)(1, 1) = c + tv.y * av.y;
1616  (*result)(1, 2) = tv.y * av.z + sv.x;
1617  (*result)(1, 3) = 0.0f;
1618 
1619  (*result)(2, 0) = tv.z * av.x + sv.y;
1620  (*result)(2, 1) = tv.z * av.y - sv.x;
1621  (*result)(2, 2) = c + tv.z * av.z;
1622  (*result)(2, 3) = 0.0f;
1623 
1624  (*result)(3, 0) = 0.0f;
1625  (*result)(3, 1) = 0.0f;
1626  (*result)(3, 2) = 0.0f;
1627  (*result)(3, 3) = 1.0f;
1628 
1629  return result;
1630  }
1631 
1644  inline Matrix4* MatrixCreatePerspectiveRH(Matrix4* result, const float fieldOfView, const float aspectRatio,
1645  const float nearPlane, const float farPlane)
1646  {
1647  memset(result->mComponents, 0, sizeof(float) << 4);
1648 
1649  //From GLM, https://pastebin.com/Gen40yLY except flipped for row-major.
1650  //Remember that GLM accesses Y, X (row, column)...
1651  const float t = tan(fieldOfView / 2.0f);
1652  (*result)(0, 0) = 1.0f / (aspectRatio * t);
1653  (*result)(1, 1) = 1.0f / t;
1654  (*result)(2, 2) = -(farPlane + nearPlane) / (farPlane - nearPlane);
1655  (*result)(3, 2) = -1.0f;
1656  (*result)(2, 3) = -(2.0f * farPlane * nearPlane) / (farPlane - nearPlane);
1657 
1658  return result;
1659  }
1660 
1673  inline Matrix4* MatrixCreatePerspectiveLH(Matrix4* result, const float fieldOfView, const float aspectRatio,
1674  const float nearPlane, const float farPlane)
1675  {
1676  memset(result->mComponents, 0, sizeof(float) << 4);
1677 
1678  //From GLM, https://pastebin.com/Gen40yLY except flipped for row-major.
1679  //Remember that GLM accesses Y, X (row, column)...
1680  const float t = tan(fieldOfView / 2.0f);
1681  (*result)(0, 0) = 1.0f / (aspectRatio * t);
1682  (*result)(1, 1) = 1.0f / t;
1683  (*result)(2, 2) = (farPlane + nearPlane) / (farPlane - nearPlane);
1684  (*result)(3, 2) = 1.0f;
1685  (*result)(2, 3) = -(2.0f * farPlane * nearPlane) / (farPlane - nearPlane);
1686 
1687  return result;
1688  }
1689 
1705  inline Matrix4* MatrixCreateOrthoRH(Matrix4* result, const float left, const float right,
1706  const float top, const float bottom, const float nearPlane, const float farPlane)
1707  {
1708  tbMath::Matrix4& output(*result);
1709  memset(result->mComponents, 0, sizeof(float) << 4);
1710 
1711  output(0, 0) = 2.0f / (right - left);
1712  output(1, 1) = 2.0f / (top - bottom);
1713  output(2, 2) = -2.0f / (farPlane - nearPlane);
1714  output(3, 3) = 1.0f;
1715  output(0, 3) = -(right + left) / (right - left);
1716  output(1, 3) = -(top + bottom) / (top - bottom);
1717  output(2, 3) = -((farPlane + nearPlane) / (farPlane - nearPlane));
1718 
1719  return result;
1720  }
1721 
1737  inline Matrix4* MatrixCreateOrthoLH(Matrix4* result, const float left, const float right,
1738  const float top, const float bottom, const float nearPlane, const float farPlane)
1739  {
1740  tbMath::Matrix4& output(*result);
1741  memset(result->mComponents, 0, sizeof(float) << 4);
1742 
1743  output(0, 0) = 2.0f / (right - left);
1744  output(1, 1) = 2.0f / (top - bottom);
1745  output(2, 2) = 2.0f / (farPlane - nearPlane);
1746  output(3, 3) = 1.0f;
1747  output(0, 3) = -(right + left) / (right - left);
1748  output(1, 3) = -(top + bottom) / (top - bottom);
1749  output(2, 3) = -(farPlane + nearPlane) / (farPlane - nearPlane);
1750 
1751  return result;
1752  }
1753 
1761  inline Matrix3* MatrixAdd(Matrix3* result, const Matrix3* leftSide, const Matrix3* rightSide)
1762  {
1763  float *r = result->mComponents;
1764  const float *m1 = leftSide->mComponents;
1765  const float *m2 = rightSide->mComponents;
1766 
1767  r[0] = m1[0] + m2[0]; r[1] = m1[1] + m2[1]; r[2] = m1[2] + m2[2];
1768  r[3] = m1[3] + m2[3]; r[4] = m1[4] + m2[4]; r[5] = m1[5] + m2[5];
1769  r[6] = m1[6] + m2[6]; r[7] = m1[7] + m2[7]; r[8] = m1[8] + m2[8];
1770  return result;
1771  }
1772 
1776  inline Matrix4* MatrixAdd(Matrix4* result, const Matrix4* leftSide, const Matrix4* rightSide)
1777  {
1778  float *r = result->mComponents;
1779  const float *m1 = leftSide->mComponents;
1780  const float *m2 = rightSide->mComponents;
1781 
1782  r[0] = m1[0] + m2[0]; r[1] = m1[1] + m2[1]; r[2] = m1[2] + m2[2]; r[3] = m1[3] + m2[3];
1783  r[4] = m1[4] + m2[4]; r[5] = m1[5] + m2[5]; r[6] = m1[6] + m2[6]; r[7] = m1[7] + m2[7];
1784  r[8] = m1[8] + m2[8]; r[9] = m1[9] + m2[9]; r[10] = m1[10] + m2[10]; r[11] = m1[11] + m2[11];
1785  r[12] = m1[12] + m2[12]; r[13] = m1[13] + m2[13]; r[14] = m1[14] + m2[14]; r[15] = m1[15] + m2[15];
1786  return result;
1787  }
1788 
1796 
1797  inline Matrix3* MatrixSubtract(Matrix3* result, const Matrix3* leftSide, const Matrix3* rightSide)
1798  {
1799  float *r = result->mComponents;
1800  const float *m1 = leftSide->mComponents;
1801  const float *m2 = rightSide->mComponents;
1802 
1803  r[0] = m1[0] - m2[0]; r[1] = m1[1] - m2[1]; r[2] = m1[2] - m2[2];
1804  r[3] = m1[3] - m2[3]; r[4] = m1[4] - m2[4]; r[5] = m1[5] - m2[5];
1805  r[6] = m1[6] - m2[6]; r[7] = m1[7] - m2[7]; r[8] = m1[8] - m2[8];
1806  return result;
1807  }
1808 
1812  inline Matrix4* MatrixSubtract(Matrix4* result, const Matrix4* leftSide, const Matrix4* rightSide)
1813  {
1814  float *r = result->mComponents;
1815  const float *m1 = leftSide->mComponents;
1816  const float *m2 = rightSide->mComponents;
1817 
1818  r[0] = m1[0] - m2[0]; r[1] = m1[1] - m2[1]; r[2] = m1[2] - m2[2]; r[3] = m1[3] - m2[3];
1819  r[4] = m1[4] - m2[4]; r[5] = m1[5] - m2[5]; r[6] = m1[6] - m2[6]; r[7] = m1[7] - m2[7];
1820  r[8] = m1[8] - m2[8]; r[9] = m1[9] - m2[9]; r[10] = m1[10] - m2[10]; r[11] = m1[11] - m2[11];
1821  r[12] = m1[12] - m2[12]; r[13] = m1[13] - m2[13]; r[14] = m1[14] - m2[14]; r[15] = m1[15] - m2[15];
1822  return result;
1823  }
1824 
1831  inline Matrix3* MatrixTranspose(Matrix3* result, const Matrix3* input)
1832  {
1833  tb_error_if(result == input, "tbExternalError: Invalid parameter; expected result to be different than input");
1834 
1835  Matrix3& a(*result);
1836  const Matrix3& b(*input);
1837  a(0, 0) = b(0, 0); a(0, 1) = b(1, 0); a(0, 2) = b(2, 0);
1838  a(1, 0) = b(0, 1); a(1, 1) = b(1, 1); a(1, 2) = b(2, 1);
1839  a(2, 0) = b(0, 2); a(2, 1) = b(1, 2); a(2, 2) = b(2, 2);
1840  return result;
1841  }
1842 
1849  inline Matrix4* MatrixTranspose(Matrix4* result, const Matrix4* input)
1850  {
1851  tb_error_if(result == input, "tbExternalError: Invalid parameter; expected result to be different than input");
1852 
1853  Matrix4& a(*result);
1854  const Matrix4& b(*input);
1855  a(0, 0) = b(0, 0); a(0, 1) = b(1, 0); a(0, 2) = b(2, 0); a(0, 3) = b(3, 0);
1856  a(1, 0) = b(0, 1); a(1, 1) = b(1, 1); a(1, 2) = b(2, 1); a(1, 3) = b(3, 1);
1857  a(2, 0) = b(0, 2); a(2, 1) = b(1, 2); a(2, 2) = b(2, 2); a(2, 3) = b(3, 2);
1858  a(3, 0) = b(0, 3); a(3, 1) = b(1, 3); a(3, 2) = b(2, 3); a(3, 3) = b(3, 3);
1859  return result;
1860  }
1861 
1872  template<typename Type> TypedMatrix3<Type>* MatrixMultiply(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* leftSide,
1873  const TypedMatrix3<Type>* rightSide)
1874  {
1875  tb_error_if(result == leftSide || result == rightSide, "tbExternalError: Invalid parameter; expected result to be different than leftSide and rightSide");
1876 
1877  const TypedMatrix3<Type>& a = *leftSide;
1878  const TypedMatrix3<Type>& b = *rightSide;
1879 
1880  (*result)(0, 0) = a(0, 0) * b(0, 0) + a(1, 0) * b(0, 1) + a(2, 0) * b(0, 2);
1881  (*result)(1, 0) = a(0, 0) * b(1, 0) + a(1, 0) * b(1, 1) + a(2, 0) * b(1, 2);
1882  (*result)(2, 0) = a(0, 0) * b(2, 0) + a(1, 0) * b(2, 1) + a(2, 0) * b(2, 2);
1883  (*result)(0, 1) = a(0, 1) * b(0, 0) + a(1, 1) * b(0, 1) + a(2, 1) * b(0, 2);
1884  (*result)(1, 1) = a(0, 1) * b(1, 0) + a(1, 1) * b(1, 1) + a(2, 1) * b(1, 2);
1885  (*result)(2, 1) = a(0, 1) * b(2, 0) + a(1, 1) * b(2, 1) + a(2, 1) * b(2, 2);
1886  (*result)(0, 2) = a(0, 2) * b(0, 0) + a(1, 2) * b(0, 1) + a(2, 2) * b(0, 2);
1887  (*result)(1, 2) = a(0, 2) * b(1, 0) + a(1, 2) * b(1, 1) + a(2, 2) * b(1, 2);
1888  (*result)(2, 2) = a(0, 2) * b(2, 0) + a(1, 2) * b(2, 1) + a(2, 2) * b(2, 2);
1889 
1890  return result;
1891  }
1892 
1896  template<typename Type> TypedMatrix4<Type>* MatrixMultiply(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* leftSide,
1897  const TypedMatrix4<Type>* rightSide)
1898  {
1899  tb_error_if(result == leftSide || result == rightSide, "tbExternalError: Invalid parameter; expected result to be different than leftSide and rightSide");
1900 
1901  const TypedMatrix4<Type>& a = *leftSide;
1902  const TypedMatrix4<Type>& b = *rightSide;
1903 
1904  (*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);
1905  (*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);
1906  (*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);
1907  (*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);
1908  (*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);
1909  (*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);
1910  (*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);
1911  (*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);
1912  (*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);
1913  (*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);
1914  (*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);
1915  (*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);
1916  (*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);
1917  (*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);
1918  (*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);
1919  (*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);
1920 
1921  return result;
1922  }
1923 
1933  template<typename Type> TypedMatrix3<Type>* MatrixMultiply(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* input, const Type& scalar)
1934  {
1935  Type* resultComponents = result->mComponents;
1936  const Type* inputComponents = input->mComponents;
1937  for (size_t index = 0; index < 9; ++index)
1938  {
1939  resultComponents[index] = inputComponents[index] * scalar;
1940  }
1941  return result;
1942  }
1943 
1953  template<typename Type> TypedMatrix4<Type>* MatrixMultiply(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* input, const Type& scalar)
1954  {
1955  Type* resultComponents = result->mComponents;
1956  const Type* inputComponents = input->mComponents;
1957  for (size_t index = 0; index < 16; ++index)
1958  {
1959  resultComponents[index] = inputComponents[index] * scalar;
1960  }
1961  return result;
1962  }
1963 
1976  const TypedMatrix3<Type>* inputMatrix, const TypedVector3<Type>* inputVector)
1977  {
1978  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
1979  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(1, 0)) + (inputVector->z * (*inputMatrix)(2, 0));
1980  result->y = (inputVector->x * (*inputMatrix)(0, 1)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(2, 1));
1981  result->z = (inputVector->x * (*inputMatrix)(0, 2)) + (inputVector->y * (*inputMatrix)(1, 2)) + (inputVector->z * (*inputMatrix)(2, 2));
1982  return result;
1983  }
1984 
1997  const TypedVector3<Type>* inputVector, const TypedMatrix3<Type>* inputMatrix)
1998  {
1999  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
2000  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(0, 1)) + (inputVector->z * (*inputMatrix)(0, 2));
2001  result->y = (inputVector->x * (*inputMatrix)(1, 0)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(1, 2));
2002  result->z = (inputVector->x * (*inputMatrix)(2, 0)) + (inputVector->y * (*inputMatrix)(2, 1)) + (inputVector->z * (*inputMatrix)(2, 2));
2003  return result;
2004  }
2005 
2018  const TypedMatrix4<Type>* inputMatrix, const TypedVector4<Type>* inputVector)
2019  {
2020  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
2021  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(1, 0)) + (inputVector->z * (*inputMatrix)(2, 0)) + (inputVector->w * (*inputMatrix)(3, 0));
2022  result->y = (inputVector->x * (*inputMatrix)(0, 1)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(2, 1)) + (inputVector->w * (*inputMatrix)(3, 1));
2023  result->z = (inputVector->x * (*inputMatrix)(0, 2)) + (inputVector->y * (*inputMatrix)(1, 2)) + (inputVector->z * (*inputMatrix)(2, 2)) + (inputVector->w * (*inputMatrix)(3, 2));
2024  result->w = (inputVector->x * (*inputMatrix)(0, 3)) + (inputVector->y * (*inputMatrix)(1, 3)) + (inputVector->z * (*inputMatrix)(2, 3)) + (inputVector->w * (*inputMatrix)(3, 3));
2025  return result;
2026  }
2027 
2040  const TypedVector4<Type>* inputVector, const TypedMatrix4<Type>* inputMatrix)
2041  {
2042  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector.");
2043  result->x = (inputVector->x * (*inputMatrix)(0, 0)) + (inputVector->y * (*inputMatrix)(0, 1)) + (inputVector->z * (*inputMatrix)(0, 2)) + (inputVector->w * (*inputMatrix)(0, 3));
2044  result->y = (inputVector->x * (*inputMatrix)(1, 0)) + (inputVector->y * (*inputMatrix)(1, 1)) + (inputVector->z * (*inputMatrix)(1, 2)) + (inputVector->w * (*inputMatrix)(1, 3));
2045  result->z = (inputVector->x * (*inputMatrix)(2, 0)) + (inputVector->y * (*inputMatrix)(2, 1)) + (inputVector->z * (*inputMatrix)(2, 2)) + (inputVector->w * (*inputMatrix)(2, 3));
2046  result->w = (inputVector->x * (*inputMatrix)(3, 0)) + (inputVector->y * (*inputMatrix)(3, 1)) + (inputVector->z * (*inputMatrix)(3, 2)) + (inputVector->w * (*inputMatrix)(3, 3));
2047  return result;
2048  }
2049 
2065  const TypedVector3<Type>* inputVector, const TypedMatrix4<Type>* inputMatrix)
2066  {
2067  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector");
2068 
2069  const TypedMatrix4<Type>& matrix(*inputMatrix);
2070  result->x = (inputVector->x * matrix(0, 0)) + (inputVector->y * matrix(0, 1)) + (inputVector->z * matrix(0, 2)) + matrix(0, 3);
2071  result->y = (inputVector->x * matrix(1, 0)) + (inputVector->y * matrix(1, 1)) + (inputVector->z * matrix(1, 2)) + matrix(1, 3);
2072  result->z = (inputVector->x * matrix(2, 0)) + (inputVector->y * matrix(2, 1)) + (inputVector->z * matrix(2, 2)) + matrix(2, 3);
2073  return result;
2074  }
2075 
2088  const TypedVector3<Type>* inputVector, const TypedMatrix4<Type>* inputMatrix)
2089  {
2090  tb_error_if(result == inputVector, "tbExternalError: Invalid parameter; expected result to be different than inputVector");
2091 
2092  const TypedMatrix4<Type>& matrix(*inputMatrix);
2093  result->x = (inputVector->x * matrix(0, 0)) + (inputVector->y * matrix(0, 1)) + (inputVector->z * matrix(0, 2));
2094  result->y = (inputVector->x * matrix(1, 0)) + (inputVector->y * matrix(1, 1)) + (inputVector->z * matrix(1, 2));
2095  result->z = (inputVector->x * matrix(2, 0)) + (inputVector->y * matrix(2, 1)) + (inputVector->z * matrix(2, 2));
2096  return result;
2097  }
2098 
2099  template<typename Type> Type Matrix2x2Determinant(const Type f11, const Type f12, const Type f21, const Type f22)
2100  {
2101  return f11 * f22 - f12 * f21;
2102  }
2103 
2108  template<typename Type> Type Matrix3x3Determinant(const Type f11, const Type f12, const Type f13,
2109  const Type f21, const Type f22, const Type f23, const Type f31, const Type f32, const Type f33)
2110  {
2111  return f11 * (f22 * f33 - f32 * f23) - f12 * (f21 * f33 - f31 * f23) + f13 * (f21 * f32 - f31 * f22);
2112  }
2113 
2118  template<typename Type> Type MatrixDeterminant(const TypedMatrix3<Type>* input)
2119  {
2120  const TypedMatrix3<Type>& m(*input);
2121  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));
2122  }
2123 
2128  template<typename Type> Type MatrixDeterminant(const TypedMatrix4<Type>* input)
2129  {
2130  const TypedMatrix4<Type>& m(*input);
2131  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))) -
2132  (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))) +
2133  (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))) -
2134  (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)));
2135  }
2136 
2140  template<typename Type> TypedMatrix3<Type>* MatrixComputeInverse(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* input)
2141  {
2142  //tb_error("This is not yet implemented in full, use the FastInverse which requires certain ... matrices.");
2143 
2144  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
2145  const Type determinant = MatrixDeterminant(input);
2146  if (true == tbMath::IsZero(determinant))
2147  {
2148  *result = *input;
2149  return result;
2150  }
2151 
2152  const Type inverseDeterminant = 1.0f / determinant;
2153 
2154  const TypedMatrix3<Type>& m(*input);
2155  (*result)(0, 0) = Matrix2x2Determinant(m(1, 1), m(1, 2), m(2, 1), m(2, 2)) * inverseDeterminant;
2156  (*result)(1, 0) = -Matrix2x2Determinant(m(1, 0), m(1, 2), m(2, 0), m(2, 2)) * inverseDeterminant;
2157  (*result)(2, 0) = Matrix2x2Determinant(m(1, 0), m(1, 1), m(2, 0), m(2, 1)) * inverseDeterminant;
2158  (*result)(0, 1) = -Matrix2x2Determinant(m(0, 1), m(0, 2), m(2, 1), m(2, 2)) * inverseDeterminant;
2159  (*result)(1, 1) = Matrix2x2Determinant(m(0, 0), m(0, 2), m(2, 0), m(2, 2)) * inverseDeterminant;
2160  (*result)(2, 1) = -Matrix2x2Determinant(m(0, 0), m(0, 1), m(2, 0), m(2, 1)) * inverseDeterminant;
2161  (*result)(0, 2) = Matrix2x2Determinant(m(0, 1), m(0, 2), m(1, 1), m(1, 2)) * inverseDeterminant;
2162  (*result)(1, 2) = -Matrix2x2Determinant(m(0, 0), m(0, 2), m(1, 0), m(1, 2)) * inverseDeterminant;
2163  (*result)(2, 2) = Matrix2x2Determinant(m(0, 0), m(0, 1), m(1, 0), m(1, 1)) * inverseDeterminant;
2164  return result;
2165  }
2166 
2178  template<typename Type> TypedMatrix4<Type>* MatrixComputeInverse(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* input)
2179  {
2180  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
2181  const Type determinant = MatrixDeterminant(input);
2182  if (true == tbMath::IsZero(determinant))
2183  {
2184  *result = *input;
2185  return result;
2186  }
2187 
2188  const Type inverseDeterminant = 1.0f / determinant;
2189  const TypedMatrix4<Type>& m(*input);
2190  (*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;
2191  (*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;
2192  (*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;
2193  (*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;
2194  (*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;
2195  (*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;
2196  (*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;
2197  (*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;
2198  (*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;
2199  (*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;
2200  (*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;
2201  (*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;
2202  (*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;
2203  (*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;
2204  (*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;
2205  (*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;
2206  return result;
2207  }
2208 
2217  template<typename Type> TypedMatrix3<Type>* MatrixFastInverse(TypedMatrix3<Type>* result, const TypedMatrix3<Type>* input)
2218  {
2219  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
2220 
2221  (*result)(0, 0) = (*input)(0, 0); //Diagonal is equal
2222  (*result)(1, 1) = (*input)(1, 1);
2223  (*result)(2, 2) = (*input)(2, 2);
2224 
2225  (*result)(1, 0) = (*input)(0, 1); //Rotation is transposed
2226  (*result)(2, 0) = (*input)(0, 2);
2227  (*result)(0, 1) = (*input)(1, 0);
2228  (*result)(2, 1) = (*input)(1, 2);
2229  (*result)(0, 2) = (*input)(2, 0);
2230  (*result)(1, 2) = (*input)(2, 1);
2231 
2232  return result;
2233  }
2234 
2250  template<typename Type> TypedMatrix4<Type>* MatrixFastInverse(TypedMatrix4<Type>* result, const TypedMatrix4<Type>* input)
2251  {
2252  tb_error_if(result == input, "tbExternalError: Invalid parameter, expected result to be different than input.");
2253 
2254  (*result)(0, 0) = (*input)(0, 0); //Diagonal is equal
2255  (*result)(1, 1) = (*input)(1, 1);
2256  (*result)(2, 2) = (*input)(2, 2);
2257  (*result)(3, 3) = (*input)(3, 3);
2258 
2259  (*result)(1, 0) = (*input)(0, 1); //Rotation is transposed
2260  (*result)(2, 0) = (*input)(0, 2);
2261  (*result)(0, 1) = (*input)(1, 0);
2262  (*result)(2, 1) = (*input)(1, 2);
2263  (*result)(0, 2) = (*input)(2, 0);
2264  (*result)(1, 2) = (*input)(2, 1);
2265 
2266  //This was the 'old' way that worked with translation in final COLUMN; it was a discrepency with where it
2267  //should have been; the test data changed 2020-11-26 and this will now succeed in the new way below. See
2268  //the comment at the very top of file for more information.
2269  //
2270  //const tbMath::Matrix4& inversed(*result); //Translation is multiplied by inversed 3x3, then negated.
2271  //(*result)(3, 0) = -((*input)(3, 0) * inversed(0, 0) + (*input)(3, 1) * inversed(1, 0) + (*input)(3, 2) * inversed(2, 0));
2272  //(*result)(3, 1) = -((*input)(3, 0) * inversed(0, 1) + (*input)(3, 1) * inversed(1, 1) + (*input)(3, 2) * inversed(2, 1));
2273  //(*result)(3, 2) = -((*input)(3, 0) * inversed(0, 2) + (*input)(3, 1) * inversed(1, 2) + (*input)(3, 2) * inversed(2, 2));
2274 
2275  //(*result)(0, 3) = 0.0f;
2276  //(*result)(1, 3) = 0.0f;
2277  //(*result)(2, 3) = 0.0f;
2278 
2279  const TypedMatrix4<Type>& inversed(*result); //Translation is multiplied by inversed 3x3, then negated.
2280  //(*result)(0, 3) = -((*input)(0, 3) * inversed(0, 0) + (*input)(1, 3) * inversed(0, 1) + (*input)(2, 3) * inversed(0, 2));
2281  //(*result)(1, 3) = -((*input)(0, 3) * inversed(1, 0) + (*input)(1, 3) * inversed(1, 1) + (*input)(2, 3) * inversed(1, 2));
2282  //(*result)(2, 3) = -((*input)(0, 3) * inversed(2, 0) + (*input)(1, 3) * inversed(2, 1) + (*input)(2, 3) * inversed(2, 2));
2283 
2284  //Negating Position then multipying by inversed 3x3...
2285  (*result)(0, 3) = (-(*input)(0, 3) * inversed(0, 0) + -(*input)(1, 3) * inversed(0, 1) + -(*input)(2, 3) * inversed(0, 2));
2286  (*result)(1, 3) = (-(*input)(0, 3) * inversed(1, 0) + -(*input)(1, 3) * inversed(1, 1) + -(*input)(2, 3) * inversed(1, 2));
2287  (*result)(2, 3) = (-(*input)(0, 3) * inversed(2, 0) + -(*input)(1, 3) * inversed(2, 1) + -(*input)(2, 3) * inversed(2, 2));
2288 
2289 
2290  (*result)(3, 0) = 0.0f;
2291  (*result)(3, 1) = 0.0f;
2292  (*result)(3, 2) = 0.0f;
2293 
2294  return result;
2295  }
2296 
2297  namespace Unstable
2298  {
2299  inline Matrix4 Translate(const Matrix4& originalMatrix, const Vector3& translation)
2300  {
2301  Matrix4 outputMatrix(kSkipInitialization);
2302  Matrix4 translationMatrix(kSkipInitialization);
2303 
2304  MatrixCreateTranslation(&translationMatrix, &translation);
2305  MatrixMultiply(&outputMatrix, &translationMatrix, &originalMatrix);
2306 
2307  return outputMatrix;
2308  }
2309 
2310  inline Matrix4 Translate(const Matrix4& originalMatrix, float x, float y, float z)
2311  {
2312  return Translate(originalMatrix, tbMath::Vector3(x, y, z));
2313  }
2314 
2318  inline Matrix4 TranslateLocal(const Matrix4& originalMatrix, const Vector3& translation)
2319  {
2320  Matrix4 outputMatrix(kSkipInitialization);
2321  Matrix4 translationMatrix(kSkipInitialization);
2322 
2323  MatrixCreateTranslation(&translationMatrix, &translation);
2324  MatrixMultiply(&outputMatrix, &originalMatrix, &translationMatrix);
2325 
2326  return outputMatrix;
2327  }
2328 
2329  inline Matrix4 TranslateLocal(const Matrix4& originalMatrix, float x, float y, float z)
2330  {
2331  return TranslateLocal(originalMatrix, tbMath::Vector3(x, y, z));
2332  }
2333 
2337  inline Matrix3 Rotate(const Matrix3& originalMatrix, const Vector3& aroundAxis, const tbMath::Angle angle)
2338  {
2339  Matrix3 outputMatrix(kSkipInitialization);
2340  Matrix3 rotationMatrix(kSkipInitialization);
2341 
2342  //TODO: TurtleBrains: MathKit: Consistency check, do we negate here. CW / CCW seems to depend on the
2343  //handedness of the world rather than the negation here.
2344  MatrixCreateRotationA(&rotationMatrix, &aroundAxis, angle);
2345  MatrixMultiply(&outputMatrix, &rotationMatrix, &originalMatrix);
2346 
2347  return outputMatrix;
2348  }
2349 
2350  inline Matrix3 Rotate(const size_t& axisIndex, const Matrix3& originalMatrix, const tbMath::Angle angle)
2351  {
2352  return Rotate(originalMatrix, originalMatrix.GetBasis(axisIndex), angle);
2353  }
2354 
2358  inline Matrix4 Rotate(const Matrix4& originalMatrix, const Vector3& aroundAxis, const tbMath::Angle angle)
2359  {
2360  Matrix4 outputMatrix(kSkipInitialization);
2361  Matrix4 rotationMatrix(kSkipInitialization);
2362 
2363  //TODO: TurtleBrains: MathKit: Consistency check, do we negate here. CW / CCW seems to depend on the
2364  //handedness of the world rather than the negation here.
2365  MatrixCreateRotationA(&rotationMatrix, &aroundAxis, angle);
2366  MatrixMultiply(&outputMatrix, &rotationMatrix, &originalMatrix);
2367 
2368  return outputMatrix;
2369  }
2370 
2371  inline Matrix4 Rotate(const size_t& axisIndex, const Matrix4& originalMatrix, const tbMath::Angle angle)
2372  {
2373  return Rotate(originalMatrix, originalMatrix.GetBasis(axisIndex), angle);
2374  }
2375 
2376  //TODO: TurtleBrains: MathKit: Does RotateWorldSpace make sense, it is a little odd because of: Translate vs TranslateLocal
2377  // and here is using Rotate vs RotateWorld. Consistency concerns.
2378  inline Matrix4 RotateWorldSpace(const size_t& axisIndex, const Matrix4& originalMatrix, const tbMath::Angle angle)
2379  {
2380  Matrix4 outputMatrix(kSkipInitialization);
2381  Matrix4 rotationMatrix(kSkipInitialization);
2382 
2383  //Negating here for positive rotationInDegrees to spin clockwise around the axis.
2384  //TODO: TurtleBrains: MathKit: Consistency check, do we negate here. CW / CCW seems to depend on the
2385  //handedness of the world rather than the negation here.
2386  const tbMath::Vector3 worldAxis(Matrix4::Identity().GetBasis(axisIndex));
2387  MatrixCreateRotationA(&rotationMatrix, &worldAxis, -angle);
2388  const Matrix4 rotationTransposed(rotationMatrix.GetTransposed());
2389  MatrixMultiply(&outputMatrix, &originalMatrix, &rotationTransposed);
2390 
2391  return outputMatrix;
2392  }
2393 
2394  inline Matrix3 Scale(const Matrix3& originalMatrix, const Vector3& scale)
2395  {
2396  Matrix3 outputMatrix(kSkipInitialization);
2397  Matrix3 scalingMatrix(kSkipInitialization);
2398 
2399  MatrixCreateScale(&scalingMatrix, &scale);
2400  MatrixMultiply(&outputMatrix, &scalingMatrix, &originalMatrix);
2401 
2402  return outputMatrix;
2403  }
2404 
2405  inline Matrix3 Scale(const Matrix3 originalMatrix, float x, float y, float z)
2406  {
2407  return Scale(originalMatrix, Vector3(x, y, z));
2408  }
2409 
2410  inline Matrix4 Scale(const Matrix4& originalMatrix, const Vector3& scale)
2411  {
2412  Matrix4 outputMatrix(kSkipInitialization);
2413  Matrix4 scalingMatrix(kSkipInitialization);
2414 
2415  MatrixCreateScale(&scalingMatrix, &scale);
2416  MatrixMultiply(&outputMatrix, &scalingMatrix, &originalMatrix);
2417 
2418  return outputMatrix;
2419  }
2420 
2421  inline Matrix4 Scale(const Matrix4& originalMatrix, float x, float y, float z)
2422  {
2423  return Scale(originalMatrix, Vector3(x, y, z));
2424  }
2425 
2426  }; /* namespace Unstable */
2427 
2428  template<typename Type> std::ostream& operator<<(std::ostream& output, const tbMath::TypedMatrix3<Type>& data)
2429  {
2430  output << "[ ";// << data.x << ", " << data.y << ", " << data.z << ", " << data.w << " }";
2431 
2432  for (int r = 0; r < 3; ++r)
2433  {
2434  output << "\n { ";
2435  for (int c = 0; c < 3; ++c)
2436  {
2437  output << data(c, r) << ((c < 2) ? ", " : "");
2438  }
2439 
2440  output << " }";
2441  }
2442 
2443  output << " ]";
2444 
2445  return output;
2446  }
2447 
2448  template<typename Type> std::istream& operator>>(std::istream& input, tbMath::TypedMatrix3<Type>& data)
2449  {
2450  String token;
2451  input >> token; //[
2452 
2453  for (int r = 0; r < 3; ++r)
2454  {
2455  input >> token; //{
2456  for (int c = 0; c < 3; ++c)
2457  {
2458  input >> token;
2459  data(c, r) = tbCore::FromString<Type>(token);
2460  }
2461 
2462  input >> token; //}
2463  }
2464 
2465  input >> token; //]
2466 
2467  return input;
2468  }
2469 
2470  template<typename Type> std::ostream& operator<<(std::ostream& output, const tbMath::TypedMatrix4<Type>& data)
2471  {
2472  output << "[ ";// << data.x << ", " << data.y << ", " << data.z << ", " << data.w << " }";
2473 
2474  for (int r = 0; r < 4; ++r)
2475  {
2476  output << "\n { ";
2477  for (int c = 0; c < 4; ++c)
2478  {
2479  output << data(c, r) << ((c < 3) ? ", " : "");
2480  }
2481 
2482  output << " }";
2483  }
2484 
2485  output << " ]";
2486 
2487  return output;
2488  }
2489 
2490  template<typename Type> std::istream& operator>>(std::istream& input, tbMath::TypedMatrix4<Type>& data)
2491  {
2492  String token;
2493  input >> token; //[
2494 
2495  for (int r = 0; r < 4; ++r)
2496  {
2497  input >> token; //{
2498  for (int c = 0; c < 4; ++c)
2499  {
2500  input >> token;
2501  data(c, r) = tbCore::FromString<Type>(token);
2502  }
2503 
2504  input >> token; //}
2505  }
2506 
2507  input >> token; //]
2508 
2509  return input;
2510  }
2511 
2512  }; /* namespace Math */
2513 }; /* namespace TurtleBrains */
2514 
2515 namespace tbMath = TurtleBrains::Math;
2516 
2517 #endif /* TurtleBrains_Matrix_hpp */
Definition: tb_angle.hpp:38
Type AsRadians(void) const
Definition: tb_angle.hpp:87
Definition: tb_matrix.hpp:156
TypedMatrix3 & operator=(const TypedMatrix3 &other)=default
void SetBasis(const size_t &basisIndex, const TypedVector3< Type > &basis)
Definition: tb_matrix.hpp:449
TypedMatrix3(const SkipInitialization &fastAndStupid)
Definition: tb_matrix.hpp:300
TypedMatrix3(const TypedMatrix3 &other)=default
TypedMatrix3(void)
Definition: tb_matrix.hpp:251
Type & operator()(int column, int row)
Definition: tb_matrix.hpp:407
static TypedMatrix3 Zero(void)
Definition: tb_matrix.hpp:161
static TypedMatrix3 Identity(void)
Definition: tb_matrix.hpp:173
TypedMatrix3(Type f11, Type f21, Type f31, Type f12, Type f22, Type f32, Type f13, Type f23, Type f33)
Definition: tb_matrix.hpp:262
bool operator!=(const TypedMatrix3 &other) const
Definition: tb_matrix.hpp:355
const Type & operator[](const int &index) const
Definition: tb_matrix.hpp:372
const Type & operator()(const size_t &column, const size_t &row) const
Definition: tb_matrix.hpp:387
void SetBasis(const size_t &basisIndex, Type basisX, Type basisY, Type basisZ)
Definition: tb_matrix.hpp:459
TypedMatrix3(const Type *const componentArray)
Definition: tb_matrix.hpp:277
Type & operator()(const size_t &column, const size_t &row)
Definition: tb_matrix.hpp:394
const TypedVector3< Type > GetBasis(const size_t &basisIndex) const
Definition: tb_matrix.hpp:441
const Type & operator()(int column, int row) const
Definition: tb_matrix.hpp:400
Type & operator[](const int &index)
Definition: tb_matrix.hpp:380
bool operator==(const TypedMatrix3 &other) const
Definition: tb_matrix.hpp:337
Definition: tb_matrix.hpp:596
const Type & operator[](const int index) const
Definition: tb_matrix.hpp:878
void SetPosition(const Type x, const Type y, const Type z)
Definition: tb_matrix.hpp:998
TypedMatrix4(Type f11, Type f21, Type f31, Type f41, Type f12, Type f22, Type f32, Type f42, Type f13, Type f23, Type f33, Type f43, Type f14, Type f24, Type f34, Type f44)
Definition: tb_matrix.hpp:726
TypedMatrix4(const Type *const componentArray)
Definition: tb_matrix.hpp:764
Type & operator()(int column, int row)
Definition: tb_matrix.hpp:913
void SetBasis(const size_t &basisIndex, Type basisX, Type basisY, Type basisZ)
Definition: tb_matrix.hpp:966
Type & operator[](const int index)
Definition: tb_matrix.hpp:886
TypedMatrix4 & operator=(const TypedMatrix4 &other)=default
TypedMatrix4(const TypedMatrix4 &other)=default
TypedVector3< Type > GetBasis(const size_t &basisIndex) const
Definition: tb_matrix.hpp:948
static TypedMatrix4 Zero(void)
Definition: tb_matrix.hpp:601
bool operator==(const TypedMatrix4 &other) const
Definition: tb_matrix.hpp:843
TypedMatrix3< Type > GetOrientation(void) const
Definition: tb_matrix.hpp:1009
TypedMatrix4(const Type *const componentArray, const ColumnMajorMatrix &columnMajor)
Definition: tb_matrix.hpp:780
TypedVector3< Type > GetPosition(void) const
Definition: tb_matrix.hpp:978
void SetBasis(const size_t &basisIndex, const TypedVector3< Type > &basis)
Definition: tb_matrix.hpp:956
TypedMatrix4(const SkipInitialization &fastAndStupid)
Definition: tb_matrix.hpp:805
const Type & operator()(const size_t &column, const size_t &row) const
Definition: tb_matrix.hpp:893
void SetOrientation(const TypedMatrix3< Type > &orientation)
Definition: tb_matrix.hpp:1022
Type & operator()(const size_t &column, const size_t &row)
Definition: tb_matrix.hpp:900
TypedMatrix4(void)
Definition: tb_matrix.hpp:714
const Type & operator()(int column, int row) const
Definition: tb_matrix.hpp:906
static TypedMatrix4 Identity(void)
Definition: tb_matrix.hpp:614
void SetPosition(const TypedVector3< Type > &position)
Definition: tb_matrix.hpp:987
bool operator!=(const TypedMatrix4 &other) const
Definition: tb_matrix.hpp:861
TypedMatrix4(Type f11, Type f21, Type f31, Type f41, Type f12, Type f22, Type f32, Type f42, Type f13, Type f23, Type f33, Type f43, Type f14, Type f24, Type f34, Type f44, const ColumnMajorMatrix &columnMajor)
Definition: tb_matrix.hpp:745
Definition: tb_quaternion.hpp:41
Definition: tb_vector.hpp:472
Definition: tb_vector.hpp:927
#define tb_unused(parameter)
Definition: tb_defines.hpp:25
#define tb_error_if(errorTest, message,...)
Definition: tb_error.hpp:42
std::string String
Definition: tb_string.hpp:302
Contains objects and functions for dealing with Vector and Matrix math.
TypedMatrix3< Type > * MatrixComputeInverse(TypedMatrix3< Type > *result, const TypedMatrix3< Type > *input)
Definition: tb_matrix.hpp:2140
Matrix3 * MatrixSubtract(Matrix3 *result, const Matrix3 *leftSide, const Matrix3 *rightSide)
Definition: tb_matrix.hpp:1797
Type Vector3DotProduct(const TypedVector3< Type > *leftSide, const TypedVector3< Type > *rightSide)
Definition: tb_vector.hpp:1618
TypedVector4< Type > * Vector4MatrixMultiply(TypedVector4< Type > *result, const TypedVector4< Type > *inputVector, const TypedMatrix4< Type > *inputMatrix)
Definition: tb_matrix.hpp:2039
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:1705
TypedMatrix3< Type > * MatrixCreateRotationZ(TypedMatrix3< Type > *result, const TypedAngle< Type > rotation)
Definition: tb_matrix.hpp:1534
TypedMatrix3< Type > * MatrixCreateRotationA(TypedMatrix3< Type > *result, const TypedVector3< Type > *rotationAxis, const TypedAngle< Type > rotation)
Definition: tb_matrix.hpp:1569
TypedMatrix3< Type > * MatrixCreateRotationY(TypedMatrix3< Type > *result, const TypedAngle< Type > rotation)
Definition: tb_matrix.hpp:1500
std::ostream & operator<<(std::ostream &output, const tbMath::TypedAngle< Type > &angle)
Definition: tb_angle.hpp:203
Matrix4 * MatrixCreatePerspectiveLH(Matrix4 *result, const float fieldOfView, const float aspectRatio, const float nearPlane, const float farPlane)
Definition: tb_matrix.hpp:1673
bool IsZero(const Type &value, const Type tolerance=tbMath::kTolerance)
Definition: tb_math.hpp:74
bool IsEqual(const Type &leftValue, const Type &rightValue, const Type tolerance=tbMath::kTolerance)
Definition: tb_math.hpp:56
Matrix4 * MatrixCreatePerspectiveRH(Matrix4 *result, const float fieldOfView, const float aspectRatio, const float nearPlane, const float farPlane)
Definition: tb_matrix.hpp:1644
Type Vector3Magnitude(const TypedVector3< Type > *input)
Definition: tb_vector.hpp:1687
TypedVector3< Type > * MatrixVector3Multiply(TypedVector3< Type > *result, const TypedMatrix3< Type > *inputMatrix, const TypedVector3< Type > *inputVector)
Definition: tb_matrix.hpp:1975
TypedMatrix4< Type > * MatrixCreateLookAt(TypedMatrix4< Type > *result, const TypedVector3< Type > &eyePosition, const TypedVector3< Type > &targetPosition, const TypedVector3< Type > &unitUp)
Definition: tb_matrix.hpp:1329
Type MatrixDeterminant(const TypedMatrix3< Type > *input)
Definition: tb_matrix.hpp:2118
TypedVector4< Type > * MatrixVector4Multiply(TypedVector4< Type > *result, const TypedMatrix4< Type > *inputMatrix, const TypedVector4< Type > *inputVector)
Definition: tb_matrix.hpp:2017
Type Matrix3x3Determinant(const Type f11, const Type f12, const Type f13, const Type f21, const Type f22, const Type f23, const Type f31, const Type f32, const Type f33)
Definition: tb_matrix.hpp:2108
TypedVector3< Type > * Vector3MatrixMultiply(TypedVector3< Type > *result, const TypedVector3< Type > *inputVector, const TypedMatrix3< Type > *inputMatrix)
Definition: tb_matrix.hpp:1996
SkipInitialization
Definition: tb_vector.hpp:80
TypedMatrix3< Type > * MatrixCreateIdentity(TypedMatrix3< Type > *result)
Definition: tb_matrix.hpp:1305
TypedMatrix3< Type > * MatrixMultiply(TypedMatrix3< Type > *result, const TypedMatrix3< Type > *input, const Type &scalar)
Definition: tb_matrix.hpp:1933
TypedMatrix4< Type > * MatrixCreateTranslation(TypedMatrix4< Type > *result, const TypedVector3< Type > *translation)
Definition: tb_matrix.hpp:1369
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:1737
TypedMatrix3< Type > * MatrixCreateRotationX(TypedMatrix3< Type > *result, const TypedAngle< Type > rotation)
Definition: tb_matrix.hpp:1466
Vector3 * Vector3Subtract(Vector3 *result, const Vector3 *leftSide, const Vector3 *rightSide)
Definition: tb_vector.hpp:1430
Matrix3 * MatrixTranspose(Matrix3 *result, const Matrix3 *input)
Definition: tb_matrix.hpp:1831
TypedVector3< Type > * Vector3TransformNormal(TypedVector3< Type > *result, const TypedVector3< Type > *inputVector, const TypedMatrix4< Type > *inputMatrix)
Definition: tb_matrix.hpp:2087
TypedVector3< Type > * Vector3CrossProduct(TypedVector3< Type > *result, const TypedVector3< Type > *leftSide, const TypedVector3< Type > *rightSide)
Definition: tb_vector.hpp:1648
TypedVector3< Type > * Vector3TransformCoordinate(TypedVector3< Type > *result, const TypedVector3< Type > *inputVector, const TypedMatrix4< Type > *inputMatrix)
Definition: tb_matrix.hpp:2064
TypedMatrix3< Type > * MatrixCreateScale(TypedMatrix3< Type > *result, const TypedVector3< Type > *scale)
Definition: tb_matrix.hpp:1404
Matrix3 * MatrixAdd(Matrix3 *result, const Matrix3 *leftSide, const Matrix3 *rightSide)
Definition: tb_matrix.hpp:1761
TypedVector3< Type > * Vector3Normalize(TypedVector3< Type > *result, const TypedVector3< Type > *value)
Definition: tb_vector.hpp:1764
TypedMatrix3< Type > * MatrixFastInverse(TypedMatrix3< Type > *result, const TypedMatrix3< Type > *input)
Definition: tb_matrix.hpp:2217
Here is some information about the primary namespace.
Definition: tb_application_dialog.hpp:22