Matrix.h (57756B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #ifndef __MATH_MATRIX_H__ 30 #define __MATH_MATRIX_H__ 31 32 /* 33 =============================================================================== 34 35 Matrix classes, all matrices are row-major except idMat3 36 37 =============================================================================== 38 */ 39 40 #define MATRIX_INVERSE_EPSILON 1e-14 41 #define MATRIX_EPSILON 1e-6 42 43 class idAngles; 44 class idQuat; 45 class idCQuat; 46 class idRotation; 47 class idMat4; 48 49 //=============================================================== 50 // 51 // idMat2 - 2x2 matrix 52 // 53 //=============================================================== 54 55 class idMat2 { 56 public: 57 idMat2(); 58 explicit idMat2( const idVec2 &x, const idVec2 &y ); 59 explicit idMat2( const float xx, const float xy, const float yx, const float yy ); 60 explicit idMat2( const float src[ 2 ][ 2 ] ); 61 62 const idVec2 & operator[]( int index ) const; 63 idVec2 & operator[]( int index ); 64 idMat2 operator-() const; 65 idMat2 operator*( const float a ) const; 66 idVec2 operator*( const idVec2 &vec ) const; 67 idMat2 operator*( const idMat2 &a ) const; 68 idMat2 operator+( const idMat2 &a ) const; 69 idMat2 operator-( const idMat2 &a ) const; 70 idMat2 & operator*=( const float a ); 71 idMat2 & operator*=( const idMat2 &a ); 72 idMat2 & operator+=( const idMat2 &a ); 73 idMat2 & operator-=( const idMat2 &a ); 74 75 friend idMat2 operator*( const float a, const idMat2 &mat ); 76 friend idVec2 operator*( const idVec2 &vec, const idMat2 &mat ); 77 friend idVec2 & operator*=( idVec2 &vec, const idMat2 &mat ); 78 79 bool Compare( const idMat2 &a ) const; // exact compare, no epsilon 80 bool Compare( const idMat2 &a, const float epsilon ) const; // compare with epsilon 81 bool operator==( const idMat2 &a ) const; // exact compare, no epsilon 82 bool operator!=( const idMat2 &a ) const; // exact compare, no epsilon 83 84 void Zero(); 85 void Identity(); 86 bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const; 87 bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const; 88 bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const; 89 90 float Trace() const; 91 float Determinant() const; 92 idMat2 Transpose() const; // returns transpose 93 idMat2 & TransposeSelf(); 94 idMat2 Inverse() const; // returns the inverse ( m * m.Inverse() = identity ) 95 bool InverseSelf(); // returns false if determinant is zero 96 idMat2 InverseFast() const; // returns the inverse ( m * m.Inverse() = identity ) 97 bool InverseFastSelf(); // returns false if determinant is zero 98 99 int GetDimension() const; 100 101 const float * ToFloatPtr() const; 102 float * ToFloatPtr(); 103 const char * ToString( int precision = 2 ) const; 104 105 private: 106 idVec2 mat[ 2 ]; 107 }; 108 109 extern idMat2 mat2_zero; 110 extern idMat2 mat2_identity; 111 #define mat2_default mat2_identity 112 113 ID_INLINE idMat2::idMat2() { 114 } 115 116 ID_INLINE idMat2::idMat2( const idVec2 &x, const idVec2 &y ) { 117 mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; 118 mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; 119 } 120 121 ID_INLINE idMat2::idMat2( const float xx, const float xy, const float yx, const float yy ) { 122 mat[ 0 ].x = xx; mat[ 0 ].y = xy; 123 mat[ 1 ].x = yx; mat[ 1 ].y = yy; 124 } 125 126 ID_INLINE idMat2::idMat2( const float src[ 2 ][ 2 ] ) { 127 memcpy( mat, src, 2 * 2 * sizeof( float ) ); 128 } 129 130 ID_INLINE const idVec2 &idMat2::operator[]( int index ) const { 131 //assert( ( index >= 0 ) && ( index < 2 ) ); 132 return mat[ index ]; 133 } 134 135 ID_INLINE idVec2 &idMat2::operator[]( int index ) { 136 //assert( ( index >= 0 ) && ( index < 2 ) ); 137 return mat[ index ]; 138 } 139 140 ID_INLINE idMat2 idMat2::operator-() const { 141 return idMat2( -mat[0][0], -mat[0][1], 142 -mat[1][0], -mat[1][1] ); 143 } 144 145 ID_INLINE idVec2 idMat2::operator*( const idVec2 &vec ) const { 146 return idVec2( 147 mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y, 148 mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y ); 149 } 150 151 ID_INLINE idMat2 idMat2::operator*( const idMat2 &a ) const { 152 return idMat2( 153 mat[0].x * a[0].x + mat[0].y * a[1].x, 154 mat[0].x * a[0].y + mat[0].y * a[1].y, 155 mat[1].x * a[0].x + mat[1].y * a[1].x, 156 mat[1].x * a[0].y + mat[1].y * a[1].y ); 157 } 158 159 ID_INLINE idMat2 idMat2::operator*( const float a ) const { 160 return idMat2( 161 mat[0].x * a, mat[0].y * a, 162 mat[1].x * a, mat[1].y * a ); 163 } 164 165 ID_INLINE idMat2 idMat2::operator+( const idMat2 &a ) const { 166 return idMat2( 167 mat[0].x + a[0].x, mat[0].y + a[0].y, 168 mat[1].x + a[1].x, mat[1].y + a[1].y ); 169 } 170 171 ID_INLINE idMat2 idMat2::operator-( const idMat2 &a ) const { 172 return idMat2( 173 mat[0].x - a[0].x, mat[0].y - a[0].y, 174 mat[1].x - a[1].x, mat[1].y - a[1].y ); 175 } 176 177 ID_INLINE idMat2 &idMat2::operator*=( const float a ) { 178 mat[0].x *= a; mat[0].y *= a; 179 mat[1].x *= a; mat[1].y *= a; 180 181 return *this; 182 } 183 184 ID_INLINE idMat2 &idMat2::operator*=( const idMat2 &a ) { 185 float x, y; 186 x = mat[0].x; y = mat[0].y; 187 mat[0].x = x * a[0].x + y * a[1].x; 188 mat[0].y = x * a[0].y + y * a[1].y; 189 x = mat[1].x; y = mat[1].y; 190 mat[1].x = x * a[0].x + y * a[1].x; 191 mat[1].y = x * a[0].y + y * a[1].y; 192 return *this; 193 } 194 195 ID_INLINE idMat2 &idMat2::operator+=( const idMat2 &a ) { 196 mat[0].x += a[0].x; mat[0].y += a[0].y; 197 mat[1].x += a[1].x; mat[1].y += a[1].y; 198 199 return *this; 200 } 201 202 ID_INLINE idMat2 &idMat2::operator-=( const idMat2 &a ) { 203 mat[0].x -= a[0].x; mat[0].y -= a[0].y; 204 mat[1].x -= a[1].x; mat[1].y -= a[1].y; 205 206 return *this; 207 } 208 209 ID_INLINE idVec2 operator*( const idVec2 &vec, const idMat2 &mat ) { 210 return mat * vec; 211 } 212 213 ID_INLINE idMat2 operator*( const float a, idMat2 const &mat ) { 214 return mat * a; 215 } 216 217 ID_INLINE idVec2 &operator*=( idVec2 &vec, const idMat2 &mat ) { 218 vec = mat * vec; 219 return vec; 220 } 221 222 ID_INLINE bool idMat2::Compare( const idMat2 &a ) const { 223 if ( mat[0].Compare( a[0] ) && 224 mat[1].Compare( a[1] ) ) { 225 return true; 226 } 227 return false; 228 } 229 230 ID_INLINE bool idMat2::Compare( const idMat2 &a, const float epsilon ) const { 231 if ( mat[0].Compare( a[0], epsilon ) && 232 mat[1].Compare( a[1], epsilon ) ) { 233 return true; 234 } 235 return false; 236 } 237 238 ID_INLINE bool idMat2::operator==( const idMat2 &a ) const { 239 return Compare( a ); 240 } 241 242 ID_INLINE bool idMat2::operator!=( const idMat2 &a ) const { 243 return !Compare( a ); 244 } 245 246 ID_INLINE void idMat2::Zero() { 247 mat[0].Zero(); 248 mat[1].Zero(); 249 } 250 251 ID_INLINE void idMat2::Identity() { 252 *this = mat2_identity; 253 } 254 255 ID_INLINE bool idMat2::IsIdentity( const float epsilon ) const { 256 return Compare( mat2_identity, epsilon ); 257 } 258 259 ID_INLINE bool idMat2::IsSymmetric( const float epsilon ) const { 260 return ( idMath::Fabs( mat[0][1] - mat[1][0] ) < epsilon ); 261 } 262 263 ID_INLINE bool idMat2::IsDiagonal( const float epsilon ) const { 264 if ( idMath::Fabs( mat[0][1] ) > epsilon || 265 idMath::Fabs( mat[1][0] ) > epsilon ) { 266 return false; 267 } 268 return true; 269 } 270 271 ID_INLINE float idMat2::Trace() const { 272 return ( mat[0][0] + mat[1][1] ); 273 } 274 275 ID_INLINE float idMat2::Determinant() const { 276 return mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]; 277 } 278 279 ID_INLINE idMat2 idMat2::Transpose() const { 280 return idMat2( mat[0][0], mat[1][0], 281 mat[0][1], mat[1][1] ); 282 } 283 284 ID_INLINE idMat2 &idMat2::TransposeSelf() { 285 float tmp; 286 287 tmp = mat[0][1]; 288 mat[0][1] = mat[1][0]; 289 mat[1][0] = tmp; 290 291 return *this; 292 } 293 294 ID_INLINE idMat2 idMat2::Inverse() const { 295 idMat2 invMat; 296 297 invMat = *this; 298 verify( invMat.InverseSelf() ); 299 return invMat; 300 } 301 302 ID_INLINE idMat2 idMat2::InverseFast() const { 303 idMat2 invMat; 304 305 invMat = *this; 306 verify( invMat.InverseFastSelf() ); 307 return invMat; 308 } 309 310 ID_INLINE int idMat2::GetDimension() const { 311 return 4; 312 } 313 314 ID_INLINE const float *idMat2::ToFloatPtr() const { 315 return mat[0].ToFloatPtr(); 316 } 317 318 ID_INLINE float *idMat2::ToFloatPtr() { 319 return mat[0].ToFloatPtr(); 320 } 321 322 323 //=============================================================== 324 // 325 // idMat3 - 3x3 matrix 326 // 327 // NOTE: matrix is column-major 328 // 329 //=============================================================== 330 331 class idMat3 { 332 public: 333 idMat3(); 334 explicit idMat3( const idVec3 &x, const idVec3 &y, const idVec3 &z ); 335 explicit idMat3( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ); 336 explicit idMat3( const float src[ 3 ][ 3 ] ); 337 338 const idVec3 & operator[]( int index ) const; 339 idVec3 & operator[]( int index ); 340 idMat3 operator-() const; 341 idMat3 operator*( const float a ) const; 342 idVec3 operator*( const idVec3 &vec ) const; 343 idMat3 operator*( const idMat3 &a ) const; 344 idMat3 operator+( const idMat3 &a ) const; 345 idMat3 operator-( const idMat3 &a ) const; 346 idMat3 & operator*=( const float a ); 347 idMat3 & operator*=( const idMat3 &a ); 348 idMat3 & operator+=( const idMat3 &a ); 349 idMat3 & operator-=( const idMat3 &a ); 350 351 friend idMat3 operator*( const float a, const idMat3 &mat ); 352 friend idVec3 operator*( const idVec3 &vec, const idMat3 &mat ); 353 friend idVec3 & operator*=( idVec3 &vec, const idMat3 &mat ); 354 355 bool Compare( const idMat3 &a ) const; // exact compare, no epsilon 356 bool Compare( const idMat3 &a, const float epsilon ) const; // compare with epsilon 357 bool operator==( const idMat3 &a ) const; // exact compare, no epsilon 358 bool operator!=( const idMat3 &a ) const; // exact compare, no epsilon 359 360 void Zero(); 361 void Identity(); 362 bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const; 363 bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const; 364 bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const; 365 bool IsRotated() const; 366 367 void ProjectVector( const idVec3 &src, idVec3 &dst ) const; 368 void UnprojectVector( const idVec3 &src, idVec3 &dst ) const; 369 370 bool FixDegeneracies(); // fix degenerate axial cases 371 bool FixDenormals(); // change tiny numbers to zero 372 373 float Trace() const; 374 float Determinant() const; 375 idMat3 OrthoNormalize() const; 376 idMat3 & OrthoNormalizeSelf(); 377 idMat3 Transpose() const; // returns transpose 378 idMat3 & TransposeSelf(); 379 idMat3 Inverse() const; // returns the inverse ( m * m.Inverse() = identity ) 380 bool InverseSelf(); // returns false if determinant is zero 381 idMat3 InverseFast() const; // returns the inverse ( m * m.Inverse() = identity ) 382 bool InverseFastSelf(); // returns false if determinant is zero 383 idMat3 TransposeMultiply( const idMat3 &b ) const; 384 385 idMat3 InertiaTranslate( const float mass, const idVec3 ¢erOfMass, const idVec3 &translation ) const; 386 idMat3 & InertiaTranslateSelf( const float mass, const idVec3 ¢erOfMass, const idVec3 &translation ); 387 idMat3 InertiaRotate( const idMat3 &rotation ) const; 388 idMat3 & InertiaRotateSelf( const idMat3 &rotation ); 389 390 int GetDimension() const; 391 392 idAngles ToAngles() const; 393 idQuat ToQuat() const; 394 idCQuat ToCQuat() const; 395 idRotation ToRotation() const; 396 idMat4 ToMat4() const; 397 idVec3 ToAngularVelocity() const; 398 const float * ToFloatPtr() const; 399 float * ToFloatPtr(); 400 const char * ToString( int precision = 2 ) const; 401 402 friend void TransposeMultiply( const idMat3 &inv, const idMat3 &b, idMat3 &dst ); 403 friend idMat3 SkewSymmetric( idVec3 const &src ); 404 405 private: 406 idVec3 mat[ 3 ]; 407 }; 408 409 extern idMat3 mat3_zero; 410 extern idMat3 mat3_identity; 411 #define mat3_default mat3_identity 412 413 ID_INLINE idMat3::idMat3() { 414 } 415 416 ID_INLINE idMat3::idMat3( const idVec3 &x, const idVec3 &y, const idVec3 &z ) { 417 mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z; 418 mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z; 419 mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z; 420 } 421 422 ID_INLINE idMat3::idMat3( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) { 423 mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz; 424 mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz; 425 mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz; 426 } 427 428 ID_INLINE idMat3::idMat3( const float src[ 3 ][ 3 ] ) { 429 memcpy( mat, src, 3 * 3 * sizeof( float ) ); 430 } 431 432 ID_INLINE const idVec3 &idMat3::operator[]( int index ) const { 433 //assert( ( index >= 0 ) && ( index < 3 ) ); 434 return mat[ index ]; 435 } 436 437 ID_INLINE idVec3 &idMat3::operator[]( int index ) { 438 //assert( ( index >= 0 ) && ( index < 3 ) ); 439 return mat[ index ]; 440 } 441 442 ID_INLINE idMat3 idMat3::operator-() const { 443 return idMat3( -mat[0][0], -mat[0][1], -mat[0][2], 444 -mat[1][0], -mat[1][1], -mat[1][2], 445 -mat[2][0], -mat[2][1], -mat[2][2] ); 446 } 447 448 ID_INLINE idVec3 idMat3::operator*( const idVec3 &vec ) const { 449 return idVec3( 450 mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z, 451 mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z, 452 mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z ); 453 } 454 455 ID_INLINE idMat3 idMat3::operator*( const idMat3 &a ) const { 456 int i, j; 457 const float *m1Ptr, *m2Ptr; 458 float *dstPtr; 459 idMat3 dst; 460 461 m1Ptr = reinterpret_cast<const float *>(this); 462 m2Ptr = reinterpret_cast<const float *>(&a); 463 dstPtr = reinterpret_cast<float *>(&dst); 464 465 for ( i = 0; i < 3; i++ ) { 466 for ( j = 0; j < 3; j++ ) { 467 *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 3 + j ] 468 + m1Ptr[1] * m2Ptr[ 1 * 3 + j ] 469 + m1Ptr[2] * m2Ptr[ 2 * 3 + j ]; 470 dstPtr++; 471 } 472 m1Ptr += 3; 473 } 474 return dst; 475 } 476 477 ID_INLINE idMat3 idMat3::operator*( const float a ) const { 478 return idMat3( 479 mat[0].x * a, mat[0].y * a, mat[0].z * a, 480 mat[1].x * a, mat[1].y * a, mat[1].z * a, 481 mat[2].x * a, mat[2].y * a, mat[2].z * a ); 482 } 483 484 ID_INLINE idMat3 idMat3::operator+( const idMat3 &a ) const { 485 return idMat3( 486 mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z, 487 mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z, 488 mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z ); 489 } 490 491 ID_INLINE idMat3 idMat3::operator-( const idMat3 &a ) const { 492 return idMat3( 493 mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z, 494 mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z, 495 mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z ); 496 } 497 498 ID_INLINE idMat3 &idMat3::operator*=( const float a ) { 499 mat[0].x *= a; mat[0].y *= a; mat[0].z *= a; 500 mat[1].x *= a; mat[1].y *= a; mat[1].z *= a; 501 mat[2].x *= a; mat[2].y *= a; mat[2].z *= a; 502 503 return *this; 504 } 505 506 ID_INLINE idMat3 &idMat3::operator*=( const idMat3 &a ) { 507 int i, j; 508 const float *m2Ptr; 509 float *m1Ptr, dst[3]; 510 511 m1Ptr = reinterpret_cast<float *>(this); 512 m2Ptr = reinterpret_cast<const float *>(&a); 513 514 for ( i = 0; i < 3; i++ ) { 515 for ( j = 0; j < 3; j++ ) { 516 dst[j] = m1Ptr[0] * m2Ptr[ 0 * 3 + j ] 517 + m1Ptr[1] * m2Ptr[ 1 * 3 + j ] 518 + m1Ptr[2] * m2Ptr[ 2 * 3 + j ]; 519 } 520 m1Ptr[0] = dst[0]; m1Ptr[1] = dst[1]; m1Ptr[2] = dst[2]; 521 m1Ptr += 3; 522 } 523 return *this; 524 } 525 526 ID_INLINE idMat3 &idMat3::operator+=( const idMat3 &a ) { 527 mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z; 528 mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z; 529 mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z; 530 531 return *this; 532 } 533 534 ID_INLINE idMat3 &idMat3::operator-=( const idMat3 &a ) { 535 mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z; 536 mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z; 537 mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z; 538 539 return *this; 540 } 541 542 ID_INLINE idVec3 operator*( const idVec3 &vec, const idMat3 &mat ) { 543 return mat * vec; 544 } 545 546 ID_INLINE idMat3 operator*( const float a, const idMat3 &mat ) { 547 return mat * a; 548 } 549 550 ID_INLINE idVec3 &operator*=( idVec3 &vec, const idMat3 &mat ) { 551 float x = mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z; 552 float y = mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z; 553 vec.z = mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z; 554 vec.x = x; 555 vec.y = y; 556 return vec; 557 } 558 559 ID_INLINE bool idMat3::Compare( const idMat3 &a ) const { 560 if ( mat[0].Compare( a[0] ) && 561 mat[1].Compare( a[1] ) && 562 mat[2].Compare( a[2] ) ) { 563 return true; 564 } 565 return false; 566 } 567 568 ID_INLINE bool idMat3::Compare( const idMat3 &a, const float epsilon ) const { 569 if ( mat[0].Compare( a[0], epsilon ) && 570 mat[1].Compare( a[1], epsilon ) && 571 mat[2].Compare( a[2], epsilon ) ) { 572 return true; 573 } 574 return false; 575 } 576 577 ID_INLINE bool idMat3::operator==( const idMat3 &a ) const { 578 return Compare( a ); 579 } 580 581 ID_INLINE bool idMat3::operator!=( const idMat3 &a ) const { 582 return !Compare( a ); 583 } 584 585 ID_INLINE void idMat3::Zero() { 586 memset( mat, 0, sizeof( idMat3 ) ); 587 } 588 589 ID_INLINE void idMat3::Identity() { 590 *this = mat3_identity; 591 } 592 593 ID_INLINE bool idMat3::IsIdentity( const float epsilon ) const { 594 return Compare( mat3_identity, epsilon ); 595 } 596 597 ID_INLINE bool idMat3::IsSymmetric( const float epsilon ) const { 598 if ( idMath::Fabs( mat[0][1] - mat[1][0] ) > epsilon ) { 599 return false; 600 } 601 if ( idMath::Fabs( mat[0][2] - mat[2][0] ) > epsilon ) { 602 return false; 603 } 604 if ( idMath::Fabs( mat[1][2] - mat[2][1] ) > epsilon ) { 605 return false; 606 } 607 return true; 608 } 609 610 ID_INLINE bool idMat3::IsDiagonal( const float epsilon ) const { 611 if ( idMath::Fabs( mat[0][1] ) > epsilon || 612 idMath::Fabs( mat[0][2] ) > epsilon || 613 idMath::Fabs( mat[1][0] ) > epsilon || 614 idMath::Fabs( mat[1][2] ) > epsilon || 615 idMath::Fabs( mat[2][0] ) > epsilon || 616 idMath::Fabs( mat[2][1] ) > epsilon ) { 617 return false; 618 } 619 return true; 620 } 621 622 ID_INLINE bool idMat3::IsRotated() const { 623 return !Compare( mat3_identity ); 624 } 625 626 ID_INLINE void idMat3::ProjectVector( const idVec3 &src, idVec3 &dst ) const { 627 dst.x = src * mat[ 0 ]; 628 dst.y = src * mat[ 1 ]; 629 dst.z = src * mat[ 2 ]; 630 } 631 632 ID_INLINE void idMat3::UnprojectVector( const idVec3 &src, idVec3 &dst ) const { 633 dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z; 634 } 635 636 ID_INLINE bool idMat3::FixDegeneracies() { 637 bool r = mat[0].FixDegenerateNormal(); 638 r |= mat[1].FixDegenerateNormal(); 639 r |= mat[2].FixDegenerateNormal(); 640 return r; 641 } 642 643 ID_INLINE bool idMat3::FixDenormals() { 644 bool r = mat[0].FixDenormals(); 645 r |= mat[1].FixDenormals(); 646 r |= mat[2].FixDenormals(); 647 return r; 648 } 649 650 ID_INLINE float idMat3::Trace() const { 651 return ( mat[0][0] + mat[1][1] + mat[2][2] ); 652 } 653 654 ID_INLINE idMat3 idMat3::OrthoNormalize() const { 655 idMat3 ortho; 656 657 ortho = *this; 658 ortho[ 0 ].Normalize(); 659 ortho[ 2 ].Cross( mat[ 0 ], mat[ 1 ] ); 660 ortho[ 2 ].Normalize(); 661 ortho[ 1 ].Cross( mat[ 2 ], mat[ 0 ] ); 662 ortho[ 1 ].Normalize(); 663 return ortho; 664 } 665 666 ID_INLINE idMat3 &idMat3::OrthoNormalizeSelf() { 667 mat[ 0 ].Normalize(); 668 mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] ); 669 mat[ 2 ].Normalize(); 670 mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] ); 671 mat[ 1 ].Normalize(); 672 return *this; 673 } 674 675 ID_INLINE idMat3 idMat3::Transpose() const { 676 return idMat3( mat[0][0], mat[1][0], mat[2][0], 677 mat[0][1], mat[1][1], mat[2][1], 678 mat[0][2], mat[1][2], mat[2][2] ); 679 } 680 681 ID_INLINE idMat3 &idMat3::TransposeSelf() { 682 float tmp0, tmp1, tmp2; 683 684 tmp0 = mat[0][1]; 685 mat[0][1] = mat[1][0]; 686 mat[1][0] = tmp0; 687 tmp1 = mat[0][2]; 688 mat[0][2] = mat[2][0]; 689 mat[2][0] = tmp1; 690 tmp2 = mat[1][2]; 691 mat[1][2] = mat[2][1]; 692 mat[2][1] = tmp2; 693 694 return *this; 695 } 696 697 ID_INLINE idMat3 idMat3::Inverse() const { 698 idMat3 invMat; 699 700 invMat = *this; 701 verify( invMat.InverseSelf() ); 702 return invMat; 703 } 704 705 ID_INLINE idMat3 idMat3::InverseFast() const { 706 idMat3 invMat; 707 708 invMat = *this; 709 verify( invMat.InverseFastSelf() ); 710 return invMat; 711 } 712 713 ID_INLINE idMat3 idMat3::TransposeMultiply( const idMat3 &b ) const { 714 return idMat3( mat[0].x * b[0].x + mat[1].x * b[1].x + mat[2].x * b[2].x, 715 mat[0].x * b[0].y + mat[1].x * b[1].y + mat[2].x * b[2].y, 716 mat[0].x * b[0].z + mat[1].x * b[1].z + mat[2].x * b[2].z, 717 mat[0].y * b[0].x + mat[1].y * b[1].x + mat[2].y * b[2].x, 718 mat[0].y * b[0].y + mat[1].y * b[1].y + mat[2].y * b[2].y, 719 mat[0].y * b[0].z + mat[1].y * b[1].z + mat[2].y * b[2].z, 720 mat[0].z * b[0].x + mat[1].z * b[1].x + mat[2].z * b[2].x, 721 mat[0].z * b[0].y + mat[1].z * b[1].y + mat[2].z * b[2].y, 722 mat[0].z * b[0].z + mat[1].z * b[1].z + mat[2].z * b[2].z ); 723 } 724 725 ID_INLINE void TransposeMultiply( const idMat3 &transpose, const idMat3 &b, idMat3 &dst ) { 726 dst[0].x = transpose[0].x * b[0].x + transpose[1].x * b[1].x + transpose[2].x * b[2].x; 727 dst[0].y = transpose[0].x * b[0].y + transpose[1].x * b[1].y + transpose[2].x * b[2].y; 728 dst[0].z = transpose[0].x * b[0].z + transpose[1].x * b[1].z + transpose[2].x * b[2].z; 729 dst[1].x = transpose[0].y * b[0].x + transpose[1].y * b[1].x + transpose[2].y * b[2].x; 730 dst[1].y = transpose[0].y * b[0].y + transpose[1].y * b[1].y + transpose[2].y * b[2].y; 731 dst[1].z = transpose[0].y * b[0].z + transpose[1].y * b[1].z + transpose[2].y * b[2].z; 732 dst[2].x = transpose[0].z * b[0].x + transpose[1].z * b[1].x + transpose[2].z * b[2].x; 733 dst[2].y = transpose[0].z * b[0].y + transpose[1].z * b[1].y + transpose[2].z * b[2].y; 734 dst[2].z = transpose[0].z * b[0].z + transpose[1].z * b[1].z + transpose[2].z * b[2].z; 735 } 736 737 ID_INLINE idMat3 SkewSymmetric( idVec3 const &src ) { 738 return idMat3( 0.0f, -src.z, src.y, src.z, 0.0f, -src.x, -src.y, src.x, 0.0f ); 739 } 740 741 ID_INLINE int idMat3::GetDimension() const { 742 return 9; 743 } 744 745 ID_INLINE const float *idMat3::ToFloatPtr() const { 746 return mat[0].ToFloatPtr(); 747 } 748 749 ID_INLINE float *idMat3::ToFloatPtr() { 750 return mat[0].ToFloatPtr(); 751 } 752 753 754 //=============================================================== 755 // 756 // idMat4 - 4x4 matrix 757 // 758 //=============================================================== 759 760 class idMat4 { 761 public: 762 idMat4(); 763 explicit idMat4( const idVec4 &x, const idVec4 &y, const idVec4 &z, const idVec4 &w ); 764 explicit idMat4(const float xx, const float xy, const float xz, const float xw, 765 const float yx, const float yy, const float yz, const float yw, 766 const float zx, const float zy, const float zz, const float zw, 767 const float wx, const float wy, const float wz, const float ww ); 768 explicit idMat4( const idMat3 &rotation, const idVec3 &translation ); 769 explicit idMat4( const float src[ 4 ][ 4 ] ); 770 771 const idVec4 & operator[]( int index ) const; 772 idVec4 & operator[]( int index ); 773 idMat4 operator*( const float a ) const; 774 idVec4 operator*( const idVec4 &vec ) const; 775 idVec3 operator*( const idVec3 &vec ) const; 776 idMat4 operator*( const idMat4 &a ) const; 777 idMat4 operator+( const idMat4 &a ) const; 778 idMat4 operator-( const idMat4 &a ) const; 779 idMat4 & operator*=( const float a ); 780 idMat4 & operator*=( const idMat4 &a ); 781 idMat4 & operator+=( const idMat4 &a ); 782 idMat4 & operator-=( const idMat4 &a ); 783 784 friend idMat4 operator*( const float a, const idMat4 &mat ); 785 friend idVec4 operator*( const idVec4 &vec, const idMat4 &mat ); 786 friend idVec3 operator*( const idVec3 &vec, const idMat4 &mat ); 787 friend idVec4 & operator*=( idVec4 &vec, const idMat4 &mat ); 788 friend idVec3 & operator*=( idVec3 &vec, const idMat4 &mat ); 789 790 bool Compare( const idMat4 &a ) const; // exact compare, no epsilon 791 bool Compare( const idMat4 &a, const float epsilon ) const; // compare with epsilon 792 bool operator==( const idMat4 &a ) const; // exact compare, no epsilon 793 bool operator!=( const idMat4 &a ) const; // exact compare, no epsilon 794 795 void Zero(); 796 void Identity(); 797 bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const; 798 bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const; 799 bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const; 800 bool IsRotated() const; 801 802 void ProjectVector( const idVec4 &src, idVec4 &dst ) const; 803 void UnprojectVector( const idVec4 &src, idVec4 &dst ) const; 804 805 float Trace() const; 806 float Determinant() const; 807 idMat4 Transpose() const; // returns transpose 808 idMat4 & TransposeSelf(); 809 idMat4 Inverse() const; // returns the inverse ( m * m.Inverse() = identity ) 810 bool InverseSelf(); // returns false if determinant is zero 811 idMat4 InverseFast() const; // returns the inverse ( m * m.Inverse() = identity ) 812 bool InverseFastSelf(); // returns false if determinant is zero 813 idMat4 TransposeMultiply( const idMat4 &b ) const; 814 815 int GetDimension() const; 816 817 const float * ToFloatPtr() const; 818 float * ToFloatPtr(); 819 const char * ToString( int precision = 2 ) const; 820 821 private: 822 idVec4 mat[ 4 ]; 823 }; 824 825 extern idMat4 mat4_zero; 826 extern idMat4 mat4_identity; 827 #define mat4_default mat4_identity 828 829 ID_INLINE idMat4::idMat4() { 830 } 831 832 ID_INLINE idMat4::idMat4( const idVec4 &x, const idVec4 &y, const idVec4 &z, const idVec4 &w ) { 833 mat[ 0 ] = x; 834 mat[ 1 ] = y; 835 mat[ 2 ] = z; 836 mat[ 3 ] = w; 837 } 838 839 ID_INLINE idMat4::idMat4( const float xx, const float xy, const float xz, const float xw, 840 const float yx, const float yy, const float yz, const float yw, 841 const float zx, const float zy, const float zz, const float zw, 842 const float wx, const float wy, const float wz, const float ww ) { 843 mat[0][0] = xx; mat[0][1] = xy; mat[0][2] = xz; mat[0][3] = xw; 844 mat[1][0] = yx; mat[1][1] = yy; mat[1][2] = yz; mat[1][3] = yw; 845 mat[2][0] = zx; mat[2][1] = zy; mat[2][2] = zz; mat[2][3] = zw; 846 mat[3][0] = wx; mat[3][1] = wy; mat[3][2] = wz; mat[3][3] = ww; 847 } 848 849 ID_INLINE idMat4::idMat4( const idMat3 &rotation, const idVec3 &translation ) { 850 // NOTE: idMat3 is transposed because it is column-major 851 mat[ 0 ][ 0 ] = rotation[0][0]; 852 mat[ 0 ][ 1 ] = rotation[1][0]; 853 mat[ 0 ][ 2 ] = rotation[2][0]; 854 mat[ 0 ][ 3 ] = translation[0]; 855 mat[ 1 ][ 0 ] = rotation[0][1]; 856 mat[ 1 ][ 1 ] = rotation[1][1]; 857 mat[ 1 ][ 2 ] = rotation[2][1]; 858 mat[ 1 ][ 3 ] = translation[1]; 859 mat[ 2 ][ 0 ] = rotation[0][2]; 860 mat[ 2 ][ 1 ] = rotation[1][2]; 861 mat[ 2 ][ 2 ] = rotation[2][2]; 862 mat[ 2 ][ 3 ] = translation[2]; 863 mat[ 3 ][ 0 ] = 0.0f; 864 mat[ 3 ][ 1 ] = 0.0f; 865 mat[ 3 ][ 2 ] = 0.0f; 866 mat[ 3 ][ 3 ] = 1.0f; 867 } 868 869 ID_INLINE idMat4::idMat4( const float src[ 4 ][ 4 ] ) { 870 memcpy( mat, src, 4 * 4 * sizeof( float ) ); 871 } 872 873 ID_INLINE const idVec4 &idMat4::operator[]( int index ) const { 874 //assert( ( index >= 0 ) && ( index < 4 ) ); 875 return mat[ index ]; 876 } 877 878 ID_INLINE idVec4 &idMat4::operator[]( int index ) { 879 //assert( ( index >= 0 ) && ( index < 4 ) ); 880 return mat[ index ]; 881 } 882 883 ID_INLINE idMat4 idMat4::operator*( const float a ) const { 884 return idMat4( 885 mat[0].x * a, mat[0].y * a, mat[0].z * a, mat[0].w * a, 886 mat[1].x * a, mat[1].y * a, mat[1].z * a, mat[1].w * a, 887 mat[2].x * a, mat[2].y * a, mat[2].z * a, mat[2].w * a, 888 mat[3].x * a, mat[3].y * a, mat[3].z * a, mat[3].w * a ); 889 } 890 891 ID_INLINE idVec4 idMat4::operator*( const idVec4 &vec ) const { 892 return idVec4( 893 mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w * vec.w, 894 mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w * vec.w, 895 mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w * vec.w, 896 mat[ 3 ].x * vec.x + mat[ 3 ].y * vec.y + mat[ 3 ].z * vec.z + mat[ 3 ].w * vec.w ); 897 } 898 899 ID_INLINE idVec3 idMat4::operator*( const idVec3 &vec ) const { 900 float s = mat[ 3 ].x * vec.x + mat[ 3 ].y * vec.y + mat[ 3 ].z * vec.z + mat[ 3 ].w; 901 if ( s == 0.0f ) { 902 return idVec3( 0.0f, 0.0f, 0.0f ); 903 } 904 if ( s == 1.0f ) { 905 return idVec3( 906 mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w, 907 mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w, 908 mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w ); 909 } 910 else { 911 float invS = 1.0f / s; 912 return idVec3( 913 (mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w) * invS, 914 (mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w) * invS, 915 (mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w) * invS ); 916 } 917 } 918 919 ID_INLINE idMat4 idMat4::operator*( const idMat4 &a ) const { 920 int i, j; 921 const float *m1Ptr, *m2Ptr; 922 float *dstPtr; 923 idMat4 dst; 924 925 m1Ptr = reinterpret_cast<const float *>(this); 926 m2Ptr = reinterpret_cast<const float *>(&a); 927 dstPtr = reinterpret_cast<float *>(&dst); 928 929 for ( i = 0; i < 4; i++ ) { 930 for ( j = 0; j < 4; j++ ) { 931 *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 4 + j ] 932 + m1Ptr[1] * m2Ptr[ 1 * 4 + j ] 933 + m1Ptr[2] * m2Ptr[ 2 * 4 + j ] 934 + m1Ptr[3] * m2Ptr[ 3 * 4 + j ]; 935 dstPtr++; 936 } 937 m1Ptr += 4; 938 } 939 return dst; 940 } 941 942 ID_INLINE idMat4 idMat4::operator+( const idMat4 &a ) const { 943 return idMat4( 944 mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z, mat[0].w + a[0].w, 945 mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z, mat[1].w + a[1].w, 946 mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z, mat[2].w + a[2].w, 947 mat[3].x + a[3].x, mat[3].y + a[3].y, mat[3].z + a[3].z, mat[3].w + a[3].w ); 948 } 949 950 ID_INLINE idMat4 idMat4::operator-( const idMat4 &a ) const { 951 return idMat4( 952 mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z, mat[0].w - a[0].w, 953 mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z, mat[1].w - a[1].w, 954 mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z, mat[2].w - a[2].w, 955 mat[3].x - a[3].x, mat[3].y - a[3].y, mat[3].z - a[3].z, mat[3].w - a[3].w ); 956 } 957 958 ID_INLINE idMat4 &idMat4::operator*=( const float a ) { 959 mat[0].x *= a; mat[0].y *= a; mat[0].z *= a; mat[0].w *= a; 960 mat[1].x *= a; mat[1].y *= a; mat[1].z *= a; mat[1].w *= a; 961 mat[2].x *= a; mat[2].y *= a; mat[2].z *= a; mat[2].w *= a; 962 mat[3].x *= a; mat[3].y *= a; mat[3].z *= a; mat[3].w *= a; 963 return *this; 964 } 965 966 ID_INLINE idMat4 &idMat4::operator*=( const idMat4 &a ) { 967 *this = (*this) * a; 968 return *this; 969 } 970 971 ID_INLINE idMat4 &idMat4::operator+=( const idMat4 &a ) { 972 mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z; mat[0].w += a[0].w; 973 mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z; mat[1].w += a[1].w; 974 mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z; mat[2].w += a[2].w; 975 mat[3].x += a[3].x; mat[3].y += a[3].y; mat[3].z += a[3].z; mat[3].w += a[3].w; 976 return *this; 977 } 978 979 ID_INLINE idMat4 &idMat4::operator-=( const idMat4 &a ) { 980 mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z; mat[0].w -= a[0].w; 981 mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z; mat[1].w -= a[1].w; 982 mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z; mat[2].w -= a[2].w; 983 mat[3].x -= a[3].x; mat[3].y -= a[3].y; mat[3].z -= a[3].z; mat[3].w -= a[3].w; 984 return *this; 985 } 986 987 ID_INLINE idMat4 operator*( const float a, const idMat4 &mat ) { 988 return mat * a; 989 } 990 991 ID_INLINE idVec4 operator*( const idVec4 &vec, const idMat4 &mat ) { 992 return mat * vec; 993 } 994 995 ID_INLINE idVec3 operator*( const idVec3 &vec, const idMat4 &mat ) { 996 return mat * vec; 997 } 998 999 ID_INLINE idVec4 &operator*=( idVec4 &vec, const idMat4 &mat ) { 1000 vec = mat * vec; 1001 return vec; 1002 } 1003 1004 ID_INLINE idVec3 &operator*=( idVec3 &vec, const idMat4 &mat ) { 1005 vec = mat * vec; 1006 return vec; 1007 } 1008 1009 ID_INLINE bool idMat4::Compare( const idMat4 &a ) const { 1010 dword i; 1011 const float *ptr1, *ptr2; 1012 1013 ptr1 = reinterpret_cast<const float *>(mat); 1014 ptr2 = reinterpret_cast<const float *>(a.mat); 1015 for ( i = 0; i < 4*4; i++ ) { 1016 if ( ptr1[i] != ptr2[i] ) { 1017 return false; 1018 } 1019 } 1020 return true; 1021 } 1022 1023 ID_INLINE bool idMat4::Compare( const idMat4 &a, const float epsilon ) const { 1024 dword i; 1025 const float *ptr1, *ptr2; 1026 1027 ptr1 = reinterpret_cast<const float *>(mat); 1028 ptr2 = reinterpret_cast<const float *>(a.mat); 1029 for ( i = 0; i < 4*4; i++ ) { 1030 if ( idMath::Fabs( ptr1[i] - ptr2[i] ) > epsilon ) { 1031 return false; 1032 } 1033 } 1034 return true; 1035 } 1036 1037 ID_INLINE bool idMat4::operator==( const idMat4 &a ) const { 1038 return Compare( a ); 1039 } 1040 1041 ID_INLINE bool idMat4::operator!=( const idMat4 &a ) const { 1042 return !Compare( a ); 1043 } 1044 1045 ID_INLINE void idMat4::Zero() { 1046 memset( mat, 0, sizeof( idMat4 ) ); 1047 } 1048 1049 ID_INLINE void idMat4::Identity() { 1050 *this = mat4_identity; 1051 } 1052 1053 ID_INLINE bool idMat4::IsIdentity( const float epsilon ) const { 1054 return Compare( mat4_identity, epsilon ); 1055 } 1056 1057 ID_INLINE bool idMat4::IsSymmetric( const float epsilon ) const { 1058 for ( int i = 1; i < 4; i++ ) { 1059 for ( int j = 0; j < i; j++ ) { 1060 if ( idMath::Fabs( mat[i][j] - mat[j][i] ) > epsilon ) { 1061 return false; 1062 } 1063 } 1064 } 1065 return true; 1066 } 1067 1068 ID_INLINE bool idMat4::IsDiagonal( const float epsilon ) const { 1069 for ( int i = 0; i < 4; i++ ) { 1070 for ( int j = 0; j < 4; j++ ) { 1071 if ( i != j && idMath::Fabs( mat[i][j] ) > epsilon ) { 1072 return false; 1073 } 1074 } 1075 } 1076 return true; 1077 } 1078 1079 ID_INLINE bool idMat4::IsRotated() const { 1080 if ( !mat[ 0 ][ 1 ] && !mat[ 0 ][ 2 ] && 1081 !mat[ 1 ][ 0 ] && !mat[ 1 ][ 2 ] && 1082 !mat[ 2 ][ 0 ] && !mat[ 2 ][ 1 ] ) { 1083 return false; 1084 } 1085 return true; 1086 } 1087 1088 ID_INLINE void idMat4::ProjectVector( const idVec4 &src, idVec4 &dst ) const { 1089 dst.x = src * mat[ 0 ]; 1090 dst.y = src * mat[ 1 ]; 1091 dst.z = src * mat[ 2 ]; 1092 dst.w = src * mat[ 3 ]; 1093 } 1094 1095 ID_INLINE void idMat4::UnprojectVector( const idVec4 &src, idVec4 &dst ) const { 1096 dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z + mat[ 3 ] * src.w; 1097 } 1098 1099 ID_INLINE float idMat4::Trace() const { 1100 return ( mat[0][0] + mat[1][1] + mat[2][2] + mat[3][3] ); 1101 } 1102 1103 ID_INLINE idMat4 idMat4::Inverse() const { 1104 idMat4 invMat; 1105 1106 invMat = *this; 1107 verify( invMat.InverseSelf() ); 1108 return invMat; 1109 } 1110 1111 ID_INLINE idMat4 idMat4::InverseFast() const { 1112 idMat4 invMat; 1113 1114 invMat = *this; 1115 verify( invMat.InverseFastSelf() ); 1116 return invMat; 1117 } 1118 1119 ID_INLINE idMat4 idMat3::ToMat4() const { 1120 // NOTE: idMat3 is transposed because it is column-major 1121 return idMat4( mat[0][0], mat[1][0], mat[2][0], 0.0f, 1122 mat[0][1], mat[1][1], mat[2][1], 0.0f, 1123 mat[0][2], mat[1][2], mat[2][2], 0.0f, 1124 0.0f, 0.0f, 0.0f, 1.0f ); 1125 } 1126 1127 ID_INLINE int idMat4::GetDimension() const { 1128 return 16; 1129 } 1130 1131 ID_INLINE const float *idMat4::ToFloatPtr() const { 1132 return mat[0].ToFloatPtr(); 1133 } 1134 1135 ID_INLINE float *idMat4::ToFloatPtr() { 1136 return mat[0].ToFloatPtr(); 1137 } 1138 1139 1140 //=============================================================== 1141 // 1142 // idMat5 - 5x5 matrix 1143 // 1144 //=============================================================== 1145 1146 class idMat5 { 1147 public: 1148 idMat5(); 1149 explicit idMat5( const idVec5 &v0, const idVec5 &v1, const idVec5 &v2, const idVec5 &v3, const idVec5 &v4 ); 1150 explicit idMat5( const float src[ 5 ][ 5 ] ); 1151 1152 const idVec5 & operator[]( int index ) const; 1153 idVec5 & operator[]( int index ); 1154 idMat5 operator*( const float a ) const; 1155 idVec5 operator*( const idVec5 &vec ) const; 1156 idMat5 operator*( const idMat5 &a ) const; 1157 idMat5 operator+( const idMat5 &a ) const; 1158 idMat5 operator-( const idMat5 &a ) const; 1159 idMat5 & operator*=( const float a ); 1160 idMat5 & operator*=( const idMat5 &a ); 1161 idMat5 & operator+=( const idMat5 &a ); 1162 idMat5 & operator-=( const idMat5 &a ); 1163 1164 friend idMat5 operator*( const float a, const idMat5 &mat ); 1165 friend idVec5 operator*( const idVec5 &vec, const idMat5 &mat ); 1166 friend idVec5 & operator*=( idVec5 &vec, const idMat5 &mat ); 1167 1168 bool Compare( const idMat5 &a ) const; // exact compare, no epsilon 1169 bool Compare( const idMat5 &a, const float epsilon ) const; // compare with epsilon 1170 bool operator==( const idMat5 &a ) const; // exact compare, no epsilon 1171 bool operator!=( const idMat5 &a ) const; // exact compare, no epsilon 1172 1173 void Zero(); 1174 void Identity(); 1175 bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const; 1176 bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const; 1177 bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const; 1178 1179 float Trace() const; 1180 float Determinant() const; 1181 idMat5 Transpose() const; // returns transpose 1182 idMat5 & TransposeSelf(); 1183 idMat5 Inverse() const; // returns the inverse ( m * m.Inverse() = identity ) 1184 bool InverseSelf(); // returns false if determinant is zero 1185 idMat5 InverseFast() const; // returns the inverse ( m * m.Inverse() = identity ) 1186 bool InverseFastSelf(); // returns false if determinant is zero 1187 1188 int GetDimension() const; 1189 1190 const float * ToFloatPtr() const; 1191 float * ToFloatPtr(); 1192 const char * ToString( int precision = 2 ) const; 1193 1194 private: 1195 idVec5 mat[ 5 ]; 1196 }; 1197 1198 extern idMat5 mat5_zero; 1199 extern idMat5 mat5_identity; 1200 #define mat5_default mat5_identity 1201 1202 ID_INLINE idMat5::idMat5() { 1203 } 1204 1205 ID_INLINE idMat5::idMat5( const float src[ 5 ][ 5 ] ) { 1206 memcpy( mat, src, 5 * 5 * sizeof( float ) ); 1207 } 1208 1209 ID_INLINE idMat5::idMat5( const idVec5 &v0, const idVec5 &v1, const idVec5 &v2, const idVec5 &v3, const idVec5 &v4 ) { 1210 mat[0] = v0; 1211 mat[1] = v1; 1212 mat[2] = v2; 1213 mat[3] = v3; 1214 mat[4] = v4; 1215 } 1216 1217 ID_INLINE const idVec5 &idMat5::operator[]( int index ) const { 1218 //assert( ( index >= 0 ) && ( index < 5 ) ); 1219 return mat[ index ]; 1220 } 1221 1222 ID_INLINE idVec5 &idMat5::operator[]( int index ) { 1223 //assert( ( index >= 0 ) && ( index < 5 ) ); 1224 return mat[ index ]; 1225 } 1226 1227 ID_INLINE idMat5 idMat5::operator*( const idMat5 &a ) const { 1228 int i, j; 1229 const float *m1Ptr, *m2Ptr; 1230 float *dstPtr; 1231 idMat5 dst; 1232 1233 m1Ptr = reinterpret_cast<const float *>(this); 1234 m2Ptr = reinterpret_cast<const float *>(&a); 1235 dstPtr = reinterpret_cast<float *>(&dst); 1236 1237 for ( i = 0; i < 5; i++ ) { 1238 for ( j = 0; j < 5; j++ ) { 1239 *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 5 + j ] 1240 + m1Ptr[1] * m2Ptr[ 1 * 5 + j ] 1241 + m1Ptr[2] * m2Ptr[ 2 * 5 + j ] 1242 + m1Ptr[3] * m2Ptr[ 3 * 5 + j ] 1243 + m1Ptr[4] * m2Ptr[ 4 * 5 + j ]; 1244 dstPtr++; 1245 } 1246 m1Ptr += 5; 1247 } 1248 return dst; 1249 } 1250 1251 ID_INLINE idMat5 idMat5::operator*( const float a ) const { 1252 return idMat5( 1253 idVec5( mat[0][0] * a, mat[0][1] * a, mat[0][2] * a, mat[0][3] * a, mat[0][4] * a ), 1254 idVec5( mat[1][0] * a, mat[1][1] * a, mat[1][2] * a, mat[1][3] * a, mat[1][4] * a ), 1255 idVec5( mat[2][0] * a, mat[2][1] * a, mat[2][2] * a, mat[2][3] * a, mat[2][4] * a ), 1256 idVec5( mat[3][0] * a, mat[3][1] * a, mat[3][2] * a, mat[3][3] * a, mat[3][4] * a ), 1257 idVec5( mat[4][0] * a, mat[4][1] * a, mat[4][2] * a, mat[4][3] * a, mat[4][4] * a ) ); 1258 } 1259 1260 ID_INLINE idVec5 idMat5::operator*( const idVec5 &vec ) const { 1261 return idVec5( 1262 mat[0][0] * vec[0] + mat[0][1] * vec[1] + mat[0][2] * vec[2] + mat[0][3] * vec[3] + mat[0][4] * vec[4], 1263 mat[1][0] * vec[0] + mat[1][1] * vec[1] + mat[1][2] * vec[2] + mat[1][3] * vec[3] + mat[1][4] * vec[4], 1264 mat[2][0] * vec[0] + mat[2][1] * vec[1] + mat[2][2] * vec[2] + mat[2][3] * vec[3] + mat[2][4] * vec[4], 1265 mat[3][0] * vec[0] + mat[3][1] * vec[1] + mat[3][2] * vec[2] + mat[3][3] * vec[3] + mat[3][4] * vec[4], 1266 mat[4][0] * vec[0] + mat[4][1] * vec[1] + mat[4][2] * vec[2] + mat[4][3] * vec[3] + mat[4][4] * vec[4] ); 1267 } 1268 1269 ID_INLINE idMat5 idMat5::operator+( const idMat5 &a ) const { 1270 return idMat5( 1271 idVec5( mat[0][0] + a[0][0], mat[0][1] + a[0][1], mat[0][2] + a[0][2], mat[0][3] + a[0][3], mat[0][4] + a[0][4] ), 1272 idVec5( mat[1][0] + a[1][0], mat[1][1] + a[1][1], mat[1][2] + a[1][2], mat[1][3] + a[1][3], mat[1][4] + a[1][4] ), 1273 idVec5( mat[2][0] + a[2][0], mat[2][1] + a[2][1], mat[2][2] + a[2][2], mat[2][3] + a[2][3], mat[2][4] + a[2][4] ), 1274 idVec5( mat[3][0] + a[3][0], mat[3][1] + a[3][1], mat[3][2] + a[3][2], mat[3][3] + a[3][3], mat[3][4] + a[3][4] ), 1275 idVec5( mat[4][0] + a[4][0], mat[4][1] + a[4][1], mat[4][2] + a[4][2], mat[4][3] + a[4][3], mat[4][4] + a[4][4] ) ); 1276 } 1277 1278 ID_INLINE idMat5 idMat5::operator-( const idMat5 &a ) const { 1279 return idMat5( 1280 idVec5( mat[0][0] - a[0][0], mat[0][1] - a[0][1], mat[0][2] - a[0][2], mat[0][3] - a[0][3], mat[0][4] - a[0][4] ), 1281 idVec5( mat[1][0] - a[1][0], mat[1][1] - a[1][1], mat[1][2] - a[1][2], mat[1][3] - a[1][3], mat[1][4] - a[1][4] ), 1282 idVec5( mat[2][0] - a[2][0], mat[2][1] - a[2][1], mat[2][2] - a[2][2], mat[2][3] - a[2][3], mat[2][4] - a[2][4] ), 1283 idVec5( mat[3][0] - a[3][0], mat[3][1] - a[3][1], mat[3][2] - a[3][2], mat[3][3] - a[3][3], mat[3][4] - a[3][4] ), 1284 idVec5( mat[4][0] - a[4][0], mat[4][1] - a[4][1], mat[4][2] - a[4][2], mat[4][3] - a[4][3], mat[4][4] - a[4][4] ) ); 1285 } 1286 1287 ID_INLINE idMat5 &idMat5::operator*=( const float a ) { 1288 mat[0][0] *= a; mat[0][1] *= a; mat[0][2] *= a; mat[0][3] *= a; mat[0][4] *= a; 1289 mat[1][0] *= a; mat[1][1] *= a; mat[1][2] *= a; mat[1][3] *= a; mat[1][4] *= a; 1290 mat[2][0] *= a; mat[2][1] *= a; mat[2][2] *= a; mat[2][3] *= a; mat[2][4] *= a; 1291 mat[3][0] *= a; mat[3][1] *= a; mat[3][2] *= a; mat[3][3] *= a; mat[3][4] *= a; 1292 mat[4][0] *= a; mat[4][1] *= a; mat[4][2] *= a; mat[4][3] *= a; mat[4][4] *= a; 1293 return *this; 1294 } 1295 1296 ID_INLINE idMat5 &idMat5::operator*=( const idMat5 &a ) { 1297 *this = *this * a; 1298 return *this; 1299 } 1300 1301 ID_INLINE idMat5 &idMat5::operator+=( const idMat5 &a ) { 1302 mat[0][0] += a[0][0]; mat[0][1] += a[0][1]; mat[0][2] += a[0][2]; mat[0][3] += a[0][3]; mat[0][4] += a[0][4]; 1303 mat[1][0] += a[1][0]; mat[1][1] += a[1][1]; mat[1][2] += a[1][2]; mat[1][3] += a[1][3]; mat[1][4] += a[1][4]; 1304 mat[2][0] += a[2][0]; mat[2][1] += a[2][1]; mat[2][2] += a[2][2]; mat[2][3] += a[2][3]; mat[2][4] += a[2][4]; 1305 mat[3][0] += a[3][0]; mat[3][1] += a[3][1]; mat[3][2] += a[3][2]; mat[3][3] += a[3][3]; mat[3][4] += a[3][4]; 1306 mat[4][0] += a[4][0]; mat[4][1] += a[4][1]; mat[4][2] += a[4][2]; mat[4][3] += a[4][3]; mat[4][4] += a[4][4]; 1307 return *this; 1308 } 1309 1310 ID_INLINE idMat5 &idMat5::operator-=( const idMat5 &a ) { 1311 mat[0][0] -= a[0][0]; mat[0][1] -= a[0][1]; mat[0][2] -= a[0][2]; mat[0][3] -= a[0][3]; mat[0][4] -= a[0][4]; 1312 mat[1][0] -= a[1][0]; mat[1][1] -= a[1][1]; mat[1][2] -= a[1][2]; mat[1][3] -= a[1][3]; mat[1][4] -= a[1][4]; 1313 mat[2][0] -= a[2][0]; mat[2][1] -= a[2][1]; mat[2][2] -= a[2][2]; mat[2][3] -= a[2][3]; mat[2][4] -= a[2][4]; 1314 mat[3][0] -= a[3][0]; mat[3][1] -= a[3][1]; mat[3][2] -= a[3][2]; mat[3][3] -= a[3][3]; mat[3][4] -= a[3][4]; 1315 mat[4][0] -= a[4][0]; mat[4][1] -= a[4][1]; mat[4][2] -= a[4][2]; mat[4][3] -= a[4][3]; mat[4][4] -= a[4][4]; 1316 return *this; 1317 } 1318 1319 ID_INLINE idVec5 operator*( const idVec5 &vec, const idMat5 &mat ) { 1320 return mat * vec; 1321 } 1322 1323 ID_INLINE idMat5 operator*( const float a, idMat5 const &mat ) { 1324 return mat * a; 1325 } 1326 1327 ID_INLINE idVec5 &operator*=( idVec5 &vec, const idMat5 &mat ) { 1328 vec = mat * vec; 1329 return vec; 1330 } 1331 1332 ID_INLINE bool idMat5::Compare( const idMat5 &a ) const { 1333 dword i; 1334 const float *ptr1, *ptr2; 1335 1336 ptr1 = reinterpret_cast<const float *>(mat); 1337 ptr2 = reinterpret_cast<const float *>(a.mat); 1338 for ( i = 0; i < 5*5; i++ ) { 1339 if ( ptr1[i] != ptr2[i] ) { 1340 return false; 1341 } 1342 } 1343 return true; 1344 } 1345 1346 ID_INLINE bool idMat5::Compare( const idMat5 &a, const float epsilon ) const { 1347 dword i; 1348 const float *ptr1, *ptr2; 1349 1350 ptr1 = reinterpret_cast<const float *>(mat); 1351 ptr2 = reinterpret_cast<const float *>(a.mat); 1352 for ( i = 0; i < 5*5; i++ ) { 1353 if ( idMath::Fabs( ptr1[i] - ptr2[i] ) > epsilon ) { 1354 return false; 1355 } 1356 } 1357 return true; 1358 } 1359 1360 ID_INLINE bool idMat5::operator==( const idMat5 &a ) const { 1361 return Compare( a ); 1362 } 1363 1364 ID_INLINE bool idMat5::operator!=( const idMat5 &a ) const { 1365 return !Compare( a ); 1366 } 1367 1368 ID_INLINE void idMat5::Zero() { 1369 memset( mat, 0, sizeof( idMat5 ) ); 1370 } 1371 1372 ID_INLINE void idMat5::Identity() { 1373 *this = mat5_identity; 1374 } 1375 1376 ID_INLINE bool idMat5::IsIdentity( const float epsilon ) const { 1377 return Compare( mat5_identity, epsilon ); 1378 } 1379 1380 ID_INLINE bool idMat5::IsSymmetric( const float epsilon ) const { 1381 for ( int i = 1; i < 5; i++ ) { 1382 for ( int j = 0; j < i; j++ ) { 1383 if ( idMath::Fabs( mat[i][j] - mat[j][i] ) > epsilon ) { 1384 return false; 1385 } 1386 } 1387 } 1388 return true; 1389 } 1390 1391 ID_INLINE bool idMat5::IsDiagonal( const float epsilon ) const { 1392 for ( int i = 0; i < 5; i++ ) { 1393 for ( int j = 0; j < 5; j++ ) { 1394 if ( i != j && idMath::Fabs( mat[i][j] ) > epsilon ) { 1395 return false; 1396 } 1397 } 1398 } 1399 return true; 1400 } 1401 1402 ID_INLINE float idMat5::Trace() const { 1403 return ( mat[0][0] + mat[1][1] + mat[2][2] + mat[3][3] + mat[4][4] ); 1404 } 1405 1406 ID_INLINE idMat5 idMat5::Inverse() const { 1407 idMat5 invMat; 1408 1409 invMat = *this; 1410 verify( invMat.InverseSelf() ); 1411 return invMat; 1412 } 1413 1414 ID_INLINE idMat5 idMat5::InverseFast() const { 1415 idMat5 invMat; 1416 1417 invMat = *this; 1418 verify( invMat.InverseFastSelf() ); 1419 return invMat; 1420 } 1421 1422 ID_INLINE int idMat5::GetDimension() const { 1423 return 25; 1424 } 1425 1426 ID_INLINE const float *idMat5::ToFloatPtr() const { 1427 return mat[0].ToFloatPtr(); 1428 } 1429 1430 ID_INLINE float *idMat5::ToFloatPtr() { 1431 return mat[0].ToFloatPtr(); 1432 } 1433 1434 1435 //=============================================================== 1436 // 1437 // idMat6 - 6x6 matrix 1438 // 1439 //=============================================================== 1440 1441 class idMat6 { 1442 public: 1443 idMat6(); 1444 explicit idMat6( const idVec6 &v0, const idVec6 &v1, const idVec6 &v2, const idVec6 &v3, const idVec6 &v4, const idVec6 &v5 ); 1445 explicit idMat6( const idMat3 &m0, const idMat3 &m1, const idMat3 &m2, const idMat3 &m3 ); 1446 explicit idMat6( const float src[ 6 ][ 6 ] ); 1447 1448 const idVec6 & operator[]( int index ) const; 1449 idVec6 & operator[]( int index ); 1450 idMat6 operator*( const float a ) const; 1451 idVec6 operator*( const idVec6 &vec ) const; 1452 idMat6 operator*( const idMat6 &a ) const; 1453 idMat6 operator+( const idMat6 &a ) const; 1454 idMat6 operator-( const idMat6 &a ) const; 1455 idMat6 & operator*=( const float a ); 1456 idMat6 & operator*=( const idMat6 &a ); 1457 idMat6 & operator+=( const idMat6 &a ); 1458 idMat6 & operator-=( const idMat6 &a ); 1459 1460 friend idMat6 operator*( const float a, const idMat6 &mat ); 1461 friend idVec6 operator*( const idVec6 &vec, const idMat6 &mat ); 1462 friend idVec6 & operator*=( idVec6 &vec, const idMat6 &mat ); 1463 1464 bool Compare( const idMat6 &a ) const; // exact compare, no epsilon 1465 bool Compare( const idMat6 &a, const float epsilon ) const; // compare with epsilon 1466 bool operator==( const idMat6 &a ) const; // exact compare, no epsilon 1467 bool operator!=( const idMat6 &a ) const; // exact compare, no epsilon 1468 1469 void Zero(); 1470 void Identity(); 1471 bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const; 1472 bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const; 1473 bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const; 1474 1475 idMat3 SubMat3( int n ) const; 1476 float Trace() const; 1477 float Determinant() const; 1478 idMat6 Transpose() const; // returns transpose 1479 idMat6 & TransposeSelf(); 1480 idMat6 Inverse() const; // returns the inverse ( m * m.Inverse() = identity ) 1481 bool InverseSelf(); // returns false if determinant is zero 1482 idMat6 InverseFast() const; // returns the inverse ( m * m.Inverse() = identity ) 1483 bool InverseFastSelf(); // returns false if determinant is zero 1484 1485 int GetDimension() const; 1486 1487 const float * ToFloatPtr() const; 1488 float * ToFloatPtr(); 1489 const char * ToString( int precision = 2 ) const; 1490 1491 private: 1492 idVec6 mat[ 6 ]; 1493 }; 1494 1495 extern idMat6 mat6_zero; 1496 extern idMat6 mat6_identity; 1497 #define mat6_default mat6_identity 1498 1499 ID_INLINE idMat6::idMat6() { 1500 } 1501 1502 ID_INLINE idMat6::idMat6( const idMat3 &m0, const idMat3 &m1, const idMat3 &m2, const idMat3 &m3 ) { 1503 mat[0] = idVec6( m0[0][0], m0[0][1], m0[0][2], m1[0][0], m1[0][1], m1[0][2] ); 1504 mat[1] = idVec6( m0[1][0], m0[1][1], m0[1][2], m1[1][0], m1[1][1], m1[1][2] ); 1505 mat[2] = idVec6( m0[2][0], m0[2][1], m0[2][2], m1[2][0], m1[2][1], m1[2][2] ); 1506 mat[3] = idVec6( m2[0][0], m2[0][1], m2[0][2], m3[0][0], m3[0][1], m3[0][2] ); 1507 mat[4] = idVec6( m2[1][0], m2[1][1], m2[1][2], m3[1][0], m3[1][1], m3[1][2] ); 1508 mat[5] = idVec6( m2[2][0], m2[2][1], m2[2][2], m3[2][0], m3[2][1], m3[2][2] ); 1509 } 1510 1511 ID_INLINE idMat6::idMat6( const idVec6 &v0, const idVec6 &v1, const idVec6 &v2, const idVec6 &v3, const idVec6 &v4, const idVec6 &v5 ) { 1512 mat[0] = v0; 1513 mat[1] = v1; 1514 mat[2] = v2; 1515 mat[3] = v3; 1516 mat[4] = v4; 1517 mat[5] = v5; 1518 } 1519 1520 ID_INLINE idMat6::idMat6( const float src[ 6 ][ 6 ] ) { 1521 memcpy( mat, src, 6 * 6 * sizeof( float ) ); 1522 } 1523 1524 ID_INLINE const idVec6 &idMat6::operator[]( int index ) const { 1525 //assert( ( index >= 0 ) && ( index < 6 ) ); 1526 return mat[ index ]; 1527 } 1528 1529 ID_INLINE idVec6 &idMat6::operator[]( int index ) { 1530 //assert( ( index >= 0 ) && ( index < 6 ) ); 1531 return mat[ index ]; 1532 } 1533 1534 ID_INLINE idMat6 idMat6::operator*( const idMat6 &a ) const { 1535 int i, j; 1536 const float *m1Ptr, *m2Ptr; 1537 float *dstPtr; 1538 idMat6 dst; 1539 1540 m1Ptr = reinterpret_cast<const float *>(this); 1541 m2Ptr = reinterpret_cast<const float *>(&a); 1542 dstPtr = reinterpret_cast<float *>(&dst); 1543 1544 for ( i = 0; i < 6; i++ ) { 1545 for ( j = 0; j < 6; j++ ) { 1546 *dstPtr = m1Ptr[0] * m2Ptr[ 0 * 6 + j ] 1547 + m1Ptr[1] * m2Ptr[ 1 * 6 + j ] 1548 + m1Ptr[2] * m2Ptr[ 2 * 6 + j ] 1549 + m1Ptr[3] * m2Ptr[ 3 * 6 + j ] 1550 + m1Ptr[4] * m2Ptr[ 4 * 6 + j ] 1551 + m1Ptr[5] * m2Ptr[ 5 * 6 + j ]; 1552 dstPtr++; 1553 } 1554 m1Ptr += 6; 1555 } 1556 return dst; 1557 } 1558 1559 ID_INLINE idMat6 idMat6::operator*( const float a ) const { 1560 return idMat6( 1561 idVec6( mat[0][0] * a, mat[0][1] * a, mat[0][2] * a, mat[0][3] * a, mat[0][4] * a, mat[0][5] * a ), 1562 idVec6( mat[1][0] * a, mat[1][1] * a, mat[1][2] * a, mat[1][3] * a, mat[1][4] * a, mat[1][5] * a ), 1563 idVec6( mat[2][0] * a, mat[2][1] * a, mat[2][2] * a, mat[2][3] * a, mat[2][4] * a, mat[2][5] * a ), 1564 idVec6( mat[3][0] * a, mat[3][1] * a, mat[3][2] * a, mat[3][3] * a, mat[3][4] * a, mat[3][5] * a ), 1565 idVec6( mat[4][0] * a, mat[4][1] * a, mat[4][2] * a, mat[4][3] * a, mat[4][4] * a, mat[4][5] * a ), 1566 idVec6( mat[5][0] * a, mat[5][1] * a, mat[5][2] * a, mat[5][3] * a, mat[5][4] * a, mat[5][5] * a ) ); 1567 } 1568 1569 ID_INLINE idVec6 idMat6::operator*( const idVec6 &vec ) const { 1570 return idVec6( 1571 mat[0][0] * vec[0] + mat[0][1] * vec[1] + mat[0][2] * vec[2] + mat[0][3] * vec[3] + mat[0][4] * vec[4] + mat[0][5] * vec[5], 1572 mat[1][0] * vec[0] + mat[1][1] * vec[1] + mat[1][2] * vec[2] + mat[1][3] * vec[3] + mat[1][4] * vec[4] + mat[1][5] * vec[5], 1573 mat[2][0] * vec[0] + mat[2][1] * vec[1] + mat[2][2] * vec[2] + mat[2][3] * vec[3] + mat[2][4] * vec[4] + mat[2][5] * vec[5], 1574 mat[3][0] * vec[0] + mat[3][1] * vec[1] + mat[3][2] * vec[2] + mat[3][3] * vec[3] + mat[3][4] * vec[4] + mat[3][5] * vec[5], 1575 mat[4][0] * vec[0] + mat[4][1] * vec[1] + mat[4][2] * vec[2] + mat[4][3] * vec[3] + mat[4][4] * vec[4] + mat[4][5] * vec[5], 1576 mat[5][0] * vec[0] + mat[5][1] * vec[1] + mat[5][2] * vec[2] + mat[5][3] * vec[3] + mat[5][4] * vec[4] + mat[5][5] * vec[5] ); 1577 } 1578 1579 ID_INLINE idMat6 idMat6::operator+( const idMat6 &a ) const { 1580 return idMat6( 1581 idVec6( mat[0][0] + a[0][0], mat[0][1] + a[0][1], mat[0][2] + a[0][2], mat[0][3] + a[0][3], mat[0][4] + a[0][4], mat[0][5] + a[0][5] ), 1582 idVec6( mat[1][0] + a[1][0], mat[1][1] + a[1][1], mat[1][2] + a[1][2], mat[1][3] + a[1][3], mat[1][4] + a[1][4], mat[1][5] + a[1][5] ), 1583 idVec6( mat[2][0] + a[2][0], mat[2][1] + a[2][1], mat[2][2] + a[2][2], mat[2][3] + a[2][3], mat[2][4] + a[2][4], mat[2][5] + a[2][5] ), 1584 idVec6( mat[3][0] + a[3][0], mat[3][1] + a[3][1], mat[3][2] + a[3][2], mat[3][3] + a[3][3], mat[3][4] + a[3][4], mat[3][5] + a[3][5] ), 1585 idVec6( mat[4][0] + a[4][0], mat[4][1] + a[4][1], mat[4][2] + a[4][2], mat[4][3] + a[4][3], mat[4][4] + a[4][4], mat[4][5] + a[4][5] ), 1586 idVec6( mat[5][0] + a[5][0], mat[5][1] + a[5][1], mat[5][2] + a[5][2], mat[5][3] + a[5][3], mat[5][4] + a[5][4], mat[5][5] + a[5][5] ) ); 1587 } 1588 1589 ID_INLINE idMat6 idMat6::operator-( const idMat6 &a ) const { 1590 return idMat6( 1591 idVec6( mat[0][0] - a[0][0], mat[0][1] - a[0][1], mat[0][2] - a[0][2], mat[0][3] - a[0][3], mat[0][4] - a[0][4], mat[0][5] - a[0][5] ), 1592 idVec6( mat[1][0] - a[1][0], mat[1][1] - a[1][1], mat[1][2] - a[1][2], mat[1][3] - a[1][3], mat[1][4] - a[1][4], mat[1][5] - a[1][5] ), 1593 idVec6( mat[2][0] - a[2][0], mat[2][1] - a[2][1], mat[2][2] - a[2][2], mat[2][3] - a[2][3], mat[2][4] - a[2][4], mat[2][5] - a[2][5] ), 1594 idVec6( mat[3][0] - a[3][0], mat[3][1] - a[3][1], mat[3][2] - a[3][2], mat[3][3] - a[3][3], mat[3][4] - a[3][4], mat[3][5] - a[3][5] ), 1595 idVec6( mat[4][0] - a[4][0], mat[4][1] - a[4][1], mat[4][2] - a[4][2], mat[4][3] - a[4][3], mat[4][4] - a[4][4], mat[4][5] - a[4][5] ), 1596 idVec6( mat[5][0] - a[5][0], mat[5][1] - a[5][1], mat[5][2] - a[5][2], mat[5][3] - a[5][3], mat[5][4] - a[5][4], mat[5][5] - a[5][5] ) ); 1597 } 1598 1599 ID_INLINE idMat6 &idMat6::operator*=( const float a ) { 1600 mat[0][0] *= a; mat[0][1] *= a; mat[0][2] *= a; mat[0][3] *= a; mat[0][4] *= a; mat[0][5] *= a; 1601 mat[1][0] *= a; mat[1][1] *= a; mat[1][2] *= a; mat[1][3] *= a; mat[1][4] *= a; mat[1][5] *= a; 1602 mat[2][0] *= a; mat[2][1] *= a; mat[2][2] *= a; mat[2][3] *= a; mat[2][4] *= a; mat[2][5] *= a; 1603 mat[3][0] *= a; mat[3][1] *= a; mat[3][2] *= a; mat[3][3] *= a; mat[3][4] *= a; mat[3][5] *= a; 1604 mat[4][0] *= a; mat[4][1] *= a; mat[4][2] *= a; mat[4][3] *= a; mat[4][4] *= a; mat[4][5] *= a; 1605 mat[5][0] *= a; mat[5][1] *= a; mat[5][2] *= a; mat[5][3] *= a; mat[5][4] *= a; mat[5][5] *= a; 1606 return *this; 1607 } 1608 1609 ID_INLINE idMat6 &idMat6::operator*=( const idMat6 &a ) { 1610 *this = *this * a; 1611 return *this; 1612 } 1613 1614 ID_INLINE idMat6 &idMat6::operator+=( const idMat6 &a ) { 1615 mat[0][0] += a[0][0]; mat[0][1] += a[0][1]; mat[0][2] += a[0][2]; mat[0][3] += a[0][3]; mat[0][4] += a[0][4]; mat[0][5] += a[0][5]; 1616 mat[1][0] += a[1][0]; mat[1][1] += a[1][1]; mat[1][2] += a[1][2]; mat[1][3] += a[1][3]; mat[1][4] += a[1][4]; mat[1][5] += a[1][5]; 1617 mat[2][0] += a[2][0]; mat[2][1] += a[2][1]; mat[2][2] += a[2][2]; mat[2][3] += a[2][3]; mat[2][4] += a[2][4]; mat[2][5] += a[2][5]; 1618 mat[3][0] += a[3][0]; mat[3][1] += a[3][1]; mat[3][2] += a[3][2]; mat[3][3] += a[3][3]; mat[3][4] += a[3][4]; mat[3][5] += a[3][5]; 1619 mat[4][0] += a[4][0]; mat[4][1] += a[4][1]; mat[4][2] += a[4][2]; mat[4][3] += a[4][3]; mat[4][4] += a[4][4]; mat[4][5] += a[4][5]; 1620 mat[5][0] += a[5][0]; mat[5][1] += a[5][1]; mat[5][2] += a[5][2]; mat[5][3] += a[5][3]; mat[5][4] += a[5][4]; mat[5][5] += a[5][5]; 1621 return *this; 1622 } 1623 1624 ID_INLINE idMat6 &idMat6::operator-=( const idMat6 &a ) { 1625 mat[0][0] -= a[0][0]; mat[0][1] -= a[0][1]; mat[0][2] -= a[0][2]; mat[0][3] -= a[0][3]; mat[0][4] -= a[0][4]; mat[0][5] -= a[0][5]; 1626 mat[1][0] -= a[1][0]; mat[1][1] -= a[1][1]; mat[1][2] -= a[1][2]; mat[1][3] -= a[1][3]; mat[1][4] -= a[1][4]; mat[1][5] -= a[1][5]; 1627 mat[2][0] -= a[2][0]; mat[2][1] -= a[2][1]; mat[2][2] -= a[2][2]; mat[2][3] -= a[2][3]; mat[2][4] -= a[2][4]; mat[2][5] -= a[2][5]; 1628 mat[3][0] -= a[3][0]; mat[3][1] -= a[3][1]; mat[3][2] -= a[3][2]; mat[3][3] -= a[3][3]; mat[3][4] -= a[3][4]; mat[3][5] -= a[3][5]; 1629 mat[4][0] -= a[4][0]; mat[4][1] -= a[4][1]; mat[4][2] -= a[4][2]; mat[4][3] -= a[4][3]; mat[4][4] -= a[4][4]; mat[4][5] -= a[4][5]; 1630 mat[5][0] -= a[5][0]; mat[5][1] -= a[5][1]; mat[5][2] -= a[5][2]; mat[5][3] -= a[5][3]; mat[5][4] -= a[5][4]; mat[5][5] -= a[5][5]; 1631 return *this; 1632 } 1633 1634 ID_INLINE idVec6 operator*( const idVec6 &vec, const idMat6 &mat ) { 1635 return mat * vec; 1636 } 1637 1638 ID_INLINE idMat6 operator*( const float a, idMat6 const &mat ) { 1639 return mat * a; 1640 } 1641 1642 ID_INLINE idVec6 &operator*=( idVec6 &vec, const idMat6 &mat ) { 1643 vec = mat * vec; 1644 return vec; 1645 } 1646 1647 ID_INLINE bool idMat6::Compare( const idMat6 &a ) const { 1648 dword i; 1649 const float *ptr1, *ptr2; 1650 1651 ptr1 = reinterpret_cast<const float *>(mat); 1652 ptr2 = reinterpret_cast<const float *>(a.mat); 1653 for ( i = 0; i < 6*6; i++ ) { 1654 if ( ptr1[i] != ptr2[i] ) { 1655 return false; 1656 } 1657 } 1658 return true; 1659 } 1660 1661 ID_INLINE bool idMat6::Compare( const idMat6 &a, const float epsilon ) const { 1662 dword i; 1663 const float *ptr1, *ptr2; 1664 1665 ptr1 = reinterpret_cast<const float *>(mat); 1666 ptr2 = reinterpret_cast<const float *>(a.mat); 1667 for ( i = 0; i < 6*6; i++ ) { 1668 if ( idMath::Fabs( ptr1[i] - ptr2[i] ) > epsilon ) { 1669 return false; 1670 } 1671 } 1672 return true; 1673 } 1674 1675 ID_INLINE bool idMat6::operator==( const idMat6 &a ) const { 1676 return Compare( a ); 1677 } 1678 1679 ID_INLINE bool idMat6::operator!=( const idMat6 &a ) const { 1680 return !Compare( a ); 1681 } 1682 1683 ID_INLINE void idMat6::Zero() { 1684 memset( mat, 0, sizeof( idMat6 ) ); 1685 } 1686 1687 ID_INLINE void idMat6::Identity() { 1688 *this = mat6_identity; 1689 } 1690 1691 ID_INLINE bool idMat6::IsIdentity( const float epsilon ) const { 1692 return Compare( mat6_identity, epsilon ); 1693 } 1694 1695 ID_INLINE bool idMat6::IsSymmetric( const float epsilon ) const { 1696 for ( int i = 1; i < 6; i++ ) { 1697 for ( int j = 0; j < i; j++ ) { 1698 if ( idMath::Fabs( mat[i][j] - mat[j][i] ) > epsilon ) { 1699 return false; 1700 } 1701 } 1702 } 1703 return true; 1704 } 1705 1706 ID_INLINE bool idMat6::IsDiagonal( const float epsilon ) const { 1707 for ( int i = 0; i < 6; i++ ) { 1708 for ( int j = 0; j < 6; j++ ) { 1709 if ( i != j && idMath::Fabs( mat[i][j] ) > epsilon ) { 1710 return false; 1711 } 1712 } 1713 } 1714 return true; 1715 } 1716 1717 ID_INLINE idMat3 idMat6::SubMat3( int n ) const { 1718 assert( n >= 0 && n < 4 ); 1719 int b0 = ((n & 2) >> 1) * 3; 1720 int b1 = (n & 1) * 3; 1721 return idMat3( 1722 mat[b0 + 0][b1 + 0], mat[b0 + 0][b1 + 1], mat[b0 + 0][b1 + 2], 1723 mat[b0 + 1][b1 + 0], mat[b0 + 1][b1 + 1], mat[b0 + 1][b1 + 2], 1724 mat[b0 + 2][b1 + 0], mat[b0 + 2][b1 + 1], mat[b0 + 2][b1 + 2] ); 1725 } 1726 1727 ID_INLINE float idMat6::Trace() const { 1728 return ( mat[0][0] + mat[1][1] + mat[2][2] + mat[3][3] + mat[4][4] + mat[5][5] ); 1729 } 1730 1731 ID_INLINE idMat6 idMat6::Inverse() const { 1732 idMat6 invMat; 1733 1734 invMat = *this; 1735 verify( invMat.InverseSelf() ); 1736 return invMat; 1737 } 1738 1739 ID_INLINE idMat6 idMat6::InverseFast() const { 1740 idMat6 invMat; 1741 1742 invMat = *this; 1743 verify( invMat.InverseFastSelf() ); 1744 return invMat; 1745 } 1746 1747 ID_INLINE int idMat6::GetDimension() const { 1748 return 36; 1749 } 1750 1751 ID_INLINE const float *idMat6::ToFloatPtr() const { 1752 return mat[0].ToFloatPtr(); 1753 } 1754 1755 ID_INLINE float *idMat6::ToFloatPtr() { 1756 return mat[0].ToFloatPtr(); 1757 } 1758 1759 #endif /* !__MATH_MATRIX_H__ */