Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

math_vector.h

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 #ifndef __MATH_VECTOR_H__
00023 #define __MATH_VECTOR_H__
00024 
00025 #pragma warning(disable : 4244)
00026 
00027 #include <math.h>
00028 #include <assert.h>
00029 
00030 //#define DotProduct(a,b)           ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
00031 //#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
00032 //#define VectorAdd(a,b,c)      ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
00033 //#define VectorCopy(a,b)           ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
00034 //#define VectorCopy(a,b)           ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
00035 
00036 //#define   VectorScale(v, s, o)    ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
00037 #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))
00038 //#define CrossProduct(a,b,c)       ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
00039 
00040 #define DotProduct4(x,y)        ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
00041 #define VectorSubtract4(a,b,c)  ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
00042 #define VectorAdd4(a,b,c)       ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
00043 #define VectorCopy4(a,b)        ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
00044 #define VectorScale4(v, s, o)   ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
00045 #define VectorMA4(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),(o)[3]=(v)[3]+(b)[3]*(s))
00046 
00047 
00048 //#define VectorClear(a)            ((a)[0]=(a)[1]=(a)[2]=0)
00049 #define VectorNegate(a,b)       ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
00050 //#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
00051 #define Vector4Copy(a,b)        ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
00052 
00053 #define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
00054 
00055 
00056 //#include "util_heap.h"
00057 
00058 #ifndef EQUAL_EPSILON
00059 #define EQUAL_EPSILON   0.001
00060 #endif
00061 
00062 float Q_fabs( float f );
00063 
00064 #ifndef ID_INLINE
00065 #ifdef _WIN32
00066 #define ID_INLINE __inline 
00067 #else
00068 #define ID_INLINE inline
00069 #endif
00070 #endif
00071 
00072 // if this is defined, vec3 will take four elements, which may allow
00073 // easier SIMD optimizations
00074 //#define   FAT_VEC3
00075 //#ifdef __ppc__
00076 //#pragma align(16)
00077 //#endif
00078 
00079 class angles_t;
00080 #ifdef __ppc__
00081 // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, 
00082 // runs *much* faster than calling sqrt(). We'll use two Newton-Raphson 
00083 // refinement steps to get bunch more precision in the 1/sqrt() value for very little cost. 
00084 // We'll then multiply 1/sqrt times the original value to get the sqrt. 
00085 // This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive) 
00086 // it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments). 
00087 
00088 static inline float idSqrt(float x) {
00089     const float half = 0.5;
00090     const float one = 1.0;
00091     float B, y0, y1;
00092 
00093     // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
00094     if (fabs(x) == 0.0)
00095         return x;
00096     B = x;
00097     
00098 #ifdef __GNUC__
00099     asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
00100 #else
00101     y0 = __frsqrte(B);
00102 #endif
00103     /* First refinement step */
00104     
00105     y1 = y0 + half*y0*(one - B*y0*y0);
00106     
00107     /* Second refinement step -- copy the output of the last step to the input of this step */
00108     
00109     y0 = y1;
00110     y1 = y0 + half*y0*(one - B*y0*y0);
00111     
00112     /* Get sqrt(x) from x * 1/sqrt(x) */
00113     return x * y1;
00114 }
00115 #else
00116 static inline double idSqrt(double x) {
00117     return sqrt(x);
00118 }
00119 #endif
00120 
00121 
00122 //class idVec3_t  : public idHeap<idVec3_t> {
00123 class idVec3_t {
00124 public: 
00125 #ifndef FAT_VEC3
00126         float x,y,z;
00127 #else
00128         float x,y,z,dist;
00129 #endif
00130 
00131 #ifndef FAT_VEC3
00132                     idVec3_t() {};
00133 #else
00134                     idVec3_t() {dist = 0.0f;};
00135 #endif
00136                     idVec3_t( const float x, const float y, const float z );
00137 
00138                     operator float *();
00139 
00140     float           operator[]( const int index ) const;
00141     float           &operator[]( const int index );
00142 
00143     void            set( const float x, const float y, const float z );
00144 
00145     idVec3_t            operator-() const;
00146 
00147     idVec3_t            &operator=( const idVec3_t &a );
00148 
00149     float           operator*( const idVec3_t &a ) const;
00150     idVec3_t            operator*( const float a ) const;
00151     friend idVec3_t operator*( float a, idVec3_t b );
00152 
00153     idVec3_t            operator+( const idVec3_t &a ) const;
00154     idVec3_t            operator-( const idVec3_t &a ) const;
00155     
00156     idVec3_t            &operator+=( const idVec3_t &a );
00157     idVec3_t            &operator-=( const idVec3_t &a );
00158     idVec3_t            &operator*=( const float a );
00159 
00160     int             operator==( const idVec3_t &a ) const;
00161     int             operator!=( const idVec3_t &a ) const;
00162 
00163     idVec3_t            Cross( const idVec3_t &a ) const;
00164     idVec3_t            &Cross( const idVec3_t &a, const idVec3_t &b );
00165 
00166     float           Length( void ) const;
00167     float           Normalize( void );
00168 
00169     void            Zero( void );
00170     void            Snap( void );
00171     void            SnapTowards( const idVec3_t &to );
00172 
00173     float           toYaw( void );
00174     float           toPitch( void );
00175     angles_t        toAngles( void );
00176     friend idVec3_t LerpVector( const idVec3_t &w1, const idVec3_t &w2, const float t );
00177 
00178     char            *string( void );
00179 };
00180 
00181 extern idVec3_t vec_zero;
00182 
00183 ID_INLINE idVec3_t::idVec3_t( const float x, const float y, const float z ) {
00184     this->x = x;
00185     this->y = y;
00186     this->z = z;
00187 #ifdef  FAT_VEC3
00188     this->dist = 0.0f;
00189 #endif
00190 }
00191 
00192 ID_INLINE float idVec3_t::operator[]( const int index ) const {
00193     return ( &x )[ index ];
00194 }
00195 
00196 ID_INLINE float &idVec3_t::operator[]( const int index ) {
00197     return ( &x )[ index ];
00198 }
00199 
00200 ID_INLINE idVec3_t::operator float *( void ) {
00201     return &x;
00202 }
00203 
00204 ID_INLINE idVec3_t idVec3_t::operator-() const {
00205     return idVec3_t( -x, -y, -z );
00206 }
00207     
00208 ID_INLINE idVec3_t &idVec3_t::operator=( const idVec3_t &a ) { 
00209     x = a.x;
00210     y = a.y;
00211     z = a.z;
00212     
00213     return *this;
00214 }
00215 
00216 ID_INLINE void idVec3_t::set( const float x, const float y, const float z ) {
00217     this->x = x;
00218     this->y = y;
00219     this->z = z;
00220 }
00221 
00222 ID_INLINE idVec3_t idVec3_t::operator-( const idVec3_t &a ) const {
00223     return idVec3_t( x - a.x, y - a.y, z - a.z );
00224 }
00225 
00226 ID_INLINE float idVec3_t::operator*( const idVec3_t &a ) const {
00227     return x * a.x + y * a.y + z * a.z;
00228 }
00229 
00230 ID_INLINE idVec3_t idVec3_t::operator*( const float a ) const {
00231     return idVec3_t( x * a, y * a, z * a );
00232 }
00233 
00234 ID_INLINE idVec3_t operator*( const float a, const idVec3_t b ) {
00235     return idVec3_t( b.x * a, b.y * a, b.z * a );
00236 }
00237 
00238 ID_INLINE idVec3_t idVec3_t::operator+( const idVec3_t &a ) const {
00239     return idVec3_t( x + a.x, y + a.y, z + a.z );
00240 }
00241 
00242 ID_INLINE idVec3_t &idVec3_t::operator+=( const idVec3_t &a ) {
00243     x += a.x;
00244     y += a.y;
00245     z += a.z;
00246 
00247     return *this;
00248 }
00249 
00250 ID_INLINE idVec3_t &idVec3_t::operator-=( const idVec3_t &a ) {
00251     x -= a.x;
00252     y -= a.y;
00253     z -= a.z;
00254 
00255     return *this;
00256 }
00257 
00258 ID_INLINE idVec3_t &idVec3_t::operator*=( const float a ) {
00259     x *= a;
00260     y *= a;
00261     z *= a;
00262 
00263     return *this;
00264 }
00265 
00266 ID_INLINE int idVec3_t::operator==( const idVec3_t &a ) const {
00267     if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
00268         return false;
00269     }
00270             
00271     if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
00272         return false;
00273     }
00274 
00275     if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
00276         return false;
00277     }
00278 
00279     return true;
00280 }
00281 
00282 ID_INLINE int idVec3_t::operator!=( const idVec3_t &a ) const {
00283     if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
00284         return true;
00285     }
00286             
00287     if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
00288         return true;
00289     }
00290 
00291     if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
00292         return true;
00293     }
00294 
00295     return false;
00296 }
00297 
00298 ID_INLINE idVec3_t idVec3_t::Cross( const idVec3_t &a ) const {
00299     return idVec3_t( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
00300 }
00301 
00302 ID_INLINE idVec3_t &idVec3_t::Cross( const idVec3_t &a, const idVec3_t &b ) {
00303     x = a.y * b.z - a.z * b.y;
00304     y = a.z * b.x - a.x * b.z;
00305     z = a.x * b.y - a.y * b.x;
00306 
00307     return *this;
00308 }
00309 
00310 ID_INLINE float idVec3_t::Length( void ) const {
00311     float length;
00312     
00313     length = x * x + y * y + z * z;
00314     return ( float )idSqrt( length );
00315 }
00316 
00317 ID_INLINE float idVec3_t::Normalize( void ) {
00318     float length;
00319     float ilength;
00320 
00321     length = this->Length();
00322     if ( length ) {
00323         ilength = 1.0f / length;
00324         x *= ilength;
00325         y *= ilength;
00326         z *= ilength;
00327     }
00328         
00329     return length;
00330 }
00331 
00332 ID_INLINE void idVec3_t::Zero( void ) {
00333     x = 0.0f;
00334     y = 0.0f;
00335     z = 0.0f;
00336 }
00337 
00338 ID_INLINE void idVec3_t::Snap( void ) {
00339     x = float( int( x ) );
00340     y = float( int( y ) );
00341     z = float( int( z ) );
00342 }
00343 
00344 /*
00345 ======================
00346 SnapTowards
00347 
00348 Round a vector to integers for more efficient network
00349 transmission, but make sure that it rounds towards a given point
00350 rather than blindly truncating.  This prevents it from truncating 
00351 into a wall.
00352 ======================
00353 */
00354 ID_INLINE void idVec3_t::SnapTowards( const idVec3_t &to ) {
00355     if ( to.x <= x ) {
00356         x = float( int( x ) );
00357     } else {
00358         x = float( int( x ) + 1 );
00359     }
00360 
00361     if ( to.y <= y ) {
00362         y = float( int( y ) );
00363     } else {
00364         y = float( int( y ) + 1 );
00365     }
00366 
00367     if ( to.z <= z ) {
00368         z = float( int( z ) );
00369     } else {
00370         z = float( int( z ) + 1 );
00371     }
00372 }
00373 
00374 //===============================================================
00375 
00376 class Bounds {
00377 public:
00378     idVec3_t    b[2];
00379 
00380             Bounds();
00381             Bounds( const idVec3_t &mins, const idVec3_t &maxs );
00382 
00383     void    Clear();
00384     void    Zero();
00385     float   Radius();       // radius from origin, not from center
00386     idVec3_t    Center();
00387     void    AddPoint( const idVec3_t &v );
00388     void    AddBounds( const Bounds &bb );
00389     bool    IsCleared();
00390     bool    ContainsPoint( const idVec3_t &p );
00391     bool    IntersectsBounds( const Bounds &b2 );   // touching is NOT intersecting
00392 };
00393 
00394 extern Bounds   boundsZero;
00395 
00396 ID_INLINE Bounds::Bounds(){
00397 }
00398 
00399 ID_INLINE bool Bounds::IsCleared() {
00400     return b[0][0] > b[1][0];
00401 }
00402 
00403 ID_INLINE bool Bounds::ContainsPoint( const idVec3_t &p ) {
00404     if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
00405         || p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
00406         return false;
00407     }
00408     return true;
00409 }
00410 
00411 ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
00412     if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
00413         || b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
00414         return false;
00415     }
00416     return true;
00417 }
00418 
00419 ID_INLINE Bounds::Bounds( const idVec3_t &mins, const idVec3_t &maxs ) {
00420     b[0] = mins;
00421     b[1] = maxs;
00422 }
00423 
00424 ID_INLINE idVec3_t Bounds::Center() {
00425     return idVec3_t( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
00426 }
00427 
00428 ID_INLINE void Bounds::Clear() {
00429     b[0][0] = b[0][1] = b[0][2] = 99999;
00430     b[1][0] = b[1][1] = b[1][2] = -99999;
00431 }
00432 
00433 ID_INLINE void Bounds::Zero() {
00434     b[0][0] = b[0][1] = b[0][2] =
00435     b[1][0] = b[1][1] = b[1][2] = 0;
00436 }
00437 
00438 ID_INLINE void Bounds::AddPoint( const idVec3_t &v ) {
00439     if ( v[0] < b[0][0]) {
00440         b[0][0] = v[0];
00441     }
00442     if ( v[0] > b[1][0]) {
00443         b[1][0] = v[0];
00444     }
00445     if ( v[1] < b[0][1] ) {
00446         b[0][1] = v[1];
00447     }
00448     if ( v[1] > b[1][1]) {
00449         b[1][1] = v[1];
00450     }
00451     if ( v[2] < b[0][2] ) {
00452         b[0][2] = v[2];
00453     }
00454     if ( v[2] > b[1][2]) {
00455         b[1][2] = v[2];
00456     }
00457 }
00458 
00459 
00460 ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
00461     if ( bb.b[0][0] < b[0][0]) {
00462         b[0][0] = bb.b[0][0];
00463     }
00464     if ( bb.b[0][1] < b[0][1]) {
00465         b[0][1] = bb.b[0][1];
00466     }
00467     if ( bb.b[0][2] < b[0][2]) {
00468         b[0][2] = bb.b[0][2];
00469     }
00470 
00471     if ( bb.b[1][0] > b[1][0]) {
00472         b[1][0] = bb.b[1][0];
00473     }
00474     if ( bb.b[1][1] > b[1][1]) {
00475         b[1][1] = bb.b[1][1];
00476     }
00477     if ( bb.b[1][2] > b[1][2]) {
00478         b[1][2] = bb.b[1][2];
00479     }
00480 }
00481 
00482 ID_INLINE float Bounds::Radius( ) {
00483     int     i;
00484     float   total;
00485     float   a, aa;
00486 
00487     total = 0;
00488     for (i=0 ; i<3 ; i++) {
00489         a = (float)fabs( b[0][i] );
00490         aa = (float)fabs( b[1][i] );
00491         if ( aa > a ) {
00492             a = aa;
00493         }
00494         total += a * a;
00495     }
00496 
00497     return (float)idSqrt( total );
00498 }
00499 
00500 //===============================================================
00501 
00502 
00503 class idVec2_t {
00504 public:
00505     float           x;
00506     float           y;
00507 
00508                     operator float *();
00509     float           operator[]( int index ) const;
00510     float           &operator[]( int index );
00511 };
00512 
00513 ID_INLINE float idVec2_t::operator[]( int index ) const {
00514     return ( &x )[ index ];
00515 }
00516 
00517 ID_INLINE float& idVec2_t::operator[]( int index ) {
00518     return ( &x )[ index ];
00519 }
00520 
00521 ID_INLINE idVec2_t::operator float *( void ) {
00522     return &x;
00523 }
00524 
00525 class vec4_t : public idVec3_t {
00526 public:
00527 #ifndef FAT_VEC3
00528     float           dist;
00529 #endif
00530     vec4_t();
00531     ~vec4_t() {};
00532     
00533     vec4_t( float x, float y, float z, float dist );
00534     float           operator[]( int index ) const;
00535     float           &operator[]( int index );
00536 };
00537 
00538 ID_INLINE vec4_t::vec4_t() {}
00539 ID_INLINE vec4_t::vec4_t( float x, float y, float z, float dist ) {
00540     this->x = x;
00541     this->y = y;
00542     this->z = z;
00543     this->dist = dist;
00544 }
00545 
00546 ID_INLINE float vec4_t::operator[]( int index ) const {
00547     return ( &x )[ index ];
00548 }
00549 
00550 ID_INLINE float& vec4_t::operator[]( int index ) {
00551     return ( &x )[ index ];
00552 }
00553 
00554 
00555 class idVec5_t : public idVec3_t {
00556 public:
00557     float           s;
00558     float           t;
00559     float           operator[]( int index ) const;
00560     float           &operator[]( int index );
00561 };
00562 
00563 
00564 ID_INLINE float idVec5_t::operator[]( int index ) const {
00565     return ( &x )[ index ];
00566 }
00567 
00568 ID_INLINE float& idVec5_t::operator[]( int index ) {
00569     return ( &x )[ index ];
00570 }
00571 
00572 #endif /* !__MATH_VECTOR_H__ */

Generated on Thu Aug 25 12:37:58 2005 for Quake III Arena by  doxygen 1.3.9.1