2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #ifndef __MATH_VECTOR_H__
23 #define __MATH_VECTOR_H__
25 #include "globaldefs.h"
27 #if GDEF_COMPILER_MSVC
28 #pragma warning(disable : 4244)
34 //#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
35 //#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
36 //#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
37 //#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
38 //#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
40 //#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
41 #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 ) )
42 //#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])
44 #define DotProduct4( x,y ) ( ( x )[0] * ( y )[0] + ( x )[1] * ( y )[1] + ( x )[2] * ( y )[2] + ( x )[3] * ( y )[3] )
45 #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] )
46 #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] )
47 #define VectorCopy4( a,b ) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2],( b )[3] = ( a )[3] )
48 #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 ) )
49 #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 ) )
52 //#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
53 #define VectorNegate( a,b ) ( ( b )[0] = -( a )[0],( b )[1] = -( a )[1],( b )[2] = -( a )[2] )
54 //#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
55 #define Vector4Copy( a,b ) ( ( b )[0] = ( a )[0],( b )[1] = ( a )[1],( b )[2] = ( a )[2],( b )[3] = ( a )[3] )
57 #define SnapVector( v ) {v[0] = (int)v[0]; v[1] = (int)v[1]; v[2] = (int)v[2]; }
60 //#include "util_heap.h"
63 #define EQUAL_EPSILON 0.001
66 float Q_fabs( float f );
69 #define ID_INLINE GDEF_ATTRIBUTE_INLINE
72 // if this is defined, vec3 will take four elements, which may allow
73 // easier SIMD optimizations
81 // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
82 // runs *much* faster than calling sqrt(). We'll use two Newton-Raphson
83 // refinement steps to get bunch more precision in the 1/sqrt() value for very little cost.
84 // We'll then multiply 1/sqrt times the original value to get the sqrt.
85 // This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive)
86 // it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments).
88 static inline float idSqrt( float x ) {
89 const float half = 0.5;
90 const float one = 1.0;
93 // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
94 if ( fabs( x ) == 0.0 ) {
100 asm ( "frsqrte %0,%1" : "=f" ( y0 ) : "f" ( B ) );
104 /* First refinement step */
106 y1 = y0 + half * y0 * ( one - B * y0 * y0 );
108 /* Second refinement step -- copy the output of the last step to the input of this step */
111 y1 = y0 + half * y0 * ( one - B * y0 * y0 );
113 /* Get sqrt(x) from x * 1/sqrt(x) */
117 static inline double idSqrt( double x ) {
123 //class idVec3 : public idHeap<idVec3> {
135 idVec3() {dist = 0.0f; };
137 idVec3( const float x, const float y, const float z );
138 idVec3( const idVec3& ) = default;
142 float operator[]( const int index ) const;
143 float &operator[]( const int index );
145 void set( const float x, const float y, const float z );
147 idVec3 operator-() const;
149 idVec3 &operator=( const idVec3 &a ) = default;
151 float operator*( const idVec3 &a ) const;
152 idVec3 operator*( const float a ) const;
153 friend idVec3 operator*( float a, idVec3 b );
155 idVec3 operator+( const idVec3 &a ) const;
156 idVec3 operator-( const idVec3 &a ) const;
158 idVec3 &operator+=( const idVec3 &a );
159 idVec3 &operator-=( const idVec3 &a );
160 idVec3 &operator*=( const float a );
162 int operator==( const idVec3 &a ) const;
163 int operator!=( const idVec3 &a ) const;
165 idVec3 Cross( const idVec3 &a ) const;
166 idVec3 &Cross( const idVec3 &a, const idVec3 &b );
168 float Length( void ) const;
169 float Normalize( void );
173 void SnapTowards( const idVec3 &to );
176 float toPitch( void );
177 angles_t toAngles( void );
178 friend idVec3 LerpVector( const idVec3 &w1, const idVec3 &w2, const float t );
180 char *string( void );
183 extern idVec3 vec_zero;
185 ID_INLINE idVec3::idVec3( const float x, const float y, const float z ) {
194 ID_INLINE float idVec3::operator[]( const int index ) const {
195 return ( &x )[ index ];
198 ID_INLINE float &idVec3::operator[]( const int index ) {
199 return ( &x )[ index ];
202 ID_INLINE idVec3::operator float *( void ) {
206 ID_INLINE idVec3 idVec3::operator-() const {
207 return idVec3( -x, -y, -z );
210 ID_INLINE void idVec3::set( const float x, const float y, const float z ) {
216 ID_INLINE idVec3 idVec3::operator-( const idVec3 &a ) const {
217 return idVec3( x - a.x, y - a.y, z - a.z );
220 ID_INLINE float idVec3::operator*( const idVec3 &a ) const {
221 return x * a.x + y * a.y + z * a.z;
224 ID_INLINE idVec3 idVec3::operator*( const float a ) const {
225 return idVec3( x * a, y * a, z * a );
228 ID_INLINE idVec3 operator*( const float a, const idVec3 b ) {
229 return idVec3( b.x * a, b.y * a, b.z * a );
232 ID_INLINE idVec3 idVec3::operator+( const idVec3 &a ) const {
233 return idVec3( x + a.x, y + a.y, z + a.z );
236 ID_INLINE idVec3 &idVec3::operator+=( const idVec3 &a ) {
244 ID_INLINE idVec3 &idVec3::operator-=( const idVec3 &a ) {
252 ID_INLINE idVec3 &idVec3::operator*=( const float a ) {
260 ID_INLINE int idVec3::operator==( const idVec3 &a ) const {
261 if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
265 if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
269 if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
276 ID_INLINE int idVec3::operator!=( const idVec3 &a ) const {
277 if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
281 if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
285 if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
292 ID_INLINE idVec3 idVec3::Cross( const idVec3 &a ) const {
293 return idVec3( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
296 ID_INLINE idVec3 &idVec3::Cross( const idVec3 &a, const idVec3 &b ) {
297 x = a.y * b.z - a.z * b.y;
298 y = a.z * b.x - a.x * b.z;
299 z = a.x * b.y - a.y * b.x;
304 ID_INLINE float idVec3::Length( void ) const {
307 length = x * x + y * y + z * z;
308 return ( float )idSqrt( length );
311 ID_INLINE float idVec3::Normalize( void ) {
315 length = this->Length();
317 ilength = 1.0f / length;
326 ID_INLINE void idVec3::Zero( void ) {
332 ID_INLINE void idVec3::Snap( void ) {
333 x = float( int( x ) );
334 y = float( int( y ) );
335 z = float( int( z ) );
339 ======================
342 Round a vector to integers for more efficient network
343 transmission, but make sure that it rounds towards a given point
344 rather than blindly truncating. This prevents it from truncating
346 ======================
348 ID_INLINE void idVec3::SnapTowards( const idVec3 &to ) {
350 x = float( int( x ) );
353 x = float( int( x ) + 1 );
357 y = float( int( y ) );
360 y = float( int( y ) + 1 );
364 z = float( int( z ) );
367 z = float( int( z ) + 1 );
371 //===============================================================
378 Bounds( const idVec3 &mins, const idVec3 &maxs );
382 float Radius(); // radius from origin, not from center
384 void AddPoint( const idVec3 &v );
385 void AddBounds( const Bounds &bb );
387 bool ContainsPoint( const idVec3 &p );
388 bool IntersectsBounds( const Bounds &b2 ); // touching is NOT intersecting
391 extern Bounds boundsZero;
393 ID_INLINE Bounds::Bounds(){
396 ID_INLINE bool Bounds::IsCleared() {
397 return b[0][0] > b[1][0];
400 ID_INLINE bool Bounds::ContainsPoint( const idVec3 &p ) {
401 if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
402 || p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
408 ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
409 if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
410 || b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
416 ID_INLINE Bounds::Bounds( const idVec3 &mins, const idVec3 &maxs ) {
421 ID_INLINE idVec3 Bounds::Center() {
422 return idVec3( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
425 ID_INLINE void Bounds::Clear() {
426 b[0][0] = b[0][1] = b[0][2] = 99999;
427 b[1][0] = b[1][1] = b[1][2] = -99999;
430 ID_INLINE void Bounds::Zero() {
431 b[0][0] = b[0][1] = b[0][2] =
432 b[1][0] = b[1][1] = b[1][2] = 0;
435 ID_INLINE void Bounds::AddPoint( const idVec3 &v ) {
436 if ( v[0] < b[0][0] ) {
439 if ( v[0] > b[1][0] ) {
442 if ( v[1] < b[0][1] ) {
445 if ( v[1] > b[1][1] ) {
448 if ( v[2] < b[0][2] ) {
451 if ( v[2] > b[1][2] ) {
457 ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
458 if ( bb.b[0][0] < b[0][0] ) {
459 b[0][0] = bb.b[0][0];
461 if ( bb.b[0][1] < b[0][1] ) {
462 b[0][1] = bb.b[0][1];
464 if ( bb.b[0][2] < b[0][2] ) {
465 b[0][2] = bb.b[0][2];
468 if ( bb.b[1][0] > b[1][0] ) {
469 b[1][0] = bb.b[1][0];
471 if ( bb.b[1][1] > b[1][1] ) {
472 b[1][1] = bb.b[1][1];
474 if ( bb.b[1][2] > b[1][2] ) {
475 b[1][2] = bb.b[1][2];
479 ID_INLINE float Bounds::Radius() {
485 for ( i = 0 ; i < 3 ; i++ ) {
486 a = (float)fabs( b[0][i] );
487 aa = (float)fabs( b[1][i] );
494 return (float)idSqrt( total );
497 //===============================================================
506 float operator[]( int index ) const;
507 float &operator[]( int index );
510 ID_INLINE float idVec2::operator[]( int index ) const {
511 return ( &x )[ index ];
514 ID_INLINE float& idVec2::operator[]( int index ) {
515 return ( &x )[ index ];
518 ID_INLINE idVec2::operator float *( void ) {
522 class idVec4 : public idVec3 {
530 idVec4( float x, float y, float z, float dist );
531 float operator[]( int index ) const;
532 float &operator[]( int index );
535 ID_INLINE idVec4::idVec4() {}
536 ID_INLINE idVec4::idVec4( float x, float y, float z, float dist ) {
543 ID_INLINE float idVec4::operator[]( int index ) const {
544 return ( &x )[ index ];
547 ID_INLINE float& idVec4::operator[]( int index ) {
548 return ( &x )[ index ];
552 class idVec5_t : public idVec3 {
556 float operator[]( int index ) const;
557 float &operator[]( int index );
561 ID_INLINE float idVec5_t::operator[]( int index ) const {
562 return ( &x )[ index ];
565 ID_INLINE float& idVec5_t::operator[]( int index ) {
566 return ( &x )[ index ];
569 #endif /* !__MATH_VECTOR_H__ */