2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 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.
14 Doom 3 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.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
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.
26 ===========================================================================
29 #ifndef __MATH_VECTOR_H__
30 #define __MATH_VECTOR_H__
33 ===============================================================================
37 ===============================================================================
40 #define VECTOR_EPSILON 0.001f
46 //===============================================================
50 //===============================================================
58 explicit idVec2( const float x, const float y );
60 void Set( const float x, const float y );
63 float operator[]( int index ) const;
64 float & operator[]( int index );
65 idVec2 operator-() const;
66 float operator*( const idVec2 &a ) const;
67 idVec2 operator*( const float a ) const;
68 idVec2 operator/( const float a ) const;
69 idVec2 operator+( const idVec2 &a ) const;
70 idVec2 operator-( const idVec2 &a ) const;
71 idVec2 & operator+=( const idVec2 &a );
72 idVec2 & operator-=( const idVec2 &a );
73 idVec2 & operator/=( const idVec2 &a );
74 idVec2 & operator/=( const float a );
75 idVec2 & operator*=( const float a );
77 friend idVec2 operator*( const float a, const idVec2 b );
79 bool Compare( const idVec2 &a ) const; // exact compare, no epsilon
80 bool Compare( const idVec2 &a, const float epsilon ) const; // compare with epsilon
81 bool operator==( const idVec2 &a ) const; // exact compare, no epsilon
82 bool operator!=( const idVec2 &a ) const; // exact compare, no epsilon
84 float Length( void ) const;
85 float LengthFast( void ) const;
86 float LengthSqr( void ) const;
87 float Normalize( void ); // returns length
88 float NormalizeFast( void ); // returns length
89 idVec2 & Truncate( float length ); // cap length
90 void Clamp( const idVec2 &min, const idVec2 &max );
91 void Snap( void ); // snap to closest integer value
92 void SnapInt( void ); // snap towards integer (floor)
94 int GetDimension( void ) const;
96 const float * ToFloatPtr( void ) const;
97 float * ToFloatPtr( void );
98 const char * ToString( int precision = 2 ) const;
100 void Lerp( const idVec2 &v1, const idVec2 &v2, const float l );
103 extern idVec2 vec2_origin;
104 #define vec2_zero vec2_origin
106 ID_INLINE idVec2::idVec2( void ) {
109 ID_INLINE idVec2::idVec2( const float x, const float y ) {
114 ID_INLINE void idVec2::Set( const float x, const float y ) {
119 ID_INLINE void idVec2::Zero( void ) {
123 ID_INLINE bool idVec2::Compare( const idVec2 &a ) const {
124 return ( ( x == a.x ) && ( y == a.y ) );
127 ID_INLINE bool idVec2::Compare( const idVec2 &a, const float epsilon ) const {
128 if ( idMath::Fabs( x - a.x ) > epsilon ) {
132 if ( idMath::Fabs( y - a.y ) > epsilon ) {
139 ID_INLINE bool idVec2::operator==( const idVec2 &a ) const {
143 ID_INLINE bool idVec2::operator!=( const idVec2 &a ) const {
144 return !Compare( a );
147 ID_INLINE float idVec2::operator[]( int index ) const {
148 return ( &x )[ index ];
151 ID_INLINE float& idVec2::operator[]( int index ) {
152 return ( &x )[ index ];
155 ID_INLINE float idVec2::Length( void ) const {
156 return ( float )idMath::Sqrt( x * x + y * y );
159 ID_INLINE float idVec2::LengthFast( void ) const {
162 sqrLength = x * x + y * y;
163 return sqrLength * idMath::RSqrt( sqrLength );
166 ID_INLINE float idVec2::LengthSqr( void ) const {
167 return ( x * x + y * y );
170 ID_INLINE float idVec2::Normalize( void ) {
171 float sqrLength, invLength;
173 sqrLength = x * x + y * y;
174 invLength = idMath::InvSqrt( sqrLength );
177 return invLength * sqrLength;
180 ID_INLINE float idVec2::NormalizeFast( void ) {
181 float lengthSqr, invLength;
183 lengthSqr = x * x + y * y;
184 invLength = idMath::RSqrt( lengthSqr );
187 return invLength * lengthSqr;
190 ID_INLINE idVec2 &idVec2::Truncate( float length ) {
198 length2 = LengthSqr();
199 if ( length2 > length * length ) {
200 ilength = length * idMath::InvSqrt( length2 );
209 ID_INLINE void idVec2::Clamp( const idVec2 &min, const idVec2 &max ) {
212 } else if ( x > max.x ) {
217 } else if ( y > max.y ) {
222 ID_INLINE void idVec2::Snap( void ) {
223 x = floor( x + 0.5f );
224 y = floor( y + 0.5f );
227 ID_INLINE void idVec2::SnapInt( void ) {
228 x = float( int( x ) );
229 y = float( int( y ) );
232 ID_INLINE idVec2 idVec2::operator-() const {
233 return idVec2( -x, -y );
236 ID_INLINE idVec2 idVec2::operator-( const idVec2 &a ) const {
237 return idVec2( x - a.x, y - a.y );
240 ID_INLINE float idVec2::operator*( const idVec2 &a ) const {
241 return x * a.x + y * a.y;
244 ID_INLINE idVec2 idVec2::operator*( const float a ) const {
245 return idVec2( x * a, y * a );
248 ID_INLINE idVec2 idVec2::operator/( const float a ) const {
249 float inva = 1.0f / a;
250 return idVec2( x * inva, y * inva );
253 ID_INLINE idVec2 operator*( const float a, const idVec2 b ) {
254 return idVec2( b.x * a, b.y * a );
257 ID_INLINE idVec2 idVec2::operator+( const idVec2 &a ) const {
258 return idVec2( x + a.x, y + a.y );
261 ID_INLINE idVec2 &idVec2::operator+=( const idVec2 &a ) {
268 ID_INLINE idVec2 &idVec2::operator/=( const idVec2 &a ) {
275 ID_INLINE idVec2 &idVec2::operator/=( const float a ) {
276 float inva = 1.0f / a;
283 ID_INLINE idVec2 &idVec2::operator-=( const idVec2 &a ) {
290 ID_INLINE idVec2 &idVec2::operator*=( const float a ) {
297 ID_INLINE int idVec2::GetDimension( void ) const {
301 ID_INLINE const float *idVec2::ToFloatPtr( void ) const {
305 ID_INLINE float *idVec2::ToFloatPtr( void ) {
310 //===============================================================
312 // idVec3 - 3D vector
314 //===============================================================
323 explicit idVec3( const float x, const float y, const float z );
325 void Set( const float x, const float y, const float z );
328 float operator[]( const int index ) const;
329 float & operator[]( const int index );
330 idVec3 operator-() const;
331 idVec3 & operator=( const idVec3 &a ); // required because of a msvc 6 & 7 bug
332 float operator*( const idVec3 &a ) const;
333 idVec3 operator*( const float a ) const;
334 idVec3 operator/( const float a ) const;
335 idVec3 operator+( const idVec3 &a ) const;
336 idVec3 operator-( const idVec3 &a ) const;
337 idVec3 & operator+=( const idVec3 &a );
338 idVec3 & operator-=( const idVec3 &a );
339 idVec3 & operator/=( const idVec3 &a );
340 idVec3 & operator/=( const float a );
341 idVec3 & operator*=( const float a );
343 friend idVec3 operator*( const float a, const idVec3 b );
345 bool Compare( const idVec3 &a ) const; // exact compare, no epsilon
346 bool Compare( const idVec3 &a, const float epsilon ) const; // compare with epsilon
347 bool operator==( const idVec3 &a ) const; // exact compare, no epsilon
348 bool operator!=( const idVec3 &a ) const; // exact compare, no epsilon
350 bool FixDegenerateNormal( void ); // fix degenerate axial cases
351 bool FixDenormals( void ); // change tiny numbers to zero
353 idVec3 Cross( const idVec3 &a ) const;
354 idVec3 & Cross( const idVec3 &a, const idVec3 &b );
355 float Length( void ) const;
356 float LengthSqr( void ) const;
357 float LengthFast( void ) const;
358 float Normalize( void ); // returns length
359 float NormalizeFast( void ); // returns length
360 idVec3 & Truncate( float length ); // cap length
361 void Clamp( const idVec3 &min, const idVec3 &max );
362 void Snap( void ); // snap to closest integer value
363 void SnapInt( void ); // snap towards integer (floor)
365 int GetDimension( void ) const;
367 float ToYaw( void ) const;
368 float ToPitch( void ) const;
369 idAngles ToAngles( void ) const;
370 idPolar3 ToPolar( void ) const;
371 idMat3 ToMat3( void ) const; // vector should be normalized
372 const idVec2 & ToVec2( void ) const;
373 idVec2 & ToVec2( void );
374 const float * ToFloatPtr( void ) const;
375 float * ToFloatPtr( void );
376 const char * ToString( int precision = 2 ) const;
378 void NormalVectors( idVec3 &left, idVec3 &down ) const; // vector should be normalized
379 void OrthogonalBasis( idVec3 &left, idVec3 &up ) const;
381 void ProjectOntoPlane( const idVec3 &normal, const float overBounce = 1.0f );
382 bool ProjectAlongPlane( const idVec3 &normal, const float epsilon, const float overBounce = 1.0f );
383 void ProjectSelfOntoSphere( const float radius );
385 void Lerp( const idVec3 &v1, const idVec3 &v2, const float l );
386 void SLerp( const idVec3 &v1, const idVec3 &v2, const float l );
389 extern idVec3 vec3_origin;
390 #define vec3_zero vec3_origin
392 ID_INLINE idVec3::idVec3( void ) {
395 ID_INLINE idVec3::idVec3( const float x, const float y, const float z ) {
401 ID_INLINE float idVec3::operator[]( const int index ) const {
402 return ( &x )[ index ];
405 ID_INLINE float &idVec3::operator[]( const int index ) {
406 return ( &x )[ index ];
409 ID_INLINE void idVec3::Set( const float x, const float y, const float z ) {
415 ID_INLINE void idVec3::Zero( void ) {
419 ID_INLINE idVec3 idVec3::operator-() const {
420 return idVec3( -x, -y, -z );
423 ID_INLINE idVec3 &idVec3::operator=( const idVec3 &a ) {
430 ID_INLINE idVec3 idVec3::operator-( const idVec3 &a ) const {
431 return idVec3( x - a.x, y - a.y, z - a.z );
434 ID_INLINE float idVec3::operator*( const idVec3 &a ) const {
435 return x * a.x + y * a.y + z * a.z;
438 ID_INLINE idVec3 idVec3::operator*( const float a ) const {
439 return idVec3( x * a, y * a, z * a );
442 ID_INLINE idVec3 idVec3::operator/( const float a ) const {
443 float inva = 1.0f / a;
444 return idVec3( x * inva, y * inva, z * inva );
447 ID_INLINE idVec3 operator*( const float a, const idVec3 b ) {
448 return idVec3( b.x * a, b.y * a, b.z * a );
451 ID_INLINE idVec3 idVec3::operator+( const idVec3 &a ) const {
452 return idVec3( x + a.x, y + a.y, z + a.z );
455 ID_INLINE idVec3 &idVec3::operator+=( const idVec3 &a ) {
463 ID_INLINE idVec3 &idVec3::operator/=( const idVec3 &a ) {
471 ID_INLINE idVec3 &idVec3::operator/=( const float a ) {
472 float inva = 1.0f / a;
480 ID_INLINE idVec3 &idVec3::operator-=( const idVec3 &a ) {
488 ID_INLINE idVec3 &idVec3::operator*=( const float a ) {
496 ID_INLINE bool idVec3::Compare( const idVec3 &a ) const {
497 return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) );
500 ID_INLINE bool idVec3::Compare( const idVec3 &a, const float epsilon ) const {
501 if ( idMath::Fabs( x - a.x ) > epsilon ) {
505 if ( idMath::Fabs( y - a.y ) > epsilon ) {
509 if ( idMath::Fabs( z - a.z ) > epsilon ) {
516 ID_INLINE bool idVec3::operator==( const idVec3 &a ) const {
520 ID_INLINE bool idVec3::operator!=( const idVec3 &a ) const {
521 return !Compare( a );
524 ID_INLINE float idVec3::NormalizeFast( void ) {
525 float sqrLength, invLength;
527 sqrLength = x * x + y * y + z * z;
528 invLength = idMath::RSqrt( sqrLength );
532 return invLength * sqrLength;
535 ID_INLINE bool idVec3::FixDegenerateNormal( void ) {
550 } else if ( z == 0.0f ) {
564 } else if ( y == 0.0f ) {
580 if ( idMath::Fabs( x ) == 1.0f ) {
581 if ( y != 0.0f || z != 0.0f ) {
586 } else if ( idMath::Fabs( y ) == 1.0f ) {
587 if ( x != 0.0f || z != 0.0f ) {
592 } else if ( idMath::Fabs( z ) == 1.0f ) {
593 if ( x != 0.0f || y != 0.0f ) {
602 ID_INLINE bool idVec3::FixDenormals( void ) {
603 bool denormal = false;
604 if ( fabs( x ) < 1e-30f ) {
608 if ( fabs( y ) < 1e-30f ) {
612 if ( fabs( z ) < 1e-30f ) {
619 ID_INLINE idVec3 idVec3::Cross( const idVec3 &a ) const {
620 return idVec3( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
623 ID_INLINE idVec3 &idVec3::Cross( const idVec3 &a, const idVec3 &b ) {
624 x = a.y * b.z - a.z * b.y;
625 y = a.z * b.x - a.x * b.z;
626 z = a.x * b.y - a.y * b.x;
631 ID_INLINE float idVec3::Length( void ) const {
632 return ( float )idMath::Sqrt( x * x + y * y + z * z );
635 ID_INLINE float idVec3::LengthSqr( void ) const {
636 return ( x * x + y * y + z * z );
639 ID_INLINE float idVec3::LengthFast( void ) const {
642 sqrLength = x * x + y * y + z * z;
643 return sqrLength * idMath::RSqrt( sqrLength );
646 ID_INLINE float idVec3::Normalize( void ) {
647 float sqrLength, invLength;
649 sqrLength = x * x + y * y + z * z;
650 invLength = idMath::InvSqrt( sqrLength );
654 return invLength * sqrLength;
657 ID_INLINE idVec3 &idVec3::Truncate( float length ) {
665 length2 = LengthSqr();
666 if ( length2 > length * length ) {
667 ilength = length * idMath::InvSqrt( length2 );
677 ID_INLINE void idVec3::Clamp( const idVec3 &min, const idVec3 &max ) {
680 } else if ( x > max.x ) {
685 } else if ( y > max.y ) {
690 } else if ( z > max.z ) {
695 ID_INLINE void idVec3::Snap( void ) {
696 x = floor( x + 0.5f );
697 y = floor( y + 0.5f );
698 z = floor( z + 0.5f );
701 ID_INLINE void idVec3::SnapInt( void ) {
702 x = float( int( x ) );
703 y = float( int( y ) );
704 z = float( int( z ) );
707 ID_INLINE int idVec3::GetDimension( void ) const {
711 ID_INLINE const idVec2 &idVec3::ToVec2( void ) const {
712 return *reinterpret_cast<const idVec2 *>(this);
715 ID_INLINE idVec2 &idVec3::ToVec2( void ) {
716 return *reinterpret_cast<idVec2 *>(this);
719 ID_INLINE const float *idVec3::ToFloatPtr( void ) const {
723 ID_INLINE float *idVec3::ToFloatPtr( void ) {
727 ID_INLINE void idVec3::NormalVectors( idVec3 &left, idVec3 &down ) const {
736 d = idMath::InvSqrt( d );
741 down = left.Cross( *this );
744 ID_INLINE void idVec3::OrthogonalBasis( idVec3 &left, idVec3 &up ) const {
747 if ( idMath::Fabs( z ) > 0.7f ) {
749 s = idMath::InvSqrt( l );
754 left[1] = -x * up[2];
759 s = idMath::InvSqrt( l );
763 up[0] = -z * left[1];
769 ID_INLINE void idVec3::ProjectOntoPlane( const idVec3 &normal, const float overBounce ) {
772 backoff = *this * normal;
774 if ( overBounce != 1.0 ) {
776 backoff *= overBounce;
778 backoff /= overBounce;
782 *this -= backoff * normal;
785 ID_INLINE bool idVec3::ProjectAlongPlane( const idVec3 &normal, const float epsilon, const float overBounce ) {
789 cross = this->Cross( normal ).Cross( (*this) );
790 // normalize so a fixed epsilon can be used
792 len = normal * cross;
793 if ( idMath::Fabs( len ) < epsilon ) {
796 cross *= overBounce * ( normal * (*this) ) / len;
802 //===============================================================
804 // idVec4 - 4D vector
806 //===============================================================
816 explicit idVec4( const float x, const float y, const float z, const float w );
818 void Set( const float x, const float y, const float z, const float w );
821 float operator[]( const int index ) const;
822 float & operator[]( const int index );
823 idVec4 operator-() const;
824 float operator*( const idVec4 &a ) const;
825 idVec4 operator*( const float a ) const;
826 idVec4 operator/( const float a ) const;
827 idVec4 operator+( const idVec4 &a ) const;
828 idVec4 operator-( const idVec4 &a ) const;
829 idVec4 & operator+=( const idVec4 &a );
830 idVec4 & operator-=( const idVec4 &a );
831 idVec4 & operator/=( const idVec4 &a );
832 idVec4 & operator/=( const float a );
833 idVec4 & operator*=( const float a );
835 friend idVec4 operator*( const float a, const idVec4 b );
837 bool Compare( const idVec4 &a ) const; // exact compare, no epsilon
838 bool Compare( const idVec4 &a, const float epsilon ) const; // compare with epsilon
839 bool operator==( const idVec4 &a ) const; // exact compare, no epsilon
840 bool operator!=( const idVec4 &a ) const; // exact compare, no epsilon
842 float Length( void ) const;
843 float LengthSqr( void ) const;
844 float Normalize( void ); // returns length
845 float NormalizeFast( void ); // returns length
847 int GetDimension( void ) const;
849 const idVec2 & ToVec2( void ) const;
850 idVec2 & ToVec2( void );
851 const idVec3 & ToVec3( void ) const;
852 idVec3 & ToVec3( void );
853 const float * ToFloatPtr( void ) const;
854 float * ToFloatPtr( void );
855 const char * ToString( int precision = 2 ) const;
857 void Lerp( const idVec4 &v1, const idVec4 &v2, const float l );
860 extern idVec4 vec4_origin;
861 #define vec4_zero vec4_origin
863 ID_INLINE idVec4::idVec4( void ) {
866 ID_INLINE idVec4::idVec4( const float x, const float y, const float z, const float w ) {
873 ID_INLINE void idVec4::Set( const float x, const float y, const float z, const float w ) {
880 ID_INLINE void idVec4::Zero( void ) {
881 x = y = z = w = 0.0f;
884 ID_INLINE float idVec4::operator[]( int index ) const {
885 return ( &x )[ index ];
888 ID_INLINE float& idVec4::operator[]( int index ) {
889 return ( &x )[ index ];
892 ID_INLINE idVec4 idVec4::operator-() const {
893 return idVec4( -x, -y, -z, -w );
896 ID_INLINE idVec4 idVec4::operator-( const idVec4 &a ) const {
897 return idVec4( x - a.x, y - a.y, z - a.z, w - a.w );
900 ID_INLINE float idVec4::operator*( const idVec4 &a ) const {
901 return x * a.x + y * a.y + z * a.z + w * a.w;
904 ID_INLINE idVec4 idVec4::operator*( const float a ) const {
905 return idVec4( x * a, y * a, z * a, w * a );
908 ID_INLINE idVec4 idVec4::operator/( const float a ) const {
909 float inva = 1.0f / a;
910 return idVec4( x * inva, y * inva, z * inva, w * inva );
913 ID_INLINE idVec4 operator*( const float a, const idVec4 b ) {
914 return idVec4( b.x * a, b.y * a, b.z * a, b.w * a );
917 ID_INLINE idVec4 idVec4::operator+( const idVec4 &a ) const {
918 return idVec4( x + a.x, y + a.y, z + a.z, w + a.w );
921 ID_INLINE idVec4 &idVec4::operator+=( const idVec4 &a ) {
930 ID_INLINE idVec4 &idVec4::operator/=( const idVec4 &a ) {
939 ID_INLINE idVec4 &idVec4::operator/=( const float a ) {
940 float inva = 1.0f / a;
949 ID_INLINE idVec4 &idVec4::operator-=( const idVec4 &a ) {
958 ID_INLINE idVec4 &idVec4::operator*=( const float a ) {
967 ID_INLINE bool idVec4::Compare( const idVec4 &a ) const {
968 return ( ( x == a.x ) && ( y == a.y ) && ( z == a.z ) && w == a.w );
971 ID_INLINE bool idVec4::Compare( const idVec4 &a, const float epsilon ) const {
972 if ( idMath::Fabs( x - a.x ) > epsilon ) {
976 if ( idMath::Fabs( y - a.y ) > epsilon ) {
980 if ( idMath::Fabs( z - a.z ) > epsilon ) {
984 if ( idMath::Fabs( w - a.w ) > epsilon ) {
991 ID_INLINE bool idVec4::operator==( const idVec4 &a ) const {
995 ID_INLINE bool idVec4::operator!=( const idVec4 &a ) const {
996 return !Compare( a );
999 ID_INLINE float idVec4::Length( void ) const {
1000 return ( float )idMath::Sqrt( x * x + y * y + z * z + w * w );
1003 ID_INLINE float idVec4::LengthSqr( void ) const {
1004 return ( x * x + y * y + z * z + w * w );
1007 ID_INLINE float idVec4::Normalize( void ) {
1008 float sqrLength, invLength;
1010 sqrLength = x * x + y * y + z * z + w * w;
1011 invLength = idMath::InvSqrt( sqrLength );
1016 return invLength * sqrLength;
1019 ID_INLINE float idVec4::NormalizeFast( void ) {
1020 float sqrLength, invLength;
1022 sqrLength = x * x + y * y + z * z + w * w;
1023 invLength = idMath::RSqrt( sqrLength );
1028 return invLength * sqrLength;
1031 ID_INLINE int idVec4::GetDimension( void ) const {
1035 ID_INLINE const idVec2 &idVec4::ToVec2( void ) const {
1036 return *reinterpret_cast<const idVec2 *>(this);
1039 ID_INLINE idVec2 &idVec4::ToVec2( void ) {
1040 return *reinterpret_cast<idVec2 *>(this);
1043 ID_INLINE const idVec3 &idVec4::ToVec3( void ) const {
1044 return *reinterpret_cast<const idVec3 *>(this);
1047 ID_INLINE idVec3 &idVec4::ToVec3( void ) {
1048 return *reinterpret_cast<idVec3 *>(this);
1051 ID_INLINE const float *idVec4::ToFloatPtr( void ) const {
1055 ID_INLINE float *idVec4::ToFloatPtr( void ) {
1060 //===============================================================
1062 // idVec5 - 5D vector
1064 //===============================================================
1075 explicit idVec5( const idVec3 &xyz, const idVec2 &st );
1076 explicit idVec5( const float x, const float y, const float z, const float s, const float t );
1078 float operator[]( int index ) const;
1079 float & operator[]( int index );
1080 idVec5 & operator=( const idVec3 &a );
1082 int GetDimension( void ) const;
1084 const idVec3 & ToVec3( void ) const;
1085 idVec3 & ToVec3( void );
1086 const float * ToFloatPtr( void ) const;
1087 float * ToFloatPtr( void );
1088 const char * ToString( int precision = 2 ) const;
1090 void Lerp( const idVec5 &v1, const idVec5 &v2, const float l );
1093 extern idVec5 vec5_origin;
1094 #define vec5_zero vec5_origin
1096 ID_INLINE idVec5::idVec5( void ) {
1099 ID_INLINE idVec5::idVec5( const idVec3 &xyz, const idVec2 &st ) {
1107 ID_INLINE idVec5::idVec5( const float x, const float y, const float z, const float s, const float t ) {
1115 ID_INLINE float idVec5::operator[]( int index ) const {
1116 return ( &x )[ index ];
1119 ID_INLINE float& idVec5::operator[]( int index ) {
1120 return ( &x )[ index ];
1123 ID_INLINE idVec5 &idVec5::operator=( const idVec3 &a ) {
1131 ID_INLINE int idVec5::GetDimension( void ) const {
1135 ID_INLINE const idVec3 &idVec5::ToVec3( void ) const {
1136 return *reinterpret_cast<const idVec3 *>(this);
1139 ID_INLINE idVec3 &idVec5::ToVec3( void ) {
1140 return *reinterpret_cast<idVec3 *>(this);
1143 ID_INLINE const float *idVec5::ToFloatPtr( void ) const {
1147 ID_INLINE float *idVec5::ToFloatPtr( void ) {
1152 //===============================================================
1154 // idVec6 - 6D vector
1156 //===============================================================
1161 explicit idVec6( const float *a );
1162 explicit idVec6( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 );
1164 void Set( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 );
1167 float operator[]( const int index ) const;
1168 float & operator[]( const int index );
1169 idVec6 operator-() const;
1170 idVec6 operator*( const float a ) const;
1171 idVec6 operator/( const float a ) const;
1172 float operator*( const idVec6 &a ) const;
1173 idVec6 operator-( const idVec6 &a ) const;
1174 idVec6 operator+( const idVec6 &a ) const;
1175 idVec6 & operator*=( const float a );
1176 idVec6 & operator/=( const float a );
1177 idVec6 & operator+=( const idVec6 &a );
1178 idVec6 & operator-=( const idVec6 &a );
1180 friend idVec6 operator*( const float a, const idVec6 b );
1182 bool Compare( const idVec6 &a ) const; // exact compare, no epsilon
1183 bool Compare( const idVec6 &a, const float epsilon ) const; // compare with epsilon
1184 bool operator==( const idVec6 &a ) const; // exact compare, no epsilon
1185 bool operator!=( const idVec6 &a ) const; // exact compare, no epsilon
1187 float Length( void ) const;
1188 float LengthSqr( void ) const;
1189 float Normalize( void ); // returns length
1190 float NormalizeFast( void ); // returns length
1192 int GetDimension( void ) const;
1194 const idVec3 & SubVec3( int index ) const;
1195 idVec3 & SubVec3( int index );
1196 const float * ToFloatPtr( void ) const;
1197 float * ToFloatPtr( void );
1198 const char * ToString( int precision = 2 ) const;
1204 extern idVec6 vec6_origin;
1205 #define vec6_zero vec6_origin
1206 extern idVec6 vec6_infinity;
1208 ID_INLINE idVec6::idVec6( void ) {
1211 ID_INLINE idVec6::idVec6( const float *a ) {
1212 memcpy( p, a, 6 * sizeof( float ) );
1215 ID_INLINE idVec6::idVec6( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 ) {
1224 ID_INLINE idVec6 idVec6::operator-() const {
1225 return idVec6( -p[0], -p[1], -p[2], -p[3], -p[4], -p[5] );
1228 ID_INLINE float idVec6::operator[]( const int index ) const {
1232 ID_INLINE float &idVec6::operator[]( const int index ) {
1236 ID_INLINE idVec6 idVec6::operator*( const float a ) const {
1237 return idVec6( p[0]*a, p[1]*a, p[2]*a, p[3]*a, p[4]*a, p[5]*a );
1240 ID_INLINE float idVec6::operator*( const idVec6 &a ) const {
1241 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];
1244 ID_INLINE idVec6 idVec6::operator/( const float a ) const {
1247 assert( a != 0.0f );
1249 return idVec6( p[0]*inva, p[1]*inva, p[2]*inva, p[3]*inva, p[4]*inva, p[5]*inva );
1252 ID_INLINE idVec6 idVec6::operator+( const idVec6 &a ) const {
1253 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] );
1256 ID_INLINE idVec6 idVec6::operator-( const idVec6 &a ) const {
1257 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] );
1260 ID_INLINE idVec6 &idVec6::operator*=( const float a ) {
1270 ID_INLINE idVec6 &idVec6::operator/=( const float a ) {
1273 assert( a != 0.0f );
1284 ID_INLINE idVec6 &idVec6::operator+=( const idVec6 &a ) {
1294 ID_INLINE idVec6 &idVec6::operator-=( const idVec6 &a ) {
1304 ID_INLINE idVec6 operator*( const float a, const idVec6 b ) {
1308 ID_INLINE bool idVec6::Compare( const idVec6 &a ) const {
1309 return ( ( p[0] == a[0] ) && ( p[1] == a[1] ) && ( p[2] == a[2] ) &&
1310 ( p[3] == a[3] ) && ( p[4] == a[4] ) && ( p[5] == a[5] ) );
1313 ID_INLINE bool idVec6::Compare( const idVec6 &a, const float epsilon ) const {
1314 if ( idMath::Fabs( p[0] - a[0] ) > epsilon ) {
1318 if ( idMath::Fabs( p[1] - a[1] ) > epsilon ) {
1322 if ( idMath::Fabs( p[2] - a[2] ) > epsilon ) {
1326 if ( idMath::Fabs( p[3] - a[3] ) > epsilon ) {
1330 if ( idMath::Fabs( p[4] - a[4] ) > epsilon ) {
1334 if ( idMath::Fabs( p[5] - a[5] ) > epsilon ) {
1341 ID_INLINE bool idVec6::operator==( const idVec6 &a ) const {
1342 return Compare( a );
1345 ID_INLINE bool idVec6::operator!=( const idVec6 &a ) const {
1346 return !Compare( a );
1349 ID_INLINE void idVec6::Set( const float a1, const float a2, const float a3, const float a4, const float a5, const float a6 ) {
1358 ID_INLINE void idVec6::Zero( void ) {
1359 p[0] = p[1] = p[2] = p[3] = p[4] = p[5] = 0.0f;
1362 ID_INLINE float idVec6::Length( void ) const {
1363 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] );
1366 ID_INLINE float idVec6::LengthSqr( void ) const {
1367 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] );
1370 ID_INLINE float idVec6::Normalize( void ) {
1371 float sqrLength, invLength;
1373 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];
1374 invLength = idMath::InvSqrt( sqrLength );
1381 return invLength * sqrLength;
1384 ID_INLINE float idVec6::NormalizeFast( void ) {
1385 float sqrLength, invLength;
1387 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];
1388 invLength = idMath::RSqrt( sqrLength );
1395 return invLength * sqrLength;
1398 ID_INLINE int idVec6::GetDimension( void ) const {
1402 ID_INLINE const idVec3 &idVec6::SubVec3( int index ) const {
1403 return *reinterpret_cast<const idVec3 *>(p + index * 3);
1406 ID_INLINE idVec3 &idVec6::SubVec3( int index ) {
1407 return *reinterpret_cast<idVec3 *>(p + index * 3);
1410 ID_INLINE const float *idVec6::ToFloatPtr( void ) const {
1414 ID_INLINE float *idVec6::ToFloatPtr( void ) {
1419 //===============================================================
1421 // idVecX - arbitrary sized vector
1423 // The vector lives on 16 byte aligned and 16 byte padded memory.
1425 // NOTE: due to the temporary memory pool idVecX cannot be used by multiple threads
1427 //===============================================================
1429 #define VECX_MAX_TEMP 1024
1430 #define VECX_QUAD( x ) ( ( ( ( x ) + 3 ) & ~3 ) * sizeof( float ) )
1431 #define VECX_CLEAREND() int s = size; while( s < ( ( s + 3) & ~3 ) ) { p[s++] = 0.0f; }
1432 #define VECX_ALLOCA( n ) ( (float *) _alloca16( VECX_QUAD( n ) ) )
1436 friend class idMatX;
1440 explicit idVecX( int length );
1441 explicit idVecX( int length, float *data );
1444 float operator[]( const int index ) const;
1445 float & operator[]( const int index );
1446 idVecX operator-() const;
1447 idVecX & operator=( const idVecX &a );
1448 idVecX operator*( const float a ) const;
1449 idVecX operator/( const float a ) const;
1450 float operator*( const idVecX &a ) const;
1451 idVecX operator-( const idVecX &a ) const;
1452 idVecX operator+( const idVecX &a ) const;
1453 idVecX & operator*=( const float a );
1454 idVecX & operator/=( const float a );
1455 idVecX & operator+=( const idVecX &a );
1456 idVecX & operator-=( const idVecX &a );
1458 friend idVecX operator*( const float a, const idVecX b );
1460 bool Compare( const idVecX &a ) const; // exact compare, no epsilon
1461 bool Compare( const idVecX &a, const float epsilon ) const; // compare with epsilon
1462 bool operator==( const idVecX &a ) const; // exact compare, no epsilon
1463 bool operator!=( const idVecX &a ) const; // exact compare, no epsilon
1465 void SetSize( int size );
1466 void ChangeSize( int size, bool makeZero = false );
1467 int GetSize( void ) const { return size; }
1468 void SetData( int length, float *data );
1470 void Zero( int length );
1471 void Random( int seed, float l = 0.0f, float u = 1.0f );
1472 void Random( int length, int seed, float l = 0.0f, float u = 1.0f );
1473 void Negate( void );
1474 void Clamp( float min, float max );
1475 idVecX & SwapElements( int e1, int e2 );
1477 float Length( void ) const;
1478 float LengthSqr( void ) const;
1479 idVecX Normalize( void ) const;
1480 float NormalizeSelf( void );
1482 int GetDimension( void ) const;
1484 const idVec3 & SubVec3( int index ) const;
1485 idVec3 & SubVec3( int index );
1486 const idVec6 & SubVec6( int index ) const;
1487 idVec6 & SubVec6( int index );
1488 const float * ToFloatPtr( void ) const;
1489 float * ToFloatPtr( void );
1490 const char * ToString( int precision = 2 ) const;
1493 int size; // size of the vector
1494 int alloced; // if -1 p points to data set with SetData
1495 float * p; // memory the vector is stored
1497 static float temp[VECX_MAX_TEMP+4]; // used to store intermediate results
1498 static float * tempPtr; // pointer to 16 byte aligned temporary memory
1499 static int tempIndex; // index into memory pool, wraps around
1502 void SetTempSize( int size );
1506 ID_INLINE idVecX::idVecX( void ) {
1511 ID_INLINE idVecX::idVecX( int length ) {
1517 ID_INLINE idVecX::idVecX( int length, float *data ) {
1520 SetData( length, data );
1523 ID_INLINE idVecX::~idVecX( void ) {
1524 // if not temp memory
1525 if ( p && ( p < idVecX::tempPtr || p >= idVecX::tempPtr + VECX_MAX_TEMP ) && alloced != -1 ) {
1530 ID_INLINE float idVecX::operator[]( const int index ) const {
1531 assert( index >= 0 && index < size );
1535 ID_INLINE float &idVecX::operator[]( const int index ) {
1536 assert( index >= 0 && index < size );
1540 ID_INLINE idVecX idVecX::operator-() const {
1544 m.SetTempSize( size );
1545 for ( i = 0; i < size; i++ ) {
1551 ID_INLINE idVecX &idVecX::operator=( const idVecX &a ) {
1554 SIMDProcessor->Copy16( p, a.p, a.size );
1556 memcpy( p, a.p, a.size * sizeof( float ) );
1558 idVecX::tempIndex = 0;
1562 ID_INLINE idVecX idVecX::operator+( const idVecX &a ) const {
1565 assert( size == a.size );
1566 m.SetTempSize( size );
1568 SIMDProcessor->Add16( m.p, p, a.p, size );
1571 for ( i = 0; i < size; i++ ) {
1572 m.p[i] = p[i] + a.p[i];
1578 ID_INLINE idVecX idVecX::operator-( const idVecX &a ) const {
1581 assert( size == a.size );
1582 m.SetTempSize( size );
1584 SIMDProcessor->Sub16( m.p, p, a.p, size );
1587 for ( i = 0; i < size; i++ ) {
1588 m.p[i] = p[i] - a.p[i];
1594 ID_INLINE idVecX &idVecX::operator+=( const idVecX &a ) {
1595 assert( size == a.size );
1597 SIMDProcessor->AddAssign16( p, a.p, size );
1600 for ( i = 0; i < size; i++ ) {
1604 idVecX::tempIndex = 0;
1608 ID_INLINE idVecX &idVecX::operator-=( const idVecX &a ) {
1609 assert( size == a.size );
1611 SIMDProcessor->SubAssign16( p, a.p, size );
1614 for ( i = 0; i < size; i++ ) {
1618 idVecX::tempIndex = 0;
1622 ID_INLINE idVecX idVecX::operator*( const float a ) const {
1625 m.SetTempSize( size );
1627 SIMDProcessor->Mul16( m.p, p, a, size );
1630 for ( i = 0; i < size; i++ ) {
1637 ID_INLINE idVecX &idVecX::operator*=( const float a ) {
1639 SIMDProcessor->MulAssign16( p, a, size );
1642 for ( i = 0; i < size; i++ ) {
1649 ID_INLINE idVecX idVecX::operator/( const float a ) const {
1650 assert( a != 0.0f );
1651 return (*this) * ( 1.0f / a );
1654 ID_INLINE idVecX &idVecX::operator/=( const float a ) {
1655 assert( a != 0.0f );
1656 (*this) *= ( 1.0f / a );
1660 ID_INLINE idVecX operator*( const float a, const idVecX b ) {
1664 ID_INLINE float idVecX::operator*( const idVecX &a ) const {
1668 assert( size == a.size );
1669 for ( i = 0; i < size; i++ ) {
1670 sum += p[i] * a.p[i];
1675 ID_INLINE bool idVecX::Compare( const idVecX &a ) const {
1678 assert( size == a.size );
1679 for ( i = 0; i < size; i++ ) {
1680 if ( p[i] != a.p[i] ) {
1687 ID_INLINE bool idVecX::Compare( const idVecX &a, const float epsilon ) const {
1690 assert( size == a.size );
1691 for ( i = 0; i < size; i++ ) {
1692 if ( idMath::Fabs( p[i] - a.p[i] ) > epsilon ) {
1699 ID_INLINE bool idVecX::operator==( const idVecX &a ) const {
1700 return Compare( a );
1703 ID_INLINE bool idVecX::operator!=( const idVecX &a ) const {
1704 return !Compare( a );
1707 ID_INLINE void idVecX::SetSize( int newSize ) {
1708 int alloc = ( newSize + 3 ) & ~3;
1709 if ( alloc > alloced && alloced != -1 ) {
1713 p = (float *) Mem_Alloc16( alloc * sizeof( float ) );
1720 ID_INLINE void idVecX::ChangeSize( int newSize, bool makeZero ) {
1721 int alloc = ( newSize + 3 ) & ~3;
1722 if ( alloc > alloced && alloced != -1 ) {
1724 p = (float *) Mem_Alloc16( alloc * sizeof( float ) );
1727 for ( int i = 0; i < size; i++ ) {
1730 Mem_Free16( oldVec );
1733 // zero any new elements
1734 for ( int i = size; i < newSize; i++ ) {
1743 ID_INLINE void idVecX::SetTempSize( int newSize ) {
1746 alloced = ( newSize + 3 ) & ~3;
1747 assert( alloced < VECX_MAX_TEMP );
1748 if ( idVecX::tempIndex + alloced > VECX_MAX_TEMP ) {
1749 idVecX::tempIndex = 0;
1751 p = idVecX::tempPtr + idVecX::tempIndex;
1752 idVecX::tempIndex += alloced;
1756 ID_INLINE void idVecX::SetData( int length, float *data ) {
1757 if ( p && ( p < idVecX::tempPtr || p >= idVecX::tempPtr + VECX_MAX_TEMP ) && alloced != -1 ) {
1760 assert( ( ( (int) data ) & 15 ) == 0 ); // data must be 16 byte aligned
1767 ID_INLINE void idVecX::Zero( void ) {
1769 SIMDProcessor->Zero16( p, size );
1771 memset( p, 0, size * sizeof( float ) );
1775 ID_INLINE void idVecX::Zero( int length ) {
1778 SIMDProcessor->Zero16( p, length );
1780 memset( p, 0, size * sizeof( float ) );
1784 ID_INLINE void idVecX::Random( int seed, float l, float u ) {
1787 idRandom rnd( seed );
1790 for ( i = 0; i < size; i++ ) {
1791 p[i] = l + rnd.RandomFloat() * c;
1795 ID_INLINE void idVecX::Random( int length, int seed, float l, float u ) {
1798 idRandom rnd( seed );
1802 for ( i = 0; i < size; i++ ) {
1803 p[i] = l + rnd.RandomFloat() * c;
1807 ID_INLINE void idVecX::Negate( void ) {
1809 SIMDProcessor->Negate16( p, size );
1812 for ( i = 0; i < size; i++ ) {
1818 ID_INLINE void idVecX::Clamp( float min, float max ) {
1820 for ( i = 0; i < size; i++ ) {
1823 } else if ( p[i] > max ) {
1829 ID_INLINE idVecX &idVecX::SwapElements( int e1, int e2 ) {
1837 ID_INLINE float idVecX::Length( void ) const {
1841 for ( i = 0; i < size; i++ ) {
1844 return idMath::Sqrt( sum );
1847 ID_INLINE float idVecX::LengthSqr( void ) const {
1851 for ( i = 0; i < size; i++ ) {
1857 ID_INLINE idVecX idVecX::Normalize( void ) const {
1860 float invSqrt, sum = 0.0f;
1862 m.SetTempSize( size );
1863 for ( i = 0; i < size; i++ ) {
1866 invSqrt = idMath::InvSqrt( sum );
1867 for ( i = 0; i < size; i++ ) {
1868 m.p[i] = p[i] * invSqrt;
1873 ID_INLINE float idVecX::NormalizeSelf( void ) {
1874 float invSqrt, sum = 0.0f;
1876 for ( i = 0; i < size; i++ ) {
1879 invSqrt = idMath::InvSqrt( sum );
1880 for ( i = 0; i < size; i++ ) {
1883 return invSqrt * sum;
1886 ID_INLINE int idVecX::GetDimension( void ) const {
1890 ID_INLINE idVec3 &idVecX::SubVec3( int index ) {
1891 assert( index >= 0 && index * 3 + 3 <= size );
1892 return *reinterpret_cast<idVec3 *>(p + index * 3);
1895 ID_INLINE const idVec3 &idVecX::SubVec3( int index ) const {
1896 assert( index >= 0 && index * 3 + 3 <= size );
1897 return *reinterpret_cast<const idVec3 *>(p + index * 3);
1900 ID_INLINE idVec6 &idVecX::SubVec6( int index ) {
1901 assert( index >= 0 && index * 6 + 6 <= size );
1902 return *reinterpret_cast<idVec6 *>(p + index * 6);
1905 ID_INLINE const idVec6 &idVecX::SubVec6( int index ) const {
1906 assert( index >= 0 && index * 6 + 6 <= size );
1907 return *reinterpret_cast<const idVec6 *>(p + index * 6);
1910 ID_INLINE const float *idVecX::ToFloatPtr( void ) const {
1914 ID_INLINE float *idVecX::ToFloatPtr( void ) {
1919 //===============================================================
1923 //===============================================================
1927 float radius, theta, phi;
1930 explicit idPolar3( const float radius, const float theta, const float phi );
1932 void Set( const float radius, const float theta, const float phi );
1934 float operator[]( const int index ) const;
1935 float & operator[]( const int index );
1936 idPolar3 operator-() const;
1937 idPolar3 & operator=( const idPolar3 &a );
1939 idVec3 ToVec3( void ) const;
1942 ID_INLINE idPolar3::idPolar3( void ) {
1945 ID_INLINE idPolar3::idPolar3( const float radius, const float theta, const float phi ) {
1946 assert( radius > 0 );
1947 this->radius = radius;
1948 this->theta = theta;
1952 ID_INLINE void idPolar3::Set( const float radius, const float theta, const float phi ) {
1953 assert( radius > 0 );
1954 this->radius = radius;
1955 this->theta = theta;
1959 ID_INLINE float idPolar3::operator[]( const int index ) const {
1960 return ( &radius )[ index ];
1963 ID_INLINE float &idPolar3::operator[]( const int index ) {
1964 return ( &radius )[ index ];
1967 ID_INLINE idPolar3 idPolar3::operator-() const {
1968 return idPolar3( radius, -theta, -phi );
1971 ID_INLINE idPolar3 &idPolar3::operator=( const idPolar3 &a ) {
1978 ID_INLINE idVec3 idPolar3::ToVec3( void ) const {
1979 float sp, cp, st, ct;
1980 idMath::SinCos( phi, sp, cp );
1981 idMath::SinCos( theta, st, ct );
1982 return idVec3( cp * radius * ct, cp * radius * st, radius * sp );
1987 ===============================================================================
1989 Old 3D vector macros, should no longer be used.
1991 ===============================================================================
1994 #define DotProduct( a, b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
1995 #define VectorSubtract( a, b, c ) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
1996 #define VectorAdd( a, b, c ) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
1997 #define VectorScale( v, s, o ) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
1998 #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))
1999 #define VectorCopy( a, b ) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
2002 #endif /* !__MATH_VECTOR_H__ */