mMatrix.h

Engine/source/math/mMatrix.h

More...

Classes:

class

4x4 Matrix Class

Public Functions

Detailed Description

Public Functions

mTransformPlane(const MatrixF & mat, const Point3F & scale, const PlaneF & plane, PlaneF * result)

operator*(const MatrixF & m1, const MatrixF & m2)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#ifndef _MMATRIX_H_
 25#define _MMATRIX_H_
 26
 27#ifndef _MPLANE_H_
 28#include "math/mPlane.h"
 29#endif
 30
 31#ifndef _MBOX_H_
 32#include "math/mBox.h"
 33#endif
 34
 35#ifndef _MPOINT4_H_
 36#include "math/mPoint4.h"
 37#endif
 38
 39/// 4x4 Matrix Class
 40///
 41/// This runs at F32 precision.
 42
 43class MatrixF
 44{
 45private:
 46   F32 m[16];     ///< Note: Torque uses row-major matrices
 47
 48public:
 49   /// Create an uninitialized matrix.
 50   ///
 51   /// @param   identity    If true, initialize to the identity matrix.
 52   explicit MatrixF(bool identity=false);
 53
 54   /// Create a matrix to rotate about origin by e.
 55   /// @see set
 56   explicit MatrixF( const EulerF &e);
 57
 58   /// Create a matrix to rotate about p by e.
 59   /// @see set
 60   MatrixF( const EulerF &e, const Point3F& p);
 61
 62   /// Get the index in m to element in column i, row j
 63   ///
 64   /// This is necessary as we have m as a one dimensional array.
 65   ///
 66   /// @param   i   Column desired.
 67   /// @param   j   Row desired.
 68   static U32 idx(U32 i, U32 j) { return (i + j*4); }
 69
 70   /// Initialize matrix to rotate about origin by e.
 71   MatrixF& set( const EulerF &e);
 72
 73   /// Initialize matrix to rotate about p by e.
 74   MatrixF& set( const EulerF &e, const Point3F& p);
 75
 76   /// Initialize matrix with a cross product of p.
 77   MatrixF& setCrossProduct( const Point3F &p);
 78
 79   /// Initialize matrix with a tensor product of p.
 80   MatrixF& setTensorProduct( const Point3F &p, const Point3F& q);
 81
 82   operator F32*() { return (m); }              ///< Allow people to get at m.
 83   operator const F32*() const { return (F32*)(m); }  ///< Allow people to get at m.
 84
 85   bool isAffine() const;                       ///< Check to see if this is an affine matrix.
 86   bool isIdentity() const;                     ///< Checks for identity matrix.
 87
 88   /// Make this an identity matrix.
 89   MatrixF& identity();
 90
 91   /// Invert m.
 92   MatrixF& inverse();
 93   /// Copy the inversion of this into out matrix.
 94   void invertTo( MatrixF *out );
 95
 96   /// Take inverse of matrix assuming it is affine (rotation,
 97   /// scale, sheer, translation only).
 98   MatrixF& affineInverse();           
 99
100   /// Swap rows and columns.
101   MatrixF& transpose();
102
103   /// M * Matrix(p) -> M
104   MatrixF& scale( const Point3F &s );            
105   MatrixF& scale( F32 s ) { return scale( Point3F( s, s, s ) ); }
106
107   /// Return scale assuming scale was applied via mat.scale(s).
108   Point3F getScale() const;
109
110   EulerF toEuler() const;
111
112   /// Compute the inverse of the matrix.
113   ///
114   /// Computes inverse of full 4x4 matrix. Returns false and performs no inverse if
115   /// the determinant is 0.
116   ///
117   /// Note: In most cases you want to use the normal inverse function.  This method should
118   ///       be used if the matrix has something other than (0,0,0,1) in the bottom row.
119   bool fullInverse();
120
121   /// Swaps rows and columns into matrix.
122   void transposeTo(F32 *matrix) const;
123
124   /// Normalize the matrix.
125   void normalize();
126
127   /// Copy the requested column into a Point4F.
128   void getColumn(S32 col, Point4F *cptr) const;
129   Point4F getColumn4F(S32 col) const { Point4F ret; getColumn(col,&ret); return ret; }
130
131   /// Copy the requested column into a Point3F.
132   ///
133   /// This drops the bottom-most row.
134   void getColumn(S32 col, Point3F *cptr) const;
135   Point3F getColumn3F(S32 col) const { Point3F ret; getColumn(col,&ret); return ret; }
136
137   /// Set the specified column from a Point4F.
138   void setColumn(S32 col, const Point4F& cptr);
139
140   /// Set the specified column from a Point3F.
141   ///
142   /// The bottom-most row is not set.
143   void setColumn(S32 col, const Point3F& cptr);
144
145   /// Copy the specified row into a Point4F.
146   void getRow(S32 row, Point4F *cptr) const;
147   Point4F getRow4F(S32 row) const { Point4F ret; getRow(row,&ret); return ret; }
148
149   /// Copy the specified row into a Point3F.
150   ///
151   /// Right-most item is dropped.
152   void getRow(S32 row, Point3F *cptr) const;
153   Point3F getRow3F(S32 row) const { Point3F ret; getRow(row,&ret); return ret; }
154
155   /// Set the specified row from a Point4F.
156   void setRow(S32 row, const Point4F& cptr);
157
158   /// Set the specified row from a Point3F.
159   ///
160   /// The right-most item is not set.
161   void setRow(S32 row, const Point3F& cptr);
162
163   /// Get the position of the matrix.
164   ///
165   /// This is the 4th column of the matrix.
166   Point3F getPosition() const;
167
168   /// Set the position of the matrix.
169   ///
170   /// This is the 4th column of the matrix.
171   void setPosition( const Point3F &pos ) { setColumn( 3, pos ); }
172
173   /// Add the passed delta to the matrix position.
174   void displace( const Point3F &delta );
175
176   /// Get the x axis of the matrix.
177   ///
178   /// This is the 1st column of the matrix and is
179   /// normally considered the right vector.
180   VectorF getRightVector() const;
181
182   /// Get the y axis of the matrix.
183   ///
184   /// This is the 2nd column of the matrix and is
185   /// normally considered the forward vector.   
186   VectorF getForwardVector() const;   
187
188   /// Get the z axis of the matrix.
189   ///
190   /// This is the 3rd column of the matrix and is
191   /// normally considered the up vector.   
192   VectorF getUpVector() const;
193
194   MatrixF&  mul(const MatrixF &a);                    ///< M * a -> M
195   MatrixF&  mulL(const MatrixF &a);                   ///< a * M -> M
196   MatrixF&  mul(const MatrixF &a, const MatrixF &b);  ///< a * b -> M
197
198   // Scalar multiplies
199   MatrixF&  mul(const F32 a);                         ///< M * a -> M
200   MatrixF&  mul(const MatrixF &a, const F32 b);       ///< a * b -> M
201
202
203   void mul( Point4F& p ) const;                       ///< M * p -> p (full [4x4] * [1x4])
204   void mulP( Point3F& p ) const;                      ///< M * p -> p (assume w = 1.0f)
205   void mulP( const Point3F &p, Point3F *d) const;     ///< M * p -> d (assume w = 1.0f)
206   void mulV( VectorF& p ) const;                      ///< M * v -> v (assume w = 0.0f)
207   void mulV( const VectorF &p, Point3F *d) const;     ///< M * v -> d (assume w = 0.0f)
208
209   void mul(Box3F& b) const;                           ///< Axial box -> Axial Box
210   
211   MatrixF& add( const MatrixF& m );
212
213   /// Convenience function to allow people to treat this like an array.
214   F32& operator ()(S32 row, S32 col) { return m[idx(col,row)]; }
215   F32 operator ()(S32 row, S32 col) const { return m[idx(col,row)]; }
216
217   void dumpMatrix(const char *caption=<a href="/coding/file/types_8lint_8h/#types_8lint_8h_1a070d2ce7b6bb7e5c05602aa8c308d0c4">NULL</a>) const;
218
219   // Math operator overloads
220   //------------------------------------
221   friend MatrixF operator *( const MatrixF &m1, const MatrixF &m2 );
222   MatrixF& operator *=( const MatrixF &m );
223
224   // Static identity matrix
225   const static MatrixF Identity;
226};
227
228
229//--------------------------------------
230// Inline Functions
231
232inline MatrixF::MatrixF(bool _identity)
233{
234   if (_identity)
235      identity();
236}
237
238inline MatrixF::MatrixF( const EulerF &e )
239{
240   set(e);
241}
242
243inline MatrixF::MatrixF( const EulerF &e, const Point3F& p )
244{
245   set(e,p);
246}
247
248inline MatrixF& MatrixF::set( const EulerF &e)
249{
250   m_matF_set_euler( e, *this );
251   return (*this);
252}
253
254
255inline MatrixF& MatrixF::set( const EulerF &e, const Point3F& p)
256{
257   m_matF_set_euler_point( e, p, *this );
258   return (*this);
259}
260
261inline MatrixF& MatrixF::setCrossProduct( const Point3F &p)
262{
263   m[1] = -(m[4] = p.z);
264   m[8] = -(m[2] = p.y);
265   m[6] = -(m[9] = p.x);
266   m[0] = m[3] = m[5] = m[7] = m[10] = m[11] =
267      m[12] = m[13] = m[14] = 0.0f;
268   m[15] = 1;
269   return (*this);
270}
271
272inline MatrixF& MatrixF::setTensorProduct( const Point3F &p, const Point3F &q)
273{
274   m[0] = p.x * q.x;
275   m[1] = p.x * q.y;
276   m[2] = p.x * q.z;
277   m[4] = p.y * q.x;
278   m[5] = p.y * q.y;
279   m[6] = p.y * q.z;
280   m[8] = p.z * q.x;
281   m[9] = p.z * q.y;
282   m[10] = p.z * q.z;
283   m[3] = m[7] = m[11] = m[12] = m[13] = m[14] = 0.0f;
284   m[15] = 1.0f;
285   return (*this);
286}
287
288inline bool MatrixF::isIdentity() const
289{
290   return
291   m[0]  == 1.0f &&
292   m[1]  == 0.0f &&
293   m[2]  == 0.0f &&
294   m[3]  == 0.0f &&
295   m[4]  == 0.0f &&
296   m[5]  == 1.0f &&
297   m[6]  == 0.0f &&
298   m[7]  == 0.0f &&
299   m[8]  == 0.0f &&
300   m[9]  == 0.0f &&
301   m[10] == 1.0f &&
302   m[11] == 0.0f &&
303   m[12] == 0.0f &&
304   m[13] == 0.0f &&
305   m[14] == 0.0f &&
306   m[15] == 1.0f;
307}
308
309inline MatrixF& MatrixF::identity()
310{
311   m[0]  = 1.0f;
312   m[1]  = 0.0f;
313   m[2]  = 0.0f;
314   m[3]  = 0.0f;
315   m[4]  = 0.0f;
316   m[5]  = 1.0f;
317   m[6]  = 0.0f;
318   m[7]  = 0.0f;
319   m[8]  = 0.0f;
320   m[9]  = 0.0f;
321   m[10] = 1.0f;
322   m[11] = 0.0f;
323   m[12] = 0.0f;
324   m[13] = 0.0f;
325   m[14] = 0.0f;
326   m[15] = 1.0f;
327   return (*this);
328}
329
330
331inline MatrixF& MatrixF::inverse()
332{
333   m_matF_inverse(m);
334   return (*this);
335}
336
337inline void MatrixF::invertTo( MatrixF *out )
338{
339   m_matF_invert_to(m,*out);
340}
341
342inline MatrixF& MatrixF::affineInverse()
343{
344//   AssertFatal(isAffine() == true, "Error, this matrix is not an affine transform");
345   m_matF_affineInverse(m);
346   return (*this);
347}
348
349inline MatrixF& MatrixF::transpose()
350{
351   m_matF_transpose(m);
352   return (*this);
353}
354
355inline MatrixF& MatrixF::scale(const Point3F& p)
356{
357   m_matF_scale(m,p);
358   return *this;
359}
360
361inline Point3F MatrixF::getScale() const
362{
363   Point3F scale;
364   scale.x = mSqrt(m[0]*m[0] + m[4] * m[4] + m[8] * m[8]);
365   scale.y = mSqrt(m[1]*m[1] + m[5] * m[5] + m[9] * m[9]);
366   scale.z = mSqrt(m[2]*m[2] + m[6] * m[6] + m[10] * m[10]);
367   return scale;
368}
369
370inline void MatrixF::normalize()
371{
372   m_matF_normalize(m);
373}
374
375inline MatrixF& MatrixF::mul( const MatrixF &a )
376{  // M * a -> M
377   AssertFatal(&a != this, "MatrixF::mul - a.mul(a) is invalid!");
378
379   MatrixF tempThis(*this);
380   m_matF_x_matF(tempThis, a, *this);
381   return (*this);
382}
383
384inline MatrixF& MatrixF::mulL( const MatrixF &a )
385{  // a * M -> M
386   AssertFatal(&a != this, "MatrixF::mulL - a.mul(a) is invalid!");
387
388   MatrixF tempThis(*this);
389   m_matF_x_matF(a, tempThis, *this);
390   return (*this);
391}
392
393inline MatrixF& MatrixF::mul( const MatrixF &a, const MatrixF &b )
394{  // a * b -> M
395   AssertFatal((&a != this) && (&b != this), "MatrixF::mul - a.mul(a, b) a.mul(b, a) a.mul(a, a) is invalid!");
396
397   m_matF_x_matF(a, b, *this);
398   return (*this);
399}
400
401
402inline MatrixF& MatrixF::mul(const F32 a)
403{
404   for (U32 i = 0; i < 16; i++)
405      m[i] *= a;
406
407   return *this;
408}
409
410
411inline MatrixF& MatrixF::mul(const MatrixF &a, const F32 b)
412{
413   *this = a;
414   mul(b);
415
416   return *this;
417}
418
419inline void MatrixF::mul( Point4F& p ) const
420{
421   Point4F temp;
422   m_matF_x_point4F(*this, &p.x, &temp.x);
423   p = temp;
424}
425
426inline void MatrixF::mulP( Point3F& p) const
427{
428   // M * p -> d
429   Point3F d;
430   m_matF_x_point3F(*this, &p.x, &d.x);
431   p = d;
432}
433
434inline void MatrixF::mulP( const Point3F &p, Point3F *d) const
435{
436   // M * p -> d
437   m_matF_x_point3F(*this, &p.x, &d->x);
438}
439
440inline void MatrixF::mulV( VectorF& v) const
441{
442   // M * v -> v
443   VectorF temp;
444   m_matF_x_vectorF(*this, &v.x, &temp.x);
445   v = temp;
446}
447
448inline void MatrixF::mulV( const VectorF &v, Point3F *d) const
449{
450   // M * v -> d
451   m_matF_x_vectorF(*this, &v.x, &d->x);
452}
453
454inline void MatrixF::mul(Box3F& b) const
455{
456   m_matF_x_box3F(*this, &b.minExtents.x, &b.maxExtents.x);
457}
458
459inline MatrixF& MatrixF::add( const MatrixF& a )
460{
461   for( U32 i = 0; i < 16; ++ i )
462      m[ i ] += a.m[ i ];
463      
464   return *this;
465}
466
467inline void MatrixF::getColumn(S32 col, Point4F *cptr) const
468{
469   cptr->x = m[col];
470   cptr->y = m[col+4];
471   cptr->z = m[col+8];
472   cptr->w = m[col+12];
473}
474
475inline void MatrixF::getColumn(S32 col, Point3F *cptr) const
476{
477   cptr->x = m[col];
478   cptr->y = m[col+4];
479   cptr->z = m[col+8];
480}
481
482inline void MatrixF::setColumn(S32 col, const Point4F &cptr)
483{
484   m[col]   = cptr.x;
485   m[col+4] = cptr.y;
486   m[col+8] = cptr.z;
487   m[col+12]= cptr.w;
488}
489
490inline void MatrixF::setColumn(S32 col, const Point3F &cptr)
491{
492   m[col]   = cptr.x;
493   m[col+4] = cptr.y;
494   m[col+8] = cptr.z;
495}
496
497
498inline void MatrixF::getRow(S32 col, Point4F *cptr) const
499{
500   col *= 4;
501   cptr->x = m[col++];
502   cptr->y = m[col++];
503   cptr->z = m[col++];
504   cptr->w = m[col];
505}
506
507inline void MatrixF::getRow(S32 col, Point3F *cptr) const
508{
509   col *= 4;
510   cptr->x = m[col++];
511   cptr->y = m[col++];
512   cptr->z = m[col];
513}
514
515inline void MatrixF::setRow(S32 col, const Point4F &cptr)
516{
517   col *= 4;
518   m[col++] = cptr.x;
519   m[col++] = cptr.y;
520   m[col++] = cptr.z;
521   m[col]   = cptr.w;
522}
523
524inline void MatrixF::setRow(S32 col, const Point3F &cptr)
525{
526   col *= 4;
527   m[col++] = cptr.x;
528   m[col++] = cptr.y;
529   m[col]   = cptr.z;
530}
531
532inline Point3F MatrixF::getPosition() const
533{
534   return Point3F( m[3], m[3+4], m[3+8] );
535}
536
537inline void MatrixF::displace( const Point3F &delta )
538{
539   m[3]   += delta.x;
540   m[3+4] += delta.y;
541   m[3+8] += delta.z;
542}
543
544inline VectorF MatrixF::getForwardVector() const
545{
546   VectorF vec;
547   getColumn( 1, &vec );
548   return vec;
549}
550
551inline VectorF MatrixF::getRightVector() const
552{
553   VectorF vec;
554   getColumn( 0, &vec );
555   return vec;
556}
557
558inline VectorF MatrixF::getUpVector() const
559{
560   VectorF vec;
561   getColumn( 2, &vec );
562   return vec;
563}
564
565//------------------------------------
566// Math operator overloads
567//------------------------------------
568inline MatrixF operator *( const MatrixF &m1, const MatrixF &m2 )
569{
570   // temp = m1 * m2
571   MatrixF temp;
572   m_matF_x_matF(m1, m2, temp);
573   return temp;
574}
575
576inline MatrixF& MatrixF::operator *=( const MatrixF &m1 )
577{
578   MatrixF tempThis(*this);
579   m_matF_x_matF(tempThis, m1, *this);
580   return (*this);
581}
582
583//------------------------------------
584// Non-member methods
585//------------------------------------
586
587inline void mTransformPlane(const MatrixF& mat, const Point3F& scale, const PlaneF&  plane, PlaneF * result)
588{
589   m_matF_x_scale_x_planeF(mat, &scale.x, &plane.x, &result->x);
590}
591
592#endif //_MMATRIX_H_
593