Vector.h (35156B)
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_VECTOR_H__ 30 #define __MATH_VECTOR_H__ 31 32 /* 33 =============================================================================== 34 35 Vector classes 36 37 =============================================================================== 38 */ 39 40 #include "../containers/Array.h" // for idTupleSize 41 42 #define VECTOR_EPSILON 0.001f 43 44 class idAngles; 45 class idPolar3; 46 class idMat3; 47 48 //=============================================================== 49 // 50 // idVec2 - 2D vector 51 // 52 //=============================================================== 53 54 class idVec2 { 55 public: 56 float x; 57 float y; 58 59 idVec2(); 60 explicit idVec2( const float x, const float y ); 61 62 void Set( const float x, const float y ); 63 void Zero(); 64 65 float operator[]( int index ) const; 66 float & operator[]( int index ); 67 idVec2 operator-() const; 68 float operator*( const idVec2 &a ) const; 69 idVec2 operator*( const float a ) const; 70 idVec2 operator/( const float a ) const; 71 idVec2 operator+( const idVec2 &a ) const; 72 idVec2 operator-( const idVec2 &a ) const; 73 idVec2 & operator+=( const idVec2 &a ); 74 idVec2 & operator-=( const idVec2 &a ); 75 idVec2 & operator/=( const idVec2 &a ); 76 idVec2 & operator/=( const float a ); 77 idVec2 & operator*=( const float a ); 78 79 friend idVec2 operator*( const float a, const idVec2 b ); 80 81 idVec2 Scale( const idVec2 &a ) const; 82 83 bool Compare( const idVec2 &a ) const; // exact compare, no epsilon 84 bool Compare( const idVec2 &a, const float epsilon ) const; // compare with epsilon 85 bool operator==( const idVec2 &a ) const; // exact compare, no epsilon 86 bool operator!=( const idVec2 &a ) const; // exact compare, no epsilon 87 88 float Length() const; 89 float LengthFast() const; 90 float LengthSqr() const; 91 float Normalize(); // returns length 92 float NormalizeFast(); // returns length 93 idVec2 Truncate( float length ) const; // cap length 94 void Clamp( const idVec2 &min, const idVec2 &max ); 95 void Snap(); // snap to closest integer value 96 void SnapInt(); // snap towards integer (floor) 97 98 int GetDimension() const; 99 100 const float * ToFloatPtr() const; 101 float * ToFloatPtr(); 102 const char * ToString( int precision = 2 ) const; 103 104 void Lerp( const idVec2 &v1, const idVec2 &v2, const float l ); 105 }; 106 107 extern idVec2 vec2_origin; 108 #define vec2_zero vec2_origin 109 110 ID_INLINE idVec2::idVec2() { 111 } 112 113 ID_INLINE idVec2::idVec2( const float x, const float y ) { 114 this->x = x; 115 this->y = y; 116 } 117 118 ID_INLINE void idVec2::Set( const float x, const float y ) { 119 this->x = x; 120 this->y = y; 121 } 122 123 ID_INLINE void idVec2::Zero() { 124 x = y = 0.0f; 125 } 126 127 ID_INLINE bool idVec2::Compare( const idVec2 &a ) const { 128 return ( ( x == a.x ) && ( y == a.y ) ); 129 } 130 131 ID_INLINE bool idVec2::Compare( const idVec2 &a, const float epsilon ) const { 132 if ( idMath::Fabs( x - a.x ) > epsilon ) { 133 return false; 134 } 135 136 if ( idMath::Fabs( y - a.y ) > epsilon ) { 137 return false; 138 } 139 140 return true; 141 } 142 143 ID_INLINE bool idVec2::operator==( const idVec2 &a ) const { 144 return Compare( a ); 145 } 146 147 ID_INLINE bool idVec2::operator!=( const idVec2 &a ) const { 148 return !Compare( a ); 149 } 150 151 ID_INLINE float idVec2::operator[]( int index ) const { 152 return ( &x )[ index ]; 153 } 154 155 ID_INLINE float& idVec2::operator[]( int index ) { 156 return ( &x )[ index ]; 157 } 158 159 ID_INLINE float idVec2::Length() const { 160 return ( float )idMath::Sqrt( x * x + y * y ); 161 } 162 163 ID_INLINE float idVec2::LengthFast() const { 164 float sqrLength; 165 166 sqrLength = x * x + y * y; 167 return sqrLength * idMath::InvSqrt( sqrLength ); 168 } 169 170 ID_INLINE float idVec2::LengthSqr() const { 171 return ( x * x + y * y ); 172 } 173 174 ID_INLINE float idVec2::Normalize() { 175 float sqrLength, invLength; 176 177 sqrLength = x * x + y * y; 178 invLength = idMath::InvSqrt( sqrLength ); 179 x *= invLength; 180 y *= invLength; 181 return invLength * sqrLength; 182 } 183 184 ID_INLINE float idVec2::NormalizeFast() { 185 float lengthSqr, invLength; 186 187 lengthSqr = x * x + y * y; 188 invLength = idMath::InvSqrt( lengthSqr ); 189 x *= invLength; 190 y *= invLength; 191 return invLength * lengthSqr; 192 } 193 194 ID_INLINE idVec2 idVec2::Truncate( float length ) const { 195 if ( length < idMath::FLT_SMALLEST_NON_DENORMAL ) { 196 return vec2_zero; 197 } else { 198 float length2 = LengthSqr(); 199 if ( length2 > length * length ) { 200 float ilength = length * idMath::InvSqrt( length2 ); 201 return *this * ilength; 202 } 203 } 204 return *this; 205 } 206 207 ID_INLINE void idVec2::Clamp( const idVec2 &min, const idVec2 &max ) { 208 if ( x < min.x ) { 209 x = min.x; 210 } else if ( x > max.x ) { 211 x = max.x; 212 } 213 if ( y < min.y ) { 214 y = min.y; 215 } else if ( y > max.y ) { 216 y = max.y; 217 } 218 } 219 220 ID_INLINE void idVec2::Snap() { 221 x = floor( x + 0.5f ); 222 y = floor( y + 0.5f ); 223 } 224 225 ID_INLINE void idVec2::SnapInt() { 226 x = float( int( x ) ); 227 y = float( int( y ) ); 228 } 229 230 ID_INLINE idVec2 idVec2::operator-() const { 231 return idVec2( -x, -y ); 232 } 233 234 ID_INLINE idVec2 idVec2::operator-( const idVec2 &a ) const { 235 return idVec2( x - a.x, y - a.y ); 236 } 237 238 ID_INLINE float idVec2::operator*( const idVec2 &a ) const { 239 return x * a.x + y * a.y; 240 } 241 242 ID_INLINE idVec2 idVec2::operator*( const float a ) const { 243 return idVec2( x * a, y * a ); 244 } 245 246 ID_INLINE idVec2 idVec2::operator/( const float a ) const { 247 float inva = 1.0f / a; 248 return idVec2( x * inva, y * inva ); 249 } 250 251 ID_INLINE idVec2 operator*( const float a, const idVec2 b ) { 252 return idVec2( b.x * a, b.y * a ); 253 } 254 255 ID_INLINE idVec2 idVec2::operator+( const idVec2 &a ) const { 256 return idVec2( x + a.x, y + a.y ); 257 } 258 259 ID_INLINE idVec2 &idVec2::operator+=( const idVec2 &a ) { 260 x += a.x; 261 y += a.y; 262 263 return *this; 264 } 265 266 ID_INLINE idVec2 &idVec2::operator/=( const idVec2 &a ) { 267 x /= a.x; 268 y /= a.y; 269 270 return *this; 271 } 272 273 ID_INLINE idVec2 &idVec2::operator/=( const float a ) { 274 float inva = 1.0f / a; 275 x *= inva; 276 y *= inva; 277 278 return *this; 279 } 280 281 ID_INLINE idVec2 &idVec2::operator-=( const idVec2 &a ) { 282 x -= a.x; 283 y -= a.y; 284 285 return *this; 286 } 287 288 ID_INLINE idVec2 &idVec2::operator*=( const float a ) { 289 x *= a; 290 y *= a; 291 292 return *this; 293 } 294 295 ID_INLINE idVec2 idVec2::Scale( const idVec2 &a ) const { 296 return idVec2( x * a.x, y * a.y ); 297 } 298 299 ID_INLINE int idVec2::GetDimension() const { 300 return 2; 301 } 302 303 ID_INLINE const float *idVec2::ToFloatPtr() const { 304 return &x; 305 } 306 307 ID_INLINE float *idVec2::ToFloatPtr() { 308 return &x; 309 } 310 311 312 //=============================================================== 313 // 314 // idVec3 - 3D vector 315 // 316 //=============================================================== 317 318 class idVec3 { 319 public: 320 float x; 321 float y; 322 float z; 323 324 idVec3(); 325 explicit idVec3( const float xyz ) { Set( xyz, xyz, xyz ); } 326 explicit idVec3( const float x, const float y, const float z ); 327 328 void Set( const float x, const float y, const float z ); 329 void Zero(); 330 331 float operator[]( const int index ) const; 332 float & operator[]( const int index ); 333 idVec3 operator-() const; 334 idVec3 & operator=( const idVec3 &a ); // required because of a msvc 6 & 7 bug 335 float operator*( const idVec3 &a ) const; 336 idVec3 operator*( const float a ) const; 337 idVec3 operator/( const float a ) const; 338 idVec3 operator+( const idVec3 &a ) const; 339 idVec3 operator-( const idVec3 &a ) const; 340 idVec3 & operator+=( const idVec3 &a ); 341 idVec3 & operator-=( const idVec3 &a ); 342 idVec3 & operator/=( const idVec3 &a ); 343 idVec3 & operator/=( const float a ); 344 idVec3 & operator*=( const float a ); 345 346 friend idVec3 operator*( const float a, const idVec3 b ); 347 348 bool Compare( const idVec3 &a ) const; // exact compare, no epsilon 349 bool Compare( const idVec3 &a, const float epsilon ) const; // compare with epsilon 350 bool operator==( const idVec3 &a ) const; // exact compare, no epsilon 351 bool operator!=( const idVec3 &a ) const; // exact compare, no epsilon 352 353 bool FixDegenerateNormal(); // fix degenerate axial cases 354 bool FixDenormals(); // change tiny numbers to zero 355 356 idVec3 Cross( const idVec3 &a ) const; 357 idVec3 & Cross( const idVec3 &a, const idVec3 &b ); 358 float Length() const; 359 float LengthSqr() const; 360 float LengthFast() const; 361 float Normalize(); // returns length 362 float NormalizeFast(); // returns length 363 idVec3 Truncate( float length ) const; // cap length 364 void Clamp( const idVec3 &min, const idVec3 &max ); 365 void Snap(); // snap to closest integer value 366 void SnapInt(); // snap towards integer (floor) 367 368 int GetDimension() const; 369 370 float ToYaw() const; 371 float ToPitch() const; 372 idAngles ToAngles() const; 373 idPolar3 ToPolar() const; 374 idMat3 ToMat3() const; // vector should be normalized 375 const idVec2 & ToVec2() const; 376 idVec2 & ToVec2(); 377 const float * ToFloatPtr() const; 378 float * ToFloatPtr(); 379 const char * ToString( int precision = 2 ) const; 380 381 void NormalVectors( idVec3 &left, idVec3 &down ) const; // vector should be normalized 382 void OrthogonalBasis( idVec3 &left, idVec3 &up ) const; 383 384 void ProjectOntoPlane( const idVec3 &normal, const float overBounce = 1.0f ); 385 bool ProjectAlongPlane( const idVec3 &normal, const float epsilon, const float overBounce = 1.0f ); 386 void ProjectSelfOntoSphere( const float radius ); 387 388 void Lerp( const idVec3 &v1, const idVec3 &v2, const float l ); 389 void SLerp( const idVec3 &v1, const idVec3 &v2, const float l ); 390 }; 391 392 extern idVec3 vec3_origin; 393 #define vec3_zero vec3_origin 394 395 ID_INLINE idVec3::idVec3() { 396 } 397 398 ID_INLINE idVec3::idVec3( const float x, const float y, const float z ) { 399 this->x = x; 400 this->y = y; 401 this->z = z; 402 } 403 404 ID_INLINE float idVec3::operator[]( const int index ) const { 405 return ( &x )[ index ]; 406 } 407 408 ID_INLINE float &idVec3::operator[]( const int index ) { 409 return ( &x )[ index ]; 410 } 411 412 ID_INLINE void idVec3::Set( const float x, const float y, const float z ) { 413 this->x = x; 414 this->y = y; 415 this->z = z; 416 } 417 418 ID_INLINE void idVec3::Zero() { 419 x = y = z = 0.0f; 420 } 421 422 ID_INLINE idVec3 idVec3::operator-() const { 423 return idVec3( -x, -y, -z ); 424 } 425 426 ID_INLINE idVec3 &idVec3::operator=( const idVec3 &a ) { 427 x = a.x; 428 y = a.y; 429 z = a.z; 430 return *this; 431 } 432 433 ID_INLINE idVec3 idVec3::operator-( const idVec3 &a ) const { 434 return idVec3( x - a.x, y - a.y, z - a.z ); 435 } 436 437 ID_INLINE float idVec3::operator*( const idVec3 &a ) const { 438 return x * a.x + y * a.y + z * a.z; 439 } 440 441 ID_INLINE idVec3 idVec3::operator*( const float a ) const { 442 return idVec3( x * a, y * a, z * a ); 443 } 444 445 ID_INLINE idVec3 idVec3::operator/( const float a ) const { 446 float inva = 1.0f / a; 447 return idVec3( x * inva, y * inva, z * inva ); 448 } 449 450 ID_INLINE idVec3 operator*( const float a, const idVec3 b ) { 451 return idVec3( b.x * a, b.y * a, b.z * a ); 452 } 453 454 ID_INLINE idVec3 operator/( const float a, const idVec3 b ) { 455 return idVec3( a / b.x, a / b.y, a / b.z ); 456 } 457 458 ID_INLINE idVec3 idVec3::operator+( const idVec3 &a ) const { 459 return idVec3( x + a.x, y + a.y, z + a.z ); 460 } 461 462 ID_INLINE idVec3 &idVec3::operator+=( const idVec3 &a ) { 463 x += a.x; 464 y += a.y; 465 z += a.z; 466 467 return *this; 468 } 469 470 ID_INLINE idVec3 &idVec3::operator/=( const idVec3 &a ) { 471 x /= a.x; 472 y /= a.y; 473 z /= a.z; 474 475 return *this; 476 } 477 478 ID_INLINE idVec3 &idVec3::operator/=( const float a ) { 479 float inva = 1.0f / a; 480 x *= inva; 481 y *= inva; 482 z *= inva; 483 484 return *this; 485 } 486 487 ID_INLINE idVec3 &idVec3::operator-=( const idVec3 &a ) { 488 x -= a.x; 489 y -= a.y; 490 z -= a.z; 491 492 return *this; 493 } 494 495 ID_INLINE idVec3 &idVec3::operator*=( const float a ) { 496 x *= a; 497 y *= a; 498 z *= a; 499 500 return *this; 501 } 502 503 ID_INLINE bool idVec3::Compare( const idVec3 &a ) const { 504 return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) ); 505 } 506 507 ID_INLINE bool idVec3::Compare( const idVec3 &a, const float epsilon ) const { 508 if ( idMath::Fabs( x - a.x ) > epsilon ) { 509 return false; 510 } 511 512 if ( idMath::Fabs( y - a.y ) > epsilon ) { 513 return false; 514 } 515 516 if ( idMath::Fabs( z - a.z ) > epsilon ) { 517 return false; 518 } 519 520 return true; 521 } 522 523 ID_INLINE bool idVec3::operator==( const idVec3 &a ) const { 524 return Compare( a ); 525 } 526 527 ID_INLINE bool idVec3::operator!=( const idVec3 &a ) const { 528 return !Compare( a ); 529 } 530 531 ID_INLINE float idVec3::NormalizeFast() { 532 float sqrLength, invLength; 533 534 sqrLength = x * x + y * y + z * z; 535 invLength = idMath::InvSqrt( sqrLength ); 536 x *= invLength; 537 y *= invLength; 538 z *= invLength; 539 return invLength * sqrLength; 540 } 541 542 ID_INLINE bool idVec3::FixDegenerateNormal() { 543 if ( x == 0.0f ) { 544 if ( y == 0.0f ) { 545 if ( z > 0.0f ) { 546 if ( z != 1.0f ) { 547 z = 1.0f; 548 return true; 549 } 550 } else { 551 if ( z != -1.0f ) { 552 z = -1.0f; 553 return true; 554 } 555 } 556 return false; 557 } else if ( z == 0.0f ) { 558 if ( y > 0.0f ) { 559 if ( y != 1.0f ) { 560 y = 1.0f; 561 return true; 562 } 563 } else { 564 if ( y != -1.0f ) { 565 y = -1.0f; 566 return true; 567 } 568 } 569 return false; 570 } 571 } else if ( y == 0.0f ) { 572 if ( z == 0.0f ) { 573 if ( x > 0.0f ) { 574 if ( x != 1.0f ) { 575 x = 1.0f; 576 return true; 577 } 578 } else { 579 if ( x != -1.0f ) { 580 x = -1.0f; 581 return true; 582 } 583 } 584 return false; 585 } 586 } 587 if ( idMath::Fabs( x ) == 1.0f ) { 588 if ( y != 0.0f || z != 0.0f ) { 589 y = z = 0.0f; 590 return true; 591 } 592 return false; 593 } else if ( idMath::Fabs( y ) == 1.0f ) { 594 if ( x != 0.0f || z != 0.0f ) { 595 x = z = 0.0f; 596 return true; 597 } 598 return false; 599 } else if ( idMath::Fabs( z ) == 1.0f ) { 600 if ( x != 0.0f || y != 0.0f ) { 601 x = y = 0.0f; 602 return true; 603 } 604 return false; 605 } 606 return false; 607 } 608 609 ID_INLINE bool idVec3::FixDenormals() { 610 bool denormal = false; 611 if ( fabs( x ) < 1e-30f ) { 612 x = 0.0f; 613 denormal = true; 614 } 615 if ( fabs( y ) < 1e-30f ) { 616 y = 0.0f; 617 denormal = true; 618 } 619 if ( fabs( z ) < 1e-30f ) { 620 z = 0.0f; 621 denormal = true; 622 } 623 return denormal; 624 } 625 626 ID_INLINE idVec3 idVec3::Cross( const idVec3 &a ) const { 627 return idVec3( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x ); 628 } 629 630 ID_INLINE idVec3 &idVec3::Cross( const idVec3 &a, const idVec3 &b ) { 631 x = a.y * b.z - a.z * b.y; 632 y = a.z * b.x - a.x * b.z; 633 z = a.x * b.y - a.y * b.x; 634 635 return *this; 636 } 637 638 ID_INLINE float idVec3::Length() const { 639 return ( float )idMath::Sqrt( x * x + y * y + z * z ); 640 } 641 642 ID_INLINE float idVec3::LengthSqr() const { 643 return ( x * x + y * y + z * z ); 644 } 645 646 ID_INLINE float idVec3::LengthFast() const { 647 float sqrLength; 648 649 sqrLength = x * x + y * y + z * z; 650 return sqrLength * idMath::InvSqrt( sqrLength ); 651 } 652 653 ID_INLINE float idVec3::Normalize() { 654 float sqrLength, invLength; 655 656 sqrLength = x * x + y * y + z * z; 657 invLength = idMath::InvSqrt( sqrLength ); 658 x *= invLength; 659 y *= invLength; 660 z *= invLength; 661 return invLength * sqrLength; 662 } 663 664 ID_INLINE idVec3 idVec3::Truncate( float length ) const { 665 if ( length < idMath::FLT_SMALLEST_NON_DENORMAL ) { 666 return vec3_zero; 667 } else { 668 float length2 = LengthSqr(); 669 if ( length2 > length * length ) { 670 float ilength = length * idMath::InvSqrt( length2 ); 671 return *this * ilength; 672 } 673 } 674 return *this; 675 } 676 677 ID_INLINE void idVec3::Clamp( const idVec3 &min, const idVec3 &max ) { 678 if ( x < min.x ) { 679 x = min.x; 680 } else if ( x > max.x ) { 681 x = max.x; 682 } 683 if ( y < min.y ) { 684 y = min.y; 685 } else if ( y > max.y ) { 686 y = max.y; 687 } 688 if ( z < min.z ) { 689 z = min.z; 690 } else if ( z > max.z ) { 691 z = max.z; 692 } 693 } 694 695 ID_INLINE void idVec3::Snap() { 696 x = floor( x + 0.5f ); 697 y = floor( y + 0.5f ); 698 z = floor( z + 0.5f ); 699 } 700 701 ID_INLINE void idVec3::SnapInt() { 702 x = float( int( x ) ); 703 y = float( int( y ) ); 704 z = float( int( z ) ); 705 } 706 707 ID_INLINE int idVec3::GetDimension() const { 708 return 3; 709 } 710 711 ID_INLINE const idVec2 &idVec3::ToVec2() const { 712 return *reinterpret_cast<const idVec2 *>(this); 713 } 714 715 ID_INLINE idVec2 &idVec3::ToVec2() { 716 return *reinterpret_cast<idVec2 *>(this); 717 } 718 719 ID_INLINE const float *idVec3::ToFloatPtr() const { 720 return &x; 721 } 722 723 ID_INLINE float *idVec3::ToFloatPtr() { 724 return &x; 725 } 726 727 ID_INLINE void idVec3::NormalVectors( idVec3 &left, idVec3 &down ) const { 728 float d; 729 730 d = x * x + y * y; 731 if ( !d ) { 732 left[0] = 1; 733 left[1] = 0; 734 left[2] = 0; 735 } else { 736 d = idMath::InvSqrt( d ); 737 left[0] = -y * d; 738 left[1] = x * d; 739 left[2] = 0; 740 } 741 down = left.Cross( *this ); 742 } 743 744 ID_INLINE void idVec3::OrthogonalBasis( idVec3 &left, idVec3 &up ) const { 745 float l, s; 746 747 if ( idMath::Fabs( z ) > 0.7f ) { 748 l = y * y + z * z; 749 s = idMath::InvSqrt( l ); 750 up[0] = 0; 751 up[1] = z * s; 752 up[2] = -y * s; 753 left[0] = l * s; 754 left[1] = -x * up[2]; 755 left[2] = x * up[1]; 756 } 757 else { 758 l = x * x + y * y; 759 s = idMath::InvSqrt( l ); 760 left[0] = -y * s; 761 left[1] = x * s; 762 left[2] = 0; 763 up[0] = -z * left[1]; 764 up[1] = z * left[0]; 765 up[2] = l * s; 766 } 767 } 768 769 ID_INLINE void idVec3::ProjectOntoPlane( const idVec3 &normal, const float overBounce ) { 770 float backoff; 771 772 backoff = *this * normal; 773 774 if ( overBounce != 1.0 ) { 775 if ( backoff < 0 ) { 776 backoff *= overBounce; 777 } else { 778 backoff /= overBounce; 779 } 780 } 781 782 *this -= backoff * normal; 783 } 784 785 ID_INLINE bool idVec3::ProjectAlongPlane( const idVec3 &normal, const float epsilon, const float overBounce ) { 786 idVec3 cross; 787 float len; 788 789 cross = this->Cross( normal ).Cross( (*this) ); 790 // normalize so a fixed epsilon can be used 791 cross.Normalize(); 792 len = normal * cross; 793 if ( idMath::Fabs( len ) < epsilon ) { 794 return false; 795 } 796 cross *= overBounce * ( normal * (*this) ) / len; 797 (*this) -= cross; 798 return true; 799 } 800 801 //=============================================================== 802 // 803 // idTupleSize< idVec3 > - Specialization to get the size 804 // of an idVec3 generically. 805 // 806 //=============================================================== 807 808 template<> 809 struct idTupleSize< idVec3 > { 810 enum { value = 3 }; 811 }; 812 813 //=============================================================== 814 // 815 // idVec4 - 4D vector 816 // 817 //=============================================================== 818 819 class idVec4 { 820 public: 821 float x; 822 float y; 823 float z; 824 float w; 825 826 idVec4() { } 827 explicit idVec4( const float x ) { Set( x, x, x, x ); } 828 explicit idVec4( const float x, const float y, const float z, const float w ) { Set( x, y, z, w ); } 829 830 void Set( const float x, const float y, const float z, const float w ); 831 void Zero(); 832 833 float operator[]( const int index ) const; 834 float & operator[]( const int index ); 835 idVec4 operator-() const; 836 float operator*( const idVec4 &a ) const; 837 idVec4 operator*( const float a ) const; 838 idVec4 operator/( const float a ) const; 839 idVec4 operator+( const idVec4 &a ) const; 840 idVec4 operator-( const idVec4 &a ) const; 841 idVec4 & operator+=( const idVec4 &a ); 842 idVec4 & operator-=( const idVec4 &a ); 843 idVec4 & operator/=( const idVec4 &a ); 844 idVec4 & operator/=( const float a ); 845 idVec4 & operator*=( const float a ); 846 847 friend idVec4 operator*( const float a, const idVec4 b ); 848 849 idVec4 Multiply( const idVec4 & a ) const; 850 851 bool Compare( const idVec4 &a ) const; // exact compare, no epsilon 852 bool Compare( const idVec4 &a, const float epsilon ) const; // compare with epsilon 853 bool operator==( const idVec4 &a ) const; // exact compare, no epsilon 854 bool operator!=( const idVec4 &a ) const; // exact compare, no epsilon 855 856 float Length() const; 857 float LengthSqr() const; 858 float Normalize(); // returns length 859 float NormalizeFast(); // returns length 860 861 int GetDimension() const; 862 863 const idVec2 & ToVec2() const; 864 idVec2 & ToVec2(); 865 const idVec3 & ToVec3() const; 866 idVec3 & ToVec3(); 867 const float * ToFloatPtr() const; 868 float * ToFloatPtr(); 869 const char * ToString( int precision = 2 ) const; 870 871 void Lerp( const idVec4 &v1, const idVec4 &v2, const float l ); 872 }; 873 874 extern idVec4 vec4_origin; 875 #define vec4_zero vec4_origin 876 877 ID_INLINE void idVec4::Set( const float x, const float y, const float z, const float w ) { 878 this->x = x; 879 this->y = y; 880 this->z = z; 881 this->w = w; 882 } 883 884 ID_INLINE void idVec4::Zero() { 885 x = y = z = w = 0.0f; 886 } 887 888 ID_INLINE float idVec4::operator[]( int index ) const { 889 return ( &x )[ index ]; 890 } 891 892 ID_INLINE float& idVec4::operator[]( int index ) { 893 return ( &x )[ index ]; 894 } 895 896 ID_INLINE idVec4 idVec4::operator-() const { 897 return idVec4( -x, -y, -z, -w ); 898 } 899 900 ID_INLINE idVec4 idVec4::operator-( const idVec4 &a ) const { 901 return idVec4( x - a.x, y - a.y, z - a.z, w - a.w ); 902 } 903 904 ID_INLINE float idVec4::operator*( const idVec4 &a ) const { 905 return x * a.x + y * a.y + z * a.z + w * a.w; 906 } 907 908 ID_INLINE idVec4 idVec4::operator*( const float a ) const { 909 return idVec4( x * a, y * a, z * a, w * a ); 910 } 911 912 ID_INLINE idVec4 idVec4::operator/( const float a ) const { 913 float inva = 1.0f / a; 914 return idVec4( x * inva, y * inva, z * inva, w * inva ); 915 } 916 917 ID_INLINE idVec4 operator*( const float a, const idVec4 b ) { 918 return idVec4( b.x * a, b.y * a, b.z * a, b.w * a ); 919 } 920 921 ID_INLINE idVec4 idVec4::operator+( const idVec4 &a ) const { 922 return idVec4( x + a.x, y + a.y, z + a.z, w + a.w ); 923 } 924 925 ID_INLINE idVec4 &idVec4::operator+=( const idVec4 &a ) { 926 x += a.x; 927 y += a.y; 928 z += a.z; 929 w += a.w; 930 931 return *this; 932 } 933 934 ID_INLINE idVec4 &idVec4::operator/=( const idVec4 &a ) { 935 x /= a.x; 936 y /= a.y; 937 z /= a.z; 938 w /= a.w; 939 940 return *this; 941 } 942 943 ID_INLINE idVec4 &idVec4::operator/=( const float a ) { 944 float inva = 1.0f / a; 945 x *= inva; 946 y *= inva; 947 z *= inva; 948 w *= inva; 949 950 return *this; 951 } 952 953 ID_INLINE idVec4 &idVec4::operator-=( const idVec4 &a ) { 954 x -= a.x; 955 y -= a.y; 956 z -= a.z; 957 w -= a.w; 958 959 return *this; 960 } 961 962 ID_INLINE idVec4 &idVec4::operator*=( const float a ) { 963 x *= a; 964 y *= a; 965 z *= a; 966 w *= a; 967 968 return *this; 969 } 970 971 ID_INLINE idVec4 idVec4::Multiply( const idVec4 & a ) const { 972 return idVec4( x * a.x, y * a.y, z * a.z, w * a.w ); 973 } 974 975 ID_INLINE bool idVec4::Compare( const idVec4 &a ) const { 976 return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) && w == a.w ); 977 } 978 979 ID_INLINE bool idVec4::Compare( const idVec4 &a, const float epsilon ) const { 980 if ( idMath::Fabs( x - a.x ) > epsilon ) { 981 return false; 982 } 983 984 if ( idMath::Fabs( y - a.y ) > epsilon ) { 985 return false; 986 } 987 988 if ( idMath::Fabs( z - a.z ) > epsilon ) { 989 return false; 990 } 991 992 if ( idMath::Fabs( w - a.w ) > epsilon ) { 993 return false; 994 } 995 996 return true; 997 } 998 999 ID_INLINE bool idVec4::operator==( const idVec4 &a ) const { 1000 return Compare( a ); 1001 } 1002 1003 ID_INLINE bool idVec4::operator!=( const idVec4 &a ) const { 1004 return !Compare( a ); 1005 } 1006 1007 ID_INLINE float idVec4::Length() const { 1008 return ( float )idMath::Sqrt( x * x + y * y + z * z + w * w ); 1009 } 1010 1011 ID_INLINE float idVec4::LengthSqr() const { 1012 return ( x * x + y * y + z * z + w * w ); 1013 } 1014 1015 ID_INLINE float idVec4::Normalize() { 1016 float sqrLength, invLength; 1017 1018 sqrLength = x * x + y * y + z * z + w * w; 1019 invLength = idMath::InvSqrt( sqrLength ); 1020 x *= invLength; 1021 y *= invLength; 1022 z *= invLength; 1023 w *= invLength; 1024 return invLength * sqrLength; 1025 } 1026 1027 ID_INLINE float idVec4::NormalizeFast() { 1028 float sqrLength, invLength; 1029 1030 sqrLength = x * x + y * y + z * z + w * w; 1031 invLength = idMath::InvSqrt( sqrLength ); 1032 x *= invLength; 1033 y *= invLength; 1034 z *= invLength; 1035 w *= invLength; 1036 return invLength * sqrLength; 1037 } 1038 1039 ID_INLINE int idVec4::GetDimension() const { 1040 return 4; 1041 } 1042 1043 ID_INLINE const idVec2 &idVec4::ToVec2() const { 1044 return *reinterpret_cast<const idVec2 *>(this); 1045 } 1046 1047 ID_INLINE idVec2 &idVec4::ToVec2() { 1048 return *reinterpret_cast<idVec2 *>(this); 1049 } 1050 1051 ID_INLINE const idVec3 &idVec4::ToVec3() const { 1052 return *reinterpret_cast<const idVec3 *>(this); 1053 } 1054 1055 ID_INLINE idVec3 &idVec4::ToVec3() { 1056 return *reinterpret_cast<idVec3 *>(this); 1057 } 1058 1059 ID_INLINE const float *idVec4::ToFloatPtr() const { 1060 return &x; 1061 } 1062 1063 ID_INLINE float *idVec4::ToFloatPtr() { 1064 return &x; 1065 } 1066 1067 1068 //=============================================================== 1069 // 1070 // idVec5 - 5D vector 1071 // 1072 //=============================================================== 1073 1074 class idVec5 { 1075 public: 1076 float x; 1077 float y; 1078 float z; 1079 float s; 1080 float t; 1081 1082 idVec5(); 1083 explicit idVec5( const idVec3 &xyz, const idVec2 &st ); 1084 explicit idVec5( const float x, const float y, const float z, const float s, const float t ); 1085 1086 float operator[]( int index ) const; 1087 float & operator[]( int index ); 1088 idVec5 & operator=( const idVec3 &a ); 1089 1090 int GetDimension() const; 1091 1092 const idVec3 & ToVec3() const; 1093 idVec3 & ToVec3(); 1094 const float * ToFloatPtr() const; 1095 float * ToFloatPtr(); 1096 const char * ToString( int precision = 2 ) const; 1097 1098 void Lerp( const idVec5 &v1, const idVec5 &v2, const float l ); 1099 }; 1100 1101 extern idVec5 vec5_origin; 1102 #define vec5_zero vec5_origin 1103 1104 ID_INLINE idVec5::idVec5() { 1105 } 1106 1107 ID_INLINE idVec5::idVec5( const idVec3 &xyz, const idVec2 &st ) { 1108 x = xyz.x; 1109 y = xyz.y; 1110 z = xyz.z; 1111 s = st[0]; 1112 t = st[1]; 1113 } 1114 1115 ID_INLINE idVec5::idVec5( const float x, const float y, const float z, const float s, const float t ) { 1116 this->x = x; 1117 this->y = y; 1118 this->z = z; 1119 this->s = s; 1120 this->t = t; 1121 } 1122 1123 ID_INLINE float idVec5::operator[]( int index ) const { 1124 return ( &x )[ index ]; 1125 } 1126 1127 ID_INLINE float& idVec5::operator[]( int index ) { 1128 return ( &x )[ index ]; 1129 } 1130 1131 ID_INLINE idVec5 &idVec5::operator=( const idVec3 &a ) { 1132 x = a.x; 1133 y = a.y; 1134 z = a.z; 1135 s = t = 0; 1136 return *this; 1137 } 1138 1139 ID_INLINE int idVec5::GetDimension() const { 1140 return 5; 1141 } 1142 1143 ID_INLINE const idVec3 &idVec5::ToVec3() const { 1144 return *reinterpret_cast<const idVec3 *>(this); 1145 } 1146 1147 ID_INLINE idVec3 &idVec5::ToVec3() { 1148 return *reinterpret_cast<idVec3 *>(this); 1149 } 1150 1151 ID_INLINE const float *idVec5::ToFloatPtr() const { 1152 return &x; 1153 } 1154 1155 ID_INLINE float *idVec5::ToFloatPtr() { 1156 return &x; 1157 } 1158 1159 1160 //=============================================================== 1161 // 1162 // idVec6 - 6D vector 1163 // 1164 //=============================================================== 1165 1166 class idVec6 { 1167 public: 1168 idVec6(); 1169 explicit idVec6( const float *a ); 1170 explicit idVec6( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 ); 1171 1172 void Set( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 ); 1173 void Zero(); 1174 1175 float operator[]( const int index ) const; 1176 float & operator[]( const int index ); 1177 idVec6 operator-() const; 1178 idVec6 operator*( const float a ) const; 1179 idVec6 operator/( const float a ) const; 1180 float operator*( const idVec6 &a ) const; 1181 idVec6 operator-( const idVec6 &a ) const; 1182 idVec6 operator+( const idVec6 &a ) const; 1183 idVec6 & operator*=( const float a ); 1184 idVec6 & operator/=( const float a ); 1185 idVec6 & operator+=( const idVec6 &a ); 1186 idVec6 & operator-=( const idVec6 &a ); 1187 1188 friend idVec6 operator*( const float a, const idVec6 b ); 1189 1190 bool Compare( const idVec6 &a ) const; // exact compare, no epsilon 1191 bool Compare( const idVec6 &a, const float epsilon ) const; // compare with epsilon 1192 bool operator==( const idVec6 &a ) const; // exact compare, no epsilon 1193 bool operator!=( const idVec6 &a ) const; // exact compare, no epsilon 1194 1195 float Length() const; 1196 float LengthSqr() const; 1197 float Normalize(); // returns length 1198 float NormalizeFast(); // returns length 1199 1200 int GetDimension() const; 1201 1202 const idVec3 & SubVec3( int index ) const; 1203 idVec3 & SubVec3( int index ); 1204 const float * ToFloatPtr() const; 1205 float * ToFloatPtr(); 1206 const char * ToString( int precision = 2 ) const; 1207 1208 private: 1209 float p[6]; 1210 }; 1211 1212 extern idVec6 vec6_origin; 1213 #define vec6_zero vec6_origin 1214 extern idVec6 vec6_infinity; 1215 1216 ID_INLINE idVec6::idVec6() { 1217 } 1218 1219 ID_INLINE idVec6::idVec6( const float *a ) { 1220 memcpy( p, a, 6 * sizeof( float ) ); 1221 } 1222 1223 ID_INLINE idVec6::idVec6( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 ) { 1224 p[0] = a1; 1225 p[1] = a2; 1226 p[2] = a3; 1227 p[3] = a4; 1228 p[4] = a5; 1229 p[5] = a6; 1230 } 1231 1232 ID_INLINE idVec6 idVec6::operator-() const { 1233 return idVec6( -p[0], -p[1], -p[2], -p[3], -p[4], -p[5] ); 1234 } 1235 1236 ID_INLINE float idVec6::operator[]( const int index ) const { 1237 return p[index]; 1238 } 1239 1240 ID_INLINE float &idVec6::operator[]( const int index ) { 1241 return p[index]; 1242 } 1243 1244 ID_INLINE idVec6 idVec6::operator*( const float a ) const { 1245 return idVec6( p[0]*a, p[1]*a, p[2]*a, p[3]*a, p[4]*a, p[5]*a ); 1246 } 1247 1248 ID_INLINE float idVec6::operator*( const idVec6 &a ) const { 1249 return p[0] * a[0] + p[1] * a[1] + p[2] * a[2] + p[3] * a[3] + p[4] * a[4] + p[5] * a[5]; 1250 } 1251 1252 ID_INLINE idVec6 idVec6::operator/( const float a ) const { 1253 float inva; 1254 1255 assert( a != 0.0f ); 1256 inva = 1.0f / a; 1257 return idVec6( p[0]*inva, p[1]*inva, p[2]*inva, p[3]*inva, p[4]*inva, p[5]*inva ); 1258 } 1259 1260 ID_INLINE idVec6 idVec6::operator+( const idVec6 &a ) const { 1261 return idVec6( p[0] + a[0], p[1] + a[1], p[2] + a[2], p[3] + a[3], p[4] + a[4], p[5] + a[5] ); 1262 } 1263 1264 ID_INLINE idVec6 idVec6::operator-( const idVec6 &a ) const { 1265 return idVec6( p[0] - a[0], p[1] - a[1], p[2] - a[2], p[3] - a[3], p[4] - a[4], p[5] - a[5] ); 1266 } 1267 1268 ID_INLINE idVec6 &idVec6::operator*=( const float a ) { 1269 p[0] *= a; 1270 p[1] *= a; 1271 p[2] *= a; 1272 p[3] *= a; 1273 p[4] *= a; 1274 p[5] *= a; 1275 return *this; 1276 } 1277 1278 ID_INLINE idVec6 &idVec6::operator/=( const float a ) { 1279 float inva; 1280 1281 assert( a != 0.0f ); 1282 inva = 1.0f / a; 1283 p[0] *= inva; 1284 p[1] *= inva; 1285 p[2] *= inva; 1286 p[3] *= inva; 1287 p[4] *= inva; 1288 p[5] *= inva; 1289 return *this; 1290 } 1291 1292 ID_INLINE idVec6 &idVec6::operator+=( const idVec6 &a ) { 1293 p[0] += a[0]; 1294 p[1] += a[1]; 1295 p[2] += a[2]; 1296 p[3] += a[3]; 1297 p[4] += a[4]; 1298 p[5] += a[5]; 1299 return *this; 1300 } 1301 1302 ID_INLINE idVec6 &idVec6::operator-=( const idVec6 &a ) { 1303 p[0] -= a[0]; 1304 p[1] -= a[1]; 1305 p[2] -= a[2]; 1306 p[3] -= a[3]; 1307 p[4] -= a[4]; 1308 p[5] -= a[5]; 1309 return *this; 1310 } 1311 1312 ID_INLINE idVec6 operator*( const float a, const idVec6 b ) { 1313 return b * a; 1314 } 1315 1316 ID_INLINE bool idVec6::Compare( const idVec6 &a ) const { 1317 return ( ( p[0] == a[0] ) && ( p[1] == a[1] ) && ( p[2] == a[2] ) && 1318 ( p[3] == a[3] ) && ( p[4] == a[4] ) && ( p[5] == a[5] ) ); 1319 } 1320 1321 ID_INLINE bool idVec6::Compare( const idVec6 &a, const float epsilon ) const { 1322 if ( idMath::Fabs( p[0] - a[0] ) > epsilon ) { 1323 return false; 1324 } 1325 1326 if ( idMath::Fabs( p[1] - a[1] ) > epsilon ) { 1327 return false; 1328 } 1329 1330 if ( idMath::Fabs( p[2] - a[2] ) > epsilon ) { 1331 return false; 1332 } 1333 1334 if ( idMath::Fabs( p[3] - a[3] ) > epsilon ) { 1335 return false; 1336 } 1337 1338 if ( idMath::Fabs( p[4] - a[4] ) > epsilon ) { 1339 return false; 1340 } 1341 1342 if ( idMath::Fabs( p[5] - a[5] ) > epsilon ) { 1343 return false; 1344 } 1345 1346 return true; 1347 } 1348 1349 ID_INLINE bool idVec6::operator==( const idVec6 &a ) const { 1350 return Compare( a ); 1351 } 1352 1353 ID_INLINE bool idVec6::operator!=( const idVec6 &a ) const { 1354 return !Compare( a ); 1355 } 1356 1357 ID_INLINE void idVec6::Set( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 ) { 1358 p[0] = a1; 1359 p[1] = a2; 1360 p[2] = a3; 1361 p[3] = a4; 1362 p[4] = a5; 1363 p[5] = a6; 1364 } 1365 1366 ID_INLINE void idVec6::Zero() { 1367 p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0.0f; 1368 } 1369 1370 ID_INLINE float idVec6::Length() const { 1371 return ( float )idMath::Sqrt( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] + p[3] * p[3] + p[4] * p[4] + p[5] * p[5] ); 1372 } 1373 1374 ID_INLINE float idVec6::LengthSqr() const { 1375 return ( p[0] * p[0] + p[1] * p[1] + p[2] * p[2] + p[3] * p[3] + p[4] * p[4] + p[5] * p[5] ); 1376 } 1377 1378 ID_INLINE float idVec6::Normalize() { 1379 float sqrLength, invLength; 1380 1381 sqrLength = p[0] * p[0] + p[1] * p[1] + p[2] * p[2] + p[3] * p[3] + p[4] * p[4] + p[5] * p[5]; 1382 invLength = idMath::InvSqrt( sqrLength ); 1383 p[0] *= invLength; 1384 p[1] *= invLength; 1385 p[2] *= invLength; 1386 p[3] *= invLength; 1387 p[4] *= invLength; 1388 p[5] *= invLength; 1389 return invLength * sqrLength; 1390 } 1391 1392 ID_INLINE float idVec6::NormalizeFast() { 1393 float sqrLength, invLength; 1394 1395 sqrLength = p[0] * p[0] + p[1] * p[1] + p[2] * p[2] + p[3] * p[3] + p[4] * p[4] + p[5] * p[5]; 1396 invLength = idMath::InvSqrt( sqrLength ); 1397 p[0] *= invLength; 1398 p[1] *= invLength; 1399 p[2] *= invLength; 1400 p[3] *= invLength; 1401 p[4] *= invLength; 1402 p[5] *= invLength; 1403 return invLength * sqrLength; 1404 } 1405 1406 ID_INLINE int idVec6::GetDimension() const { 1407 return 6; 1408 } 1409 1410 ID_INLINE const idVec3 &idVec6::SubVec3( int index ) const { 1411 return *reinterpret_cast<const idVec3 *>(p + index * 3); 1412 } 1413 1414 ID_INLINE idVec3 &idVec6::SubVec3( int index ) { 1415 return *reinterpret_cast<idVec3 *>(p + index * 3); 1416 } 1417 1418 ID_INLINE const float *idVec6::ToFloatPtr() const { 1419 return p; 1420 } 1421 1422 ID_INLINE float *idVec6::ToFloatPtr() { 1423 return p; 1424 } 1425 1426 //=============================================================== 1427 // 1428 // idPolar3 1429 // 1430 //=============================================================== 1431 1432 class idPolar3 { 1433 public: 1434 float radius, theta, phi; 1435 1436 idPolar3(); 1437 explicit idPolar3( const float radius, const float theta, const float phi ); 1438 1439 void Set( const float radius, const float theta, const float phi ); 1440 1441 float operator[]( const int index ) const; 1442 float & operator[]( const int index ); 1443 idPolar3 operator-() const; 1444 idPolar3 & operator=( const idPolar3 &a ); 1445 1446 idVec3 ToVec3() const; 1447 }; 1448 1449 ID_INLINE idPolar3::idPolar3() { 1450 } 1451 1452 ID_INLINE idPolar3::idPolar3( const float radius, const float theta, const float phi ) { 1453 assert( radius > 0 ); 1454 this->radius = radius; 1455 this->theta = theta; 1456 this->phi = phi; 1457 } 1458 1459 ID_INLINE void idPolar3::Set( const float radius, const float theta, const float phi ) { 1460 assert( radius > 0 ); 1461 this->radius = radius; 1462 this->theta = theta; 1463 this->phi = phi; 1464 } 1465 1466 ID_INLINE float idPolar3::operator[]( const int index ) const { 1467 return ( &radius )[ index ]; 1468 } 1469 1470 ID_INLINE float &idPolar3::operator[]( const int index ) { 1471 return ( &radius )[ index ]; 1472 } 1473 1474 ID_INLINE idPolar3 idPolar3::operator-() const { 1475 return idPolar3( radius, -theta, -phi ); 1476 } 1477 1478 ID_INLINE idPolar3 &idPolar3::operator=( const idPolar3 &a ) { 1479 radius = a.radius; 1480 theta = a.theta; 1481 phi = a.phi; 1482 return *this; 1483 } 1484 1485 ID_INLINE idVec3 idPolar3::ToVec3() const { 1486 float sp, cp, st, ct; 1487 idMath::SinCos( phi, sp, cp ); 1488 idMath::SinCos( theta, st, ct ); 1489 return idVec3( cp * radius * ct, cp * radius * st, radius * sp ); 1490 } 1491 1492 1493 /* 1494 =============================================================================== 1495 1496 Old 3D vector macros, should no longer be used. 1497 1498 =============================================================================== 1499 */ 1500 1501 #define VectorMA( v, s, b, o ) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s)) 1502 1503 #endif /* !__MATH_VECTOR_H__ */