My Project
ParaMatrix4.h
1 #pragma once
2 namespace ParaEngine
3 {
4  class QMatrix;
5 
23  class Matrix4
24  {
25  public:
27  union {
28  struct {
29  float _11, _12, _13, _14;
30  float _21, _22, _23, _24;
31  float _31, _32, _33, _34;
32  float _41, _42, _43, _44;
33  };
34  float m[4][4];
35  float _m[16];
36  };
37  public:
42  inline Matrix4()
43  {
44  }
45 
46  inline Matrix4(
47  float m00, float m01, float m02, float m03,
48  float m10, float m11, float m12, float m13,
49  float m20, float m21, float m22, float m23,
50  float m30, float m31, float m32, float m33 )
51  {
52  m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
53  m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
54  m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
55  m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
56  }
57 
61  inline Matrix4(const Matrix3& m3x3)
62  {
63  operator=(IDENTITY);
64  operator=(m3x3);
65  }
66 
67  inline Matrix4(const DeviceMatrix& mat)
68  {
69  operator=(reinterpret_cast<const Matrix4&>(mat));
70  }
71 
73  Matrix4(const QMatrix& mat2DAffine);
74 
78  inline Matrix4(const Quaternion& rot)
79  {
80  rot.ToRotationMatrix(*this, Vector3::ZERO);
81  }
82 
84  inline void identity() {
85  *this = Matrix4::IDENTITY;
86  };
87 
88  inline float* operator [] ( size_t iRow )
89  {
90  assert( iRow < 4 );
91  return m[iRow];
92  }
93 
94  inline const float *const operator [] ( size_t iRow ) const
95  {
96  assert( iRow < 4 );
97  return m[iRow];
98  }
99 
102  inline Matrix4 operator * ( const Matrix4 &m2 ) const
103  {
104  Matrix4 r;
105  ParaMatrixMultiply(&r, this, &m2);
106  return r;
107  }
108 
110  Matrix4 Multiply4x3(const Matrix4 &m2) const;
111 
112  inline void operator *= (const Matrix4 &m2)
113  {
114  ParaMatrixMultiply(this, this, &m2);
115  }
116 
126  inline Vector3 operator * ( const Vector3 &v ) const
127  {
128  Vector3 r;
129 
130  float fInvW = 1.0f / ( m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] );
131 
132  r.x = ( m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] ) * fInvW;
133  r.y = ( m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] ) * fInvW;
134  r.z = ( m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] ) * fInvW;
135 
136  return r;
137  }
138  inline Vector4 operator * (const Vector4& v) const
139  {
140  return Vector4(
141  m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
142  m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
143  m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
144  m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
145  );
146  }
147  inline Plane operator * (const Plane& p) const
148  {
149  Plane ret;
150  Matrix4 invTrans = inverse().transpose();
151  Vector4 v4( p.normal.x, p.normal.y, p.normal.z, p.d );
152  v4 = invTrans * v4;
153  ret.normal.x = v4.x;
154  ret.normal.y = v4.y;
155  ret.normal.z = v4.z;
156  ret.d = v4.w / ret.normal.normalise();
157 
158  return ret;
159  }
160 
161 
164  inline Matrix4 operator + ( const Matrix4 &m2 ) const
165  {
166  Matrix4 r;
167 
168  r.m[0][0] = m[0][0] + m2.m[0][0];
169  r.m[0][1] = m[0][1] + m2.m[0][1];
170  r.m[0][2] = m[0][2] + m2.m[0][2];
171  r.m[0][3] = m[0][3] + m2.m[0][3];
172 
173  r.m[1][0] = m[1][0] + m2.m[1][0];
174  r.m[1][1] = m[1][1] + m2.m[1][1];
175  r.m[1][2] = m[1][2] + m2.m[1][2];
176  r.m[1][3] = m[1][3] + m2.m[1][3];
177 
178  r.m[2][0] = m[2][0] + m2.m[2][0];
179  r.m[2][1] = m[2][1] + m2.m[2][1];
180  r.m[2][2] = m[2][2] + m2.m[2][2];
181  r.m[2][3] = m[2][3] + m2.m[2][3];
182 
183  r.m[3][0] = m[3][0] + m2.m[3][0];
184  r.m[3][1] = m[3][1] + m2.m[3][1];
185  r.m[3][2] = m[3][2] + m2.m[3][2];
186  r.m[3][3] = m[3][3] + m2.m[3][3];
187 
188  return r;
189  }
190  inline Matrix4& operator += (const Matrix4 &m2)
191  {
192  m[0][0] += m2.m[0][0]; m[0][1] += m2.m[0][1]; m[0][2] += m2.m[0][2]; m[0][3] += m2.m[0][3];
193  m[1][0] += m2.m[1][0]; m[1][1] += m2.m[1][1]; m[1][2] += m2.m[1][2]; m[1][3] += m2.m[1][3];
194  m[2][0] += m2.m[2][0]; m[2][1] += m2.m[2][1]; m[2][2] += m2.m[2][2]; m[2][3] += m2.m[2][3];
195  m[3][0] += m2.m[3][0]; m[3][1] += m2.m[3][1]; m[3][2] += m2.m[3][2]; m[3][3] += m2.m[3][3];
196  return *this;
197  }
198 
201  inline Matrix4 operator - ( const Matrix4 &m2 ) const
202  {
203  Matrix4 r;
204  r.m[0][0] = m[0][0] - m2.m[0][0];
205  r.m[0][1] = m[0][1] - m2.m[0][1];
206  r.m[0][2] = m[0][2] - m2.m[0][2];
207  r.m[0][3] = m[0][3] - m2.m[0][3];
208 
209  r.m[1][0] = m[1][0] - m2.m[1][0];
210  r.m[1][1] = m[1][1] - m2.m[1][1];
211  r.m[1][2] = m[1][2] - m2.m[1][2];
212  r.m[1][3] = m[1][3] - m2.m[1][3];
213 
214  r.m[2][0] = m[2][0] - m2.m[2][0];
215  r.m[2][1] = m[2][1] - m2.m[2][1];
216  r.m[2][2] = m[2][2] - m2.m[2][2];
217  r.m[2][3] = m[2][3] - m2.m[2][3];
218 
219  r.m[3][0] = m[3][0] - m2.m[3][0];
220  r.m[3][1] = m[3][1] - m2.m[3][1];
221  r.m[3][2] = m[3][2] - m2.m[3][2];
222  r.m[3][3] = m[3][3] - m2.m[3][3];
223 
224  return r;
225  }
226  inline Matrix4& operator -= (const Matrix4 &m2)
227  {
228  m[0][0] -= m2.m[0][0]; m[0][1] -= m2.m[0][1]; m[0][2] -= m2.m[0][2]; m[0][3] -= m2.m[0][3];
229  m[1][0] -= m2.m[1][0]; m[1][1] -= m2.m[1][1]; m[1][2] -= m2.m[1][2]; m[1][3] -= m2.m[1][3];
230  m[2][0] -= m2.m[2][0]; m[2][1] -= m2.m[2][1]; m[2][2] -= m2.m[2][2]; m[2][3] -= m2.m[2][3];
231  m[3][0] -= m2.m[3][0]; m[3][1] -= m2.m[3][1]; m[3][2] -= m2.m[3][2]; m[3][3] -= m2.m[3][3];
232  return *this;
233  }
234 
237  inline bool operator == ( const Matrix4& m2 ) const
238  {
239  if(
240  m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
241  m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
242  m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
243  m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
244  return false;
245  return true;
246  }
247 
250  inline bool operator != ( const Matrix4& m2 ) const
251  {
252  if(
253  m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
254  m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
255  m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
256  m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
257  return true;
258  return false;
259  }
260 
263  inline void operator = ( const Matrix3& mat3 )
264  {
265  m[0][0] = mat3.m[0][0]; m[0][1] = mat3.m[0][1]; m[0][2] = mat3.m[0][2];
266  m[1][0] = mat3.m[1][0]; m[1][1] = mat3.m[1][1]; m[1][2] = mat3.m[1][2];
267  m[2][0] = mat3.m[2][0]; m[2][1] = mat3.m[2][1]; m[2][2] = mat3.m[2][2];
268  }
269 
270  inline Matrix4 transpose(void) const
271  {
272  return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
273  m[0][1], m[1][1], m[2][1], m[3][1],
274  m[0][2], m[1][2], m[2][2], m[3][2],
275  m[0][3], m[1][3], m[2][3], m[3][3]);
276  }
277 
278  /*
279  -----------------------------------------------------------------------
280  Translation Transformation
281  -----------------------------------------------------------------------
282  */
283  inline void offsetTrans(const Vector3& v)
284  {
285  m[3][0] += v.x; m[3][1] += v.y; m[3][2] += v.z;
286  }
287 
290  inline void setTrans( const Vector3& v )
291  {
292  m[3][0] = v.x;
293  m[3][1] = v.y;
294  m[3][2] = v.z;
295  }
296 
299  inline Vector3 getTrans() const
300  {
301  return Vector3(m[3][0], m[3][1], m[3][2]);
302  }
303 
304 
307  inline void makeTrans( const Vector3& v )
308  {
309  m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = 0.0;
310  m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = 0.0;
311  m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = 0.0;
312  m[3][0] = v.x; m[3][1] = v.y; m[3][2] = v.z; m[3][3] = 1.0;
313  }
314 
315  inline void makeTrans( float tx, float ty, float tz )
316  {
317  m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = 0.0;
318  m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = 0.0;
319  m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = 0.0;
320  m[3][0] = tx; m[3][1] = ty; m[3][2] = tz; m[3][3] = 1.0;
321  }
322 
323 
324  /*
325  -----------------------------------------------------------------------
326  Scale Transformation
327  -----------------------------------------------------------------------
328  */
331  inline void setScale( const Vector3& v )
332  {
333  m[0][0] = v.x;
334  m[1][1] = v.y;
335  m[2][2] = v.z;
336  }
337 
340  inline void makeScale( float s_x, float s_y, float s_z )
341  {
342  identity();
343  m[0][0] = s_x; m[1][1] = s_y; m[2][2] = s_z;
344  }
345 
346  inline void makeScale(const Vector3& v)
347  {
348  identity();
349  m[0][0] = v.x; m[1][1] = v.y; m[2][2] = v.z;
350  }
351 
355  inline void extract3x3Matrix(Matrix3& m3x3) const
356  {
357  m3x3.m[0][0] = m[0][0]; m3x3.m[0][1] = m[0][1]; m3x3.m[0][2] = m[0][2];
358  m3x3.m[1][0] = m[1][0]; m3x3.m[1][1] = m[1][1]; m3x3.m[1][2] = m[1][2];
359  m3x3.m[2][0] = m[2][0]; m3x3.m[2][1] = m[2][1]; m3x3.m[2][2] = m[2][2];
360  }
361 
363  bool hasScale() const;
364 
366  inline bool hasNegativeScale() const
367  {
368  return determinant() < 0;
369  }
370 
374  {
375  return Quaternion(*this);
376  }
377 
378  static const Matrix4 ZERO;
379  static const Matrix4 IDENTITY;
383 
384  inline Matrix4 operator*(float scalar) const
385  {
386  return Matrix4(
387  scalar*m[0][0], scalar*m[0][1], scalar*m[0][2], scalar*m[0][3],
388  scalar*m[1][0], scalar*m[1][1], scalar*m[1][2], scalar*m[1][3],
389  scalar*m[2][0], scalar*m[2][1], scalar*m[2][2], scalar*m[2][3],
390  scalar*m[3][0], scalar*m[3][1], scalar*m[3][2], scalar*m[3][3]);
391  }
392 
395  friend std::ostream& operator << ( std::ostream& o, const Matrix4& m )
396  {
397  o << "Matrix4(";
398  for (size_t i = 0; i < 4; ++i)
399  {
400  o << " row" << (unsigned)i << "{";
401  for(size_t j = 0; j < 4; ++j)
402  {
403  o << m[i][j] << " ";
404  }
405  o << "}";
406  }
407  o << ")";
408  return o;
409  }
410 
411  Matrix4 adjoint() const;
412  float determinant() const;
413  Matrix4 inverse() const;
414  inline void invert() {
415  *this = inverse();
416  };
417 
424  Matrix4 InvertPRMatrix() const;
425 
432  void makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
433 
435  void makeRot(const Quaternion& orientation, const Vector3& origin);
436 
442  void makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
443 
449  inline bool isAffine(void) const
450  {
451  return m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1;
452  }
453  inline bool isAffineColumnMajor(void) const
454  {
455  return m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0 && m[3][3] == 1;
456  }
457 
458 
466  inline Vector3 transformAffine(const Vector3& v) const
467  {
468  // assert(isAffineColumnMajor());
469 
470  return Vector3(
471  m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3],
472  m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3],
473  m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]);
474  }
475 
480  inline Vector4 transformAffine(const Vector4& v) const
481  {
482  // assert(isAffineColumnMajor());
483 
484  return Vector4(
485  m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
486  m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
487  m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
488  v.w);
489  }
490 
491 
492  // NOTE: There is some compiler optimization issues with WIN64 that cause FORCEINLINE to cause a crash
493  // Remove any scaling from this matrix (ie magnitude of each row is 1)
494  void RemoveScaling(float Tolerance=SMALL_NUMBER);
495 
496  // Returns matrix without scale information
497  Matrix4 GetMatrixWithoutScale(float Tolerance=SMALL_NUMBER) const;
498 
500  Vector3 ExtractScaling(float Tolerance=SMALL_NUMBER);
501 
503  Vector3 GetScaleVector(float Tolerance=SMALL_NUMBER) const;
507  float GetScaleByAxis(int axis, float Tolerance = SMALL_NUMBER) const;
508  // Remove any translation from this matrix
509  Matrix4 RemoveTranslation() const;
510 
511  inline DeviceMatrix_ptr GetPointer() { return (DeviceMatrix_ptr)this; }
512  inline const DeviceMatrix_ptr GetConstPointer() const { return (const DeviceMatrix_ptr)this; }
513  };
514 }
static const Matrix4 CLIPSPACE2DTOIMAGESPACE
Useful little matrix which takes 2D clipspace {-1, 1} to {0,1} and inverts the Y. ...
Definition: ParaMatrix4.h:382
friend std::ostream & operator<<(std::ostream &o, const Matrix4 &m)
Function for writing to a stream.
Definition: ParaMatrix4.h:395
Matrix4 Multiply4x3(const Matrix4 &m2) const
we will assume both matrix are row-major affine matrix.
Definition: ParaMatrix4.cpp:355
Definition: PEtypes.h:315
Vector3 getTrans() const
Extracts the translation transformation part of the matrix.
Definition: ParaMatrix4.h:299
Matrix4()
Default constructor.
Definition: ParaMatrix4.h:42
4-dimensional homogeneous vector.
Definition: ParaVector4.h:10
Vector4 transformAffine(const Vector4 &v) const
Column vector: 4-D Vector transformation specially for affine matrix.
Definition: ParaMatrix4.h:480
different physics engine has different winding order.
Definition: EventBinding.h:32
bool hasScale() const
Determines if this matrix involves a scaling.
Definition: ParaMatrix4.cpp:339
Implementation of a Quaternion, i.e.
Definition: ParaQuaternion.h:10
Vector3 GetScaleVector(float Tolerance=SMALL_NUMBER) const
return a 3D scale vector calculated from this matrix (where each component is the magnitude of a row ...
Definition: ParaMatrix4.cpp:296
A 3x3 matrix which can represent rotations around axes.
Definition: ParaMatrix3.h:63
void setTrans(const Vector3 &v)
Sets the translation transformation part of the matrix.
Definition: ParaMatrix4.h:290
Matrix4 operator*(const Matrix4 &m2) const
Matrix4 concatenation using &#39;*&#39;.
Definition: ParaMatrix4.h:102
Standard 3-dimensional vector.
Definition: ParaVector3.h:16
Vector3 transformAffine(const Vector3 &v) const
Column vector: 3-D Vector transformation specially for affine matrix.
Definition: ParaMatrix4.h:466
Matrix4 operator-(const Matrix4 &m2) const
Matrix4 subtraction.
Definition: ParaMatrix4.h:201
bool operator==(const Matrix4 &m2) const
Tests 2 matrices for equality.
Definition: ParaMatrix4.h:237
void identity()
make this identity
Definition: ParaMatrix4.h:84
float normalise()
Normalises the vector.
Definition: ParaVector3.h:430
void setScale(const Vector3 &v)
Sets the scale part of the matrix.
Definition: ParaMatrix4.h:331
Class encapsulating a standard 4x4 homogeneous matrix.
Definition: ParaMatrix4.h:23
Defines a plane in 3D space.
Definition: ParaPlane.h:23
Matrix4(const Quaternion &rot)
Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling Qua...
Definition: ParaMatrix4.h:78
bool hasNegativeScale() const
Determines if this matrix involves a negative scaling.
Definition: ParaMatrix4.h:366
Matrix4 InvertPRMatrix() const
Inverts a PR matrix.
Definition: ParaMatrix4.cpp:195
void operator=(const Matrix3 &mat3)
Assignment from 3x3 matrix.
Definition: ParaMatrix4.h:263
Definition: qmatrix.h:12
Vector3 ExtractScaling(float Tolerance=SMALL_NUMBER)
Remove any scaling from this matrix (ie magnitude of each row is 1) and return the 3D scale vector th...
Definition: ParaMatrix4.cpp:242
Matrix4 * ParaMatrixMultiply(Matrix4 *Result, const Matrix4 *Matrix1, const Matrix4 *Matrix2)
Multiplies two 4x4 matrices.
Definition: ParaMathMatrix.cpp:55
void makeInverseTransform(const Vector3 &position, const Vector3 &scale, const Quaternion &orientation)
Building an inverse Matrix4 from orientation / scale / position.
Definition: ParaMatrix4.cpp:162
void makeScale(float s_x, float s_y, float s_z)
Gets a scale matrix - variation for not using a vector.
Definition: ParaMatrix4.h:340
void makeRot(const Quaternion &orientation, const Vector3 &origin)
make rotation matrix
Definition: ParaMatrix4.cpp:190
Matrix4(const Matrix3 &m3x3)
Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3...
Definition: ParaMatrix4.h:61
Matrix4 operator+(const Matrix4 &m2) const
Matrix4 addition.
Definition: ParaMatrix4.h:164
bool operator!=(const Matrix4 &m2) const
Tests 2 matrices for inequality.
Definition: ParaMatrix4.h:250
void makeTrans(const Vector3 &v)
Builds a translation matrix.
Definition: ParaMatrix4.h:307
void makeTransform(const Vector3 &position, const Vector3 &scale, const Quaternion &orientation)
Building a Matrix4 from orientation / scale / position.
Definition: ParaMatrix4.cpp:140
void extract3x3Matrix(Matrix3 &m3x3) const
Extracts the rotation / scaling part of the Matrix4 as a 3x3 matrix.
Definition: ParaMatrix4.h:355
float GetScaleByAxis(int axis, float Tolerance=SMALL_NUMBER) const
Definition: ParaMatrix4.cpp:318
Quaternion extractQuaternion() const
Extracts the rotation / scaling part as a quaternion from the Matrix4.
Definition: ParaMatrix4.h:373
bool isAffine(void) const
Check whether or not the matrix is affine row-major matrix.
Definition: ParaMatrix4.h:449