]> git.xonotic.org Git - xonotic/netradiant.git/blob - libs/splines/math_vector.h
various: add explicit default contructors
[xonotic/netradiant.git] / libs / splines / math_vector.h
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
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.
11
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.
16
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
20  */
21
22 #ifndef __MATH_VECTOR_H__
23 #define __MATH_VECTOR_H__
24
25 #include "globaldefs.h"
26
27 #if GDEF_COMPILER_MSVC
28 #pragma warning(disable : 4244)
29 #endif
30
31 #include <math.h>
32 #include <assert.h>
33
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])
39
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])
43
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 ) )
50
51
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] )
56
57 #define SnapVector( v ) {v[0] = (int)v[0]; v[1] = (int)v[1]; v[2] = (int)v[2]; }
58
59
60 //#include "util_heap.h"
61
62 #ifndef EQUAL_EPSILON
63 #define EQUAL_EPSILON   0.001
64 #endif
65
66 float Q_fabs( float f );
67
68 #ifndef ID_INLINE
69 #define ID_INLINE GDEF_ATTRIBUTE_INLINE
70 #endif
71
72 // if this is defined, vec3 will take four elements, which may allow
73 // easier SIMD optimizations
74 //#define       FAT_VEC3
75 //#ifdef __ppc__
76 //#pragma align(16)
77 //#endif
78
79 class angles_t;
80 #ifdef __ppc__
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).
87
88 static inline float idSqrt( float x ) {
89         const float half = 0.5;
90         const float one = 1.0;
91         float B, y0, y1;
92
93         // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
94         if ( fabs( x ) == 0.0 ) {
95                 return x;
96         }
97         B = x;
98
99 #if GDEF_COMPILER_GNU
100         asm ( "frsqrte %0,%1" : "=f" ( y0 ) : "f" ( B ) );
101 #else
102         y0 = __frsqrte( B );
103 #endif
104         /* First refinement step */
105
106         y1 = y0 + half * y0 * ( one - B * y0 * y0 );
107
108         /* Second refinement step -- copy the output of the last step to the input of this step */
109
110         y0 = y1;
111         y1 = y0 + half * y0 * ( one - B * y0 * y0 );
112
113         /* Get sqrt(x) from x * 1/sqrt(x) */
114         return x * y1;
115 }
116 #else
117 static inline double idSqrt( double x ) {
118         return sqrt( x );
119 }
120 #endif
121
122
123 //class idVec3  : public idHeap<idVec3> {
124 class idVec3 {
125 public:
126 #ifndef FAT_VEC3
127         float x,y,z;
128 #else
129         float x,y,z,dist;
130 #endif
131
132 #ifndef FAT_VEC3
133         idVec3() {};
134 #else
135         idVec3() {dist = 0.0f; };
136 #endif
137         idVec3( const float x, const float y, const float z );
138         idVec3( const idVec3& ) = default;
139
140         operator float *();
141
142         float operator[]( const int index ) const;
143         float &operator[]( const int index );
144
145         void set( const float x, const float y, const float z );
146
147         idVec3 operator-() const;
148
149         idVec3 &operator=( const idVec3 &a ) = default;
150
151         float operator*( const idVec3 &a ) const;
152         idVec3 operator*( const float a ) const;
153         friend idVec3 operator*( float a, idVec3 b );
154
155         idVec3 operator+( const idVec3 &a ) const;
156         idVec3 operator-( const idVec3 &a ) const;
157
158         idVec3 &operator+=( const idVec3 &a );
159         idVec3 &operator-=( const idVec3 &a );
160         idVec3 &operator*=( const float a );
161
162         int operator==( const idVec3 &a ) const;
163         int operator!=( const idVec3 &a ) const;
164
165         idVec3          Cross( const idVec3 &a ) const;
166         idVec3          &Cross( const idVec3 &a, const idVec3 &b );
167
168         float           Length( void ) const;
169         float           Normalize( void );
170
171         void            Zero( void );
172         void            Snap( void );
173         void            SnapTowards( const idVec3 &to );
174
175         float           toYaw( void );
176         float           toPitch( void );
177         angles_t        toAngles( void );
178         friend idVec3   LerpVector( const idVec3 &w1, const idVec3 &w2, const float t );
179
180         char            *string( void );
181 };
182
183 extern idVec3 vec_zero;
184
185 ID_INLINE idVec3::idVec3( const float x, const float y, const float z ) {
186         this->x = x;
187         this->y = y;
188         this->z = z;
189 #ifdef  FAT_VEC3
190         this->dist = 0.0f;
191 #endif
192 }
193
194 ID_INLINE float idVec3::operator[]( const int index ) const {
195         return ( &x )[ index ];
196 }
197
198 ID_INLINE float &idVec3::operator[]( const int index ) {
199         return ( &x )[ index ];
200 }
201
202 ID_INLINE idVec3::operator float *( void ) {
203         return &x;
204 }
205
206 ID_INLINE idVec3 idVec3::operator-() const {
207         return idVec3( -x, -y, -z );
208 }
209
210 ID_INLINE void idVec3::set( const float x, const float y, const float z ) {
211         this->x = x;
212         this->y = y;
213         this->z = z;
214 }
215
216 ID_INLINE idVec3 idVec3::operator-( const idVec3 &a ) const {
217         return idVec3( x - a.x, y - a.y, z - a.z );
218 }
219
220 ID_INLINE float idVec3::operator*( const idVec3 &a ) const {
221         return x * a.x + y * a.y + z * a.z;
222 }
223
224 ID_INLINE idVec3 idVec3::operator*( const float a ) const {
225         return idVec3( x * a, y * a, z * a );
226 }
227
228 ID_INLINE idVec3 operator*( const float a, const idVec3 b ) {
229         return idVec3( b.x * a, b.y * a, b.z * a );
230 }
231
232 ID_INLINE idVec3 idVec3::operator+( const idVec3 &a ) const {
233         return idVec3( x + a.x, y + a.y, z + a.z );
234 }
235
236 ID_INLINE idVec3 &idVec3::operator+=( const idVec3 &a ) {
237         x += a.x;
238         y += a.y;
239         z += a.z;
240
241         return *this;
242 }
243
244 ID_INLINE idVec3 &idVec3::operator-=( const idVec3 &a ) {
245         x -= a.x;
246         y -= a.y;
247         z -= a.z;
248
249         return *this;
250 }
251
252 ID_INLINE idVec3 &idVec3::operator*=( const float a ) {
253         x *= a;
254         y *= a;
255         z *= a;
256
257         return *this;
258 }
259
260 ID_INLINE int idVec3::operator==( const idVec3 &a ) const {
261         if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
262                 return false;
263         }
264
265         if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
266                 return false;
267         }
268
269         if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
270                 return false;
271         }
272
273         return true;
274 }
275
276 ID_INLINE int idVec3::operator!=( const idVec3 &a ) const {
277         if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
278                 return true;
279         }
280
281         if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
282                 return true;
283         }
284
285         if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
286                 return true;
287         }
288
289         return false;
290 }
291
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 );
294 }
295
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;
300
301         return *this;
302 }
303
304 ID_INLINE float idVec3::Length( void ) const {
305         float length;
306
307         length = x * x + y * y + z * z;
308         return ( float )idSqrt( length );
309 }
310
311 ID_INLINE float idVec3::Normalize( void ) {
312         float length;
313         float ilength;
314
315         length = this->Length();
316         if ( length ) {
317                 ilength = 1.0f / length;
318                 x *= ilength;
319                 y *= ilength;
320                 z *= ilength;
321         }
322
323         return length;
324 }
325
326 ID_INLINE void idVec3::Zero( void ) {
327         x = 0.0f;
328         y = 0.0f;
329         z = 0.0f;
330 }
331
332 ID_INLINE void idVec3::Snap( void ) {
333         x = float( int( x ) );
334         y = float( int( y ) );
335         z = float( int( z ) );
336 }
337
338 /*
339    ======================
340    SnapTowards
341
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
345    into a wall.
346    ======================
347  */
348 ID_INLINE void idVec3::SnapTowards( const idVec3 &to ) {
349         if ( to.x <= x ) {
350                 x = float( int( x ) );
351         }
352         else {
353                 x = float( int( x ) + 1 );
354         }
355
356         if ( to.y <= y ) {
357                 y = float( int( y ) );
358         }
359         else {
360                 y = float( int( y ) + 1 );
361         }
362
363         if ( to.z <= z ) {
364                 z = float( int( z ) );
365         }
366         else {
367                 z = float( int( z ) + 1 );
368         }
369 }
370
371 //===============================================================
372
373 class Bounds {
374 public:
375 idVec3 b[2];
376
377 Bounds();
378 Bounds( const idVec3 &mins, const idVec3 &maxs );
379
380 void    Clear();
381 void    Zero();
382 float   Radius();           // radius from origin, not from center
383 idVec3  Center();
384 void    AddPoint( const idVec3 &v );
385 void    AddBounds( const Bounds &bb );
386 bool    IsCleared();
387 bool    ContainsPoint( const idVec3 &p );
388 bool    IntersectsBounds( const Bounds &b2 );       // touching is NOT intersecting
389 };
390
391 extern Bounds boundsZero;
392
393 ID_INLINE Bounds::Bounds(){
394 }
395
396 ID_INLINE bool Bounds::IsCleared() {
397         return b[0][0] > b[1][0];
398 }
399
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] ) {
403                 return false;
404         }
405         return true;
406 }
407
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] ) {
411                 return false;
412         }
413         return true;
414 }
415
416 ID_INLINE Bounds::Bounds( const idVec3 &mins, const idVec3 &maxs ) {
417         b[0] = mins;
418         b[1] = maxs;
419 }
420
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 );
423 }
424
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;
428 }
429
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;
433 }
434
435 ID_INLINE void Bounds::AddPoint( const idVec3 &v ) {
436         if ( v[0] < b[0][0] ) {
437                 b[0][0] = v[0];
438         }
439         if ( v[0] > b[1][0] ) {
440                 b[1][0] = v[0];
441         }
442         if ( v[1] < b[0][1] ) {
443                 b[0][1] = v[1];
444         }
445         if ( v[1] > b[1][1] ) {
446                 b[1][1] = v[1];
447         }
448         if ( v[2] < b[0][2] ) {
449                 b[0][2] = v[2];
450         }
451         if ( v[2] > b[1][2] ) {
452                 b[1][2] = v[2];
453         }
454 }
455
456
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];
460         }
461         if ( bb.b[0][1] < b[0][1] ) {
462                 b[0][1] = bb.b[0][1];
463         }
464         if ( bb.b[0][2] < b[0][2] ) {
465                 b[0][2] = bb.b[0][2];
466         }
467
468         if ( bb.b[1][0] > b[1][0] ) {
469                 b[1][0] = bb.b[1][0];
470         }
471         if ( bb.b[1][1] > b[1][1] ) {
472                 b[1][1] = bb.b[1][1];
473         }
474         if ( bb.b[1][2] > b[1][2] ) {
475                 b[1][2] = bb.b[1][2];
476         }
477 }
478
479 ID_INLINE float Bounds::Radius() {
480         int i;
481         float total;
482         float a, aa;
483
484         total = 0;
485         for ( i = 0 ; i < 3 ; i++ ) {
486                 a = (float)fabs( b[0][i] );
487                 aa = (float)fabs( b[1][i] );
488                 if ( aa > a ) {
489                         a = aa;
490                 }
491                 total += a * a;
492         }
493
494         return (float)idSqrt( total );
495 }
496
497 //===============================================================
498
499
500 class idVec2 {
501 public:
502 float x;
503 float y;
504
505 operator float *();
506 float operator[]( int index ) const;
507 float           &operator[]( int index );
508 };
509
510 ID_INLINE float idVec2::operator[]( int index ) const {
511         return ( &x )[ index ];
512 }
513
514 ID_INLINE float& idVec2::operator[]( int index ) {
515         return ( &x )[ index ];
516 }
517
518 ID_INLINE idVec2::operator float *( void ) {
519         return &x;
520 }
521
522 class idVec4 : public idVec3 {
523 public:
524 #ifndef FAT_VEC3
525 float dist;
526 #endif
527 idVec4();
528 ~idVec4() {};
529
530 idVec4( float x, float y, float z, float dist );
531 float operator[]( int index ) const;
532 float           &operator[]( int index );
533 };
534
535 ID_INLINE idVec4::idVec4() {}
536 ID_INLINE idVec4::idVec4( float x, float y, float z, float dist ) {
537         this->x = x;
538         this->y = y;
539         this->z = z;
540         this->dist = dist;
541 }
542
543 ID_INLINE float idVec4::operator[]( int index ) const {
544         return ( &x )[ index ];
545 }
546
547 ID_INLINE float& idVec4::operator[]( int index ) {
548         return ( &x )[ index ];
549 }
550
551
552 class idVec5_t : public idVec3 {
553 public:
554 float s;
555 float t;
556 float operator[]( int index ) const;
557 float           &operator[]( int index );
558 };
559
560
561 ID_INLINE float idVec5_t::operator[]( int index ) const {
562         return ( &x )[ index ];
563 }
564
565 ID_INLINE float& idVec5_t::operator[]( int index ) {
566         return ( &x )[ index ];
567 }
568
569 #endif /* !__MATH_VECTOR_H__ */