--- /dev/null
+/*\r
+Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
+For a list of contributors, see the accompanying CONTRIBUTORS file.\r
+\r
+This file is part of GtkRadiant.\r
+\r
+GtkRadiant is free software; you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2 of the License, or\r
+(at your option) any later version.\r
+\r
+GtkRadiant is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with GtkRadiant; if not, write to the Free Software\r
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
+*/\r
+\r
+#ifndef __MATH_VECTOR_H__\r
+#define __MATH_VECTOR_H__\r
+\r
+#ifdef _WIN32\r
+#pragma warning(disable : 4244)\r
+#endif\r
+\r
+#include <math.h>\r
+#include <assert.h>\r
+\r
+//#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])\r
+//#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])\r
+//#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])\r
+//#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])\r
+//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])\r
+\r
+//#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))\r
+#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))\r
+//#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])\r
+\r
+#define DotProduct4(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])\r
+#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])\r
+#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])\r
+#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])\r
+#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))\r
+#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))\r
+\r
+\r
+//#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)\r
+#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])\r
+//#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))\r
+#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])\r
+\r
+#define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}\r
+\r
+\r
+//#include "util_heap.h"\r
+\r
+#ifndef EQUAL_EPSILON\r
+#define EQUAL_EPSILON 0.001\r
+#endif\r
+\r
+float Q_fabs( float f );\r
+\r
+#ifndef ID_INLINE\r
+#ifdef _WIN32\r
+#define ID_INLINE __inline \r
+#else\r
+#define ID_INLINE inline\r
+#endif\r
+#endif\r
+\r
+// if this is defined, vec3 will take four elements, which may allow\r
+// easier SIMD optimizations\r
+//#define FAT_VEC3\r
+//#ifdef __ppc__\r
+//#pragma align(16)\r
+//#endif\r
+\r
+class angles_t;\r
+#ifdef __ppc__\r
+// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, \r
+// runs *much* faster than calling sqrt(). We'll use two Newton-Raphson \r
+// refinement steps to get bunch more precision in the 1/sqrt() value for very little cost. \r
+// We'll then multiply 1/sqrt times the original value to get the sqrt. \r
+// This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive) \r
+// it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments). \r
+\r
+static inline float idSqrt(float x) {\r
+ const float half = 0.5;\r
+ const float one = 1.0;\r
+ float B, y0, y1;\r
+\r
+ // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0\r
+ if (fabs(x) == 0.0)\r
+ return x;\r
+ B = x;\r
+ \r
+#ifdef __GNUC__\r
+ asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));\r
+#else\r
+ y0 = __frsqrte(B);\r
+#endif\r
+ /* First refinement step */\r
+ \r
+ y1 = y0 + half*y0*(one - B*y0*y0);\r
+ \r
+ /* Second refinement step -- copy the output of the last step to the input of this step */\r
+ \r
+ y0 = y1;\r
+ y1 = y0 + half*y0*(one - B*y0*y0);\r
+ \r
+ /* Get sqrt(x) from x * 1/sqrt(x) */\r
+ return x * y1;\r
+}\r
+#else\r
+static inline double idSqrt(double x) {\r
+ return sqrt(x);\r
+}\r
+#endif\r
+\r
+\r
+//class idVec3 : public idHeap<idVec3> {\r
+class idVec3 {\r
+public: \r
+#ifndef FAT_VEC3\r
+ float x,y,z;\r
+#else\r
+ float x,y,z,dist;\r
+#endif\r
+\r
+#ifndef FAT_VEC3\r
+ idVec3() {};\r
+#else\r
+ idVec3() {dist = 0.0f;};\r
+#endif\r
+ idVec3( const float x, const float y, const float z );\r
+\r
+ operator float *();\r
+\r
+ float operator[]( const int index ) const;\r
+ float &operator[]( const int index );\r
+\r
+ void set( const float x, const float y, const float z );\r
+\r
+ idVec3 operator-() const;\r
+\r
+ idVec3 &operator=( const idVec3 &a );\r
+\r
+ float operator*( const idVec3 &a ) const;\r
+ idVec3 operator*( const float a ) const;\r
+ friend idVec3 operator*( float a, idVec3 b );\r
+\r
+ idVec3 operator+( const idVec3 &a ) const;\r
+ idVec3 operator-( const idVec3 &a ) const;\r
+ \r
+ idVec3 &operator+=( const idVec3 &a );\r
+ idVec3 &operator-=( const idVec3 &a );\r
+ idVec3 &operator*=( const float a );\r
+\r
+ int operator==( const idVec3 &a ) const;\r
+ int operator!=( const idVec3 &a ) const;\r
+\r
+ idVec3 Cross( const idVec3 &a ) const;\r
+ idVec3 &Cross( const idVec3 &a, const idVec3 &b );\r
+\r
+ float Length( void ) const;\r
+ float Normalize( void );\r
+\r
+ void Zero( void );\r
+ void Snap( void );\r
+ void SnapTowards( const idVec3 &to );\r
+\r
+ float toYaw( void );\r
+ float toPitch( void );\r
+ angles_t toAngles( void );\r
+ friend idVec3 LerpVector( const idVec3 &w1, const idVec3 &w2, const float t );\r
+\r
+ char *string( void );\r
+};\r
+\r
+extern idVec3 vec_zero;\r
+\r
+ID_INLINE idVec3::idVec3( const float x, const float y, const float z ) {\r
+ this->x = x;\r
+ this->y = y;\r
+ this->z = z;\r
+#ifdef FAT_VEC3\r
+ this->dist = 0.0f;\r
+#endif\r
+}\r
+\r
+ID_INLINE float idVec3::operator[]( const int index ) const {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+ID_INLINE float &idVec3::operator[]( const int index ) {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+ID_INLINE idVec3::operator float *( void ) {\r
+ return &x;\r
+}\r
+\r
+ID_INLINE idVec3 idVec3::operator-() const {\r
+ return idVec3( -x, -y, -z );\r
+}\r
+ \r
+ID_INLINE idVec3 &idVec3::operator=( const idVec3 &a ) { \r
+ x = a.x;\r
+ y = a.y;\r
+ z = a.z;\r
+ \r
+ return *this;\r
+}\r
+\r
+ID_INLINE void idVec3::set( const float x, const float y, const float z ) {\r
+ this->x = x;\r
+ this->y = y;\r
+ this->z = z;\r
+}\r
+\r
+ID_INLINE idVec3 idVec3::operator-( const idVec3 &a ) const {\r
+ return idVec3( x - a.x, y - a.y, z - a.z );\r
+}\r
+\r
+ID_INLINE float idVec3::operator*( const idVec3 &a ) const {\r
+ return x * a.x + y * a.y + z * a.z;\r
+}\r
+\r
+ID_INLINE idVec3 idVec3::operator*( const float a ) const {\r
+ return idVec3( x * a, y * a, z * a );\r
+}\r
+\r
+ID_INLINE idVec3 operator*( const float a, const idVec3 b ) {\r
+ return idVec3( b.x * a, b.y * a, b.z * a );\r
+}\r
+\r
+ID_INLINE idVec3 idVec3::operator+( const idVec3 &a ) const {\r
+ return idVec3( x + a.x, y + a.y, z + a.z );\r
+}\r
+\r
+ID_INLINE idVec3 &idVec3::operator+=( const idVec3 &a ) {\r
+ x += a.x;\r
+ y += a.y;\r
+ z += a.z;\r
+\r
+ return *this;\r
+}\r
+\r
+ID_INLINE idVec3 &idVec3::operator-=( const idVec3 &a ) {\r
+ x -= a.x;\r
+ y -= a.y;\r
+ z -= a.z;\r
+\r
+ return *this;\r
+}\r
+\r
+ID_INLINE idVec3 &idVec3::operator*=( const float a ) {\r
+ x *= a;\r
+ y *= a;\r
+ z *= a;\r
+\r
+ return *this;\r
+}\r
+\r
+ID_INLINE int idVec3::operator==( const idVec3 &a ) const {\r
+ if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {\r
+ return false;\r
+ }\r
+ \r
+ if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {\r
+ return false;\r
+ }\r
+\r
+ if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+}\r
+\r
+ID_INLINE int idVec3::operator!=( const idVec3 &a ) const {\r
+ if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {\r
+ return true;\r
+ }\r
+ \r
+ if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {\r
+ return true;\r
+ }\r
+\r
+ if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+}\r
+\r
+ID_INLINE idVec3 idVec3::Cross( const idVec3 &a ) const {\r
+ return idVec3( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );\r
+}\r
+\r
+ID_INLINE idVec3 &idVec3::Cross( const idVec3 &a, const idVec3 &b ) {\r
+ x = a.y * b.z - a.z * b.y;\r
+ y = a.z * b.x - a.x * b.z;\r
+ z = a.x * b.y - a.y * b.x;\r
+\r
+ return *this;\r
+}\r
+\r
+ID_INLINE float idVec3::Length( void ) const {\r
+ float length;\r
+ \r
+ length = x * x + y * y + z * z;\r
+ return ( float )idSqrt( length );\r
+}\r
+\r
+ID_INLINE float idVec3::Normalize( void ) {\r
+ float length;\r
+ float ilength;\r
+\r
+ length = this->Length();\r
+ if ( length ) {\r
+ ilength = 1.0f / length;\r
+ x *= ilength;\r
+ y *= ilength;\r
+ z *= ilength;\r
+ }\r
+ \r
+ return length;\r
+}\r
+\r
+ID_INLINE void idVec3::Zero( void ) {\r
+ x = 0.0f;\r
+ y = 0.0f;\r
+ z = 0.0f;\r
+}\r
+\r
+ID_INLINE void idVec3::Snap( void ) {\r
+ x = float( int( x ) );\r
+ y = float( int( y ) );\r
+ z = float( int( z ) );\r
+}\r
+\r
+/*\r
+======================\r
+SnapTowards\r
+\r
+Round a vector to integers for more efficient network\r
+transmission, but make sure that it rounds towards a given point\r
+rather than blindly truncating. This prevents it from truncating \r
+into a wall.\r
+======================\r
+*/\r
+ID_INLINE void idVec3::SnapTowards( const idVec3 &to ) {\r
+ if ( to.x <= x ) {\r
+ x = float( int( x ) );\r
+ } else {\r
+ x = float( int( x ) + 1 );\r
+ }\r
+\r
+ if ( to.y <= y ) {\r
+ y = float( int( y ) );\r
+ } else {\r
+ y = float( int( y ) + 1 );\r
+ }\r
+\r
+ if ( to.z <= z ) {\r
+ z = float( int( z ) );\r
+ } else {\r
+ z = float( int( z ) + 1 );\r
+ }\r
+}\r
+\r
+//===============================================================\r
+\r
+class Bounds {\r
+public:\r
+ idVec3 b[2];\r
+\r
+ Bounds();\r
+ Bounds( const idVec3 &mins, const idVec3 &maxs );\r
+\r
+ void Clear();\r
+ void Zero();\r
+ float Radius(); // radius from origin, not from center\r
+ idVec3 Center();\r
+ void AddPoint( const idVec3 &v );\r
+ void AddBounds( const Bounds &bb );\r
+ bool IsCleared();\r
+ bool ContainsPoint( const idVec3 &p );\r
+ bool IntersectsBounds( const Bounds &b2 ); // touching is NOT intersecting\r
+};\r
+\r
+extern Bounds boundsZero;\r
+\r
+ID_INLINE Bounds::Bounds(){\r
+}\r
+\r
+ID_INLINE bool Bounds::IsCleared() {\r
+ return b[0][0] > b[1][0];\r
+}\r
+\r
+ID_INLINE bool Bounds::ContainsPoint( const idVec3 &p ) {\r
+ if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]\r
+ || p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {\r
+ return false;\r
+ }\r
+ return true;\r
+}\r
+\r
+ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {\r
+ if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]\r
+ || b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {\r
+ return false;\r
+ }\r
+ return true;\r
+}\r
+\r
+ID_INLINE Bounds::Bounds( const idVec3 &mins, const idVec3 &maxs ) {\r
+ b[0] = mins;\r
+ b[1] = maxs;\r
+}\r
+\r
+ID_INLINE idVec3 Bounds::Center() {\r
+ 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 );\r
+}\r
+\r
+ID_INLINE void Bounds::Clear() {\r
+ b[0][0] = b[0][1] = b[0][2] = 99999;\r
+ b[1][0] = b[1][1] = b[1][2] = -99999;\r
+}\r
+\r
+ID_INLINE void Bounds::Zero() {\r
+ b[0][0] = b[0][1] = b[0][2] =\r
+ b[1][0] = b[1][1] = b[1][2] = 0;\r
+}\r
+\r
+ID_INLINE void Bounds::AddPoint( const idVec3 &v ) {\r
+ if ( v[0] < b[0][0]) {\r
+ b[0][0] = v[0];\r
+ }\r
+ if ( v[0] > b[1][0]) {\r
+ b[1][0] = v[0];\r
+ }\r
+ if ( v[1] < b[0][1] ) {\r
+ b[0][1] = v[1];\r
+ }\r
+ if ( v[1] > b[1][1]) {\r
+ b[1][1] = v[1];\r
+ }\r
+ if ( v[2] < b[0][2] ) {\r
+ b[0][2] = v[2];\r
+ }\r
+ if ( v[2] > b[1][2]) {\r
+ b[1][2] = v[2];\r
+ }\r
+}\r
+\r
+\r
+ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {\r
+ if ( bb.b[0][0] < b[0][0]) {\r
+ b[0][0] = bb.b[0][0];\r
+ }\r
+ if ( bb.b[0][1] < b[0][1]) {\r
+ b[0][1] = bb.b[0][1];\r
+ }\r
+ if ( bb.b[0][2] < b[0][2]) {\r
+ b[0][2] = bb.b[0][2];\r
+ }\r
+\r
+ if ( bb.b[1][0] > b[1][0]) {\r
+ b[1][0] = bb.b[1][0];\r
+ }\r
+ if ( bb.b[1][1] > b[1][1]) {\r
+ b[1][1] = bb.b[1][1];\r
+ }\r
+ if ( bb.b[1][2] > b[1][2]) {\r
+ b[1][2] = bb.b[1][2];\r
+ }\r
+}\r
+\r
+ID_INLINE float Bounds::Radius( ) {\r
+ int i;\r
+ float total;\r
+ float a, aa;\r
+\r
+ total = 0;\r
+ for (i=0 ; i<3 ; i++) {\r
+ a = (float)fabs( b[0][i] );\r
+ aa = (float)fabs( b[1][i] );\r
+ if ( aa > a ) {\r
+ a = aa;\r
+ }\r
+ total += a * a;\r
+ }\r
+\r
+ return (float)idSqrt( total );\r
+}\r
+\r
+//===============================================================\r
+\r
+\r
+class idVec2 {\r
+public:\r
+ float x;\r
+ float y;\r
+\r
+ operator float *();\r
+ float operator[]( int index ) const;\r
+ float &operator[]( int index );\r
+};\r
+\r
+ID_INLINE float idVec2::operator[]( int index ) const {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+ID_INLINE float& idVec2::operator[]( int index ) {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+ID_INLINE idVec2::operator float *( void ) {\r
+ return &x;\r
+}\r
+\r
+class idVec4 : public idVec3 {\r
+public:\r
+#ifndef FAT_VEC3\r
+ float dist;\r
+#endif\r
+ idVec4();\r
+ ~idVec4() {};\r
+ \r
+ idVec4( float x, float y, float z, float dist );\r
+ float operator[]( int index ) const;\r
+ float &operator[]( int index );\r
+};\r
+\r
+ID_INLINE idVec4::idVec4() {}\r
+ID_INLINE idVec4::idVec4( float x, float y, float z, float dist ) {\r
+ this->x = x;\r
+ this->y = y;\r
+ this->z = z;\r
+ this->dist = dist;\r
+}\r
+\r
+ID_INLINE float idVec4::operator[]( int index ) const {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+ID_INLINE float& idVec4::operator[]( int index ) {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+\r
+class idVec5_t : public idVec3 {\r
+public:\r
+ float s;\r
+ float t;\r
+ float operator[]( int index ) const;\r
+ float &operator[]( int index );\r
+};\r
+\r
+\r
+ID_INLINE float idVec5_t::operator[]( int index ) const {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+ID_INLINE float& idVec5_t::operator[]( int index ) {\r
+ return ( &x )[ index ];\r
+}\r
+\r
+#endif /* !__MATH_VECTOR_H__ */\r