mMatrix.h
Classes:
class
4x4 Matrix Class
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