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