math_vector.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #ifndef __MATH_VECTOR_H__
  19. #define __MATH_VECTOR_H__
  20. #pragma warning(disable : 4244)
  21. #include <math.h>
  22. #include <assert.h>
  23. //#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
  24. //#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
  25. //#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
  26. //#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
  27. //#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
  28. //#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
  29. #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))
  30. //#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])
  31. #define DotProduct4(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
  32. #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])
  33. #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])
  34. #define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
  35. #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))
  36. #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))
  37. //#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0)
  38. #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
  39. //#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
  40. #define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
  41. #define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
  42. //#include "util_heap.h"
  43. #ifndef EQUAL_EPSILON
  44. #define EQUAL_EPSILON 0.001
  45. #endif
  46. float Q_fabs( float f );
  47. #ifndef ID_INLINE
  48. #ifdef _WIN32
  49. #define ID_INLINE __inline
  50. #else
  51. #define ID_INLINE inline
  52. #endif
  53. #endif
  54. // if this is defined, vec3 will take four elements, which may allow
  55. // easier SIMD optimizations
  56. //#define FAT_VEC3
  57. //#ifdef __ppc__
  58. //#pragma align(16)
  59. //#endif
  60. class angles_t;
  61. #ifdef __ppc__
  62. // Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction,
  63. // runs *much* faster than calling sqrt(). We'll use two Newton-Raphson
  64. // refinement steps to get bunch more precision in the 1/sqrt() value for very little cost.
  65. // We'll then multiply 1/sqrt times the original value to get the sqrt.
  66. // This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive)
  67. // it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments).
  68. static inline float idSqrt(float x) {
  69. const float half = 0.5;
  70. const float one = 1.0;
  71. float B, y0, y1;
  72. // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
  73. if (fabs(x) == 0.0)
  74. return x;
  75. B = x;
  76. #ifdef __GNUC__
  77. asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
  78. #else
  79. y0 = __frsqrte(B);
  80. #endif
  81. /* First refinement step */
  82. y1 = y0 + half*y0*(one - B*y0*y0);
  83. /* Second refinement step -- copy the output of the last step to the input of this step */
  84. y0 = y1;
  85. y1 = y0 + half*y0*(one - B*y0*y0);
  86. /* Get sqrt(x) from x * 1/sqrt(x) */
  87. return x * y1;
  88. }
  89. #else
  90. static inline double idSqrt(double x) {
  91. return sqrt(x);
  92. }
  93. #endif
  94. //class idVec3_t : public idHeap<idVec3_t> {
  95. class idVec3_t {
  96. public:
  97. #ifndef FAT_VEC3
  98. float x,y,z;
  99. #else
  100. float x,y,z,dist;
  101. #endif
  102. #ifndef FAT_VEC3
  103. idVec3_t() {};
  104. #else
  105. idVec3_t() {dist = 0.0f;};
  106. #endif
  107. idVec3_t( const float x, const float y, const float z );
  108. operator float *();
  109. float operator[]( const int index ) const;
  110. float &operator[]( const int index );
  111. void set( const float x, const float y, const float z );
  112. idVec3_t operator-() const;
  113. idVec3_t &operator=( const idVec3_t &a );
  114. float operator*( const idVec3_t &a ) const;
  115. idVec3_t operator*( const float a ) const;
  116. friend idVec3_t operator*( float a, idVec3_t b );
  117. idVec3_t operator+( const idVec3_t &a ) const;
  118. idVec3_t operator-( const idVec3_t &a ) const;
  119. idVec3_t &operator+=( const idVec3_t &a );
  120. idVec3_t &operator-=( const idVec3_t &a );
  121. idVec3_t &operator*=( const float a );
  122. int operator==( const idVec3_t &a ) const;
  123. int operator!=( const idVec3_t &a ) const;
  124. idVec3_t Cross( const idVec3_t &a ) const;
  125. idVec3_t &Cross( const idVec3_t &a, const idVec3_t &b );
  126. float Length( void ) const;
  127. float Normalize( void );
  128. void Zero( void );
  129. void Snap( void );
  130. void SnapTowards( const idVec3_t &to );
  131. float toYaw( void );
  132. float toPitch( void );
  133. angles_t toAngles( void );
  134. friend idVec3_t LerpVector( const idVec3_t &w1, const idVec3_t &w2, const float t );
  135. char *string( void );
  136. };
  137. extern idVec3_t vec_zero;
  138. ID_INLINE idVec3_t::idVec3_t( const float x, const float y, const float z ) {
  139. this->x = x;
  140. this->y = y;
  141. this->z = z;
  142. #ifdef FAT_VEC3
  143. this->dist = 0.0f;
  144. #endif
  145. }
  146. ID_INLINE float idVec3_t::operator[]( const int index ) const {
  147. return ( &x )[ index ];
  148. }
  149. ID_INLINE float &idVec3_t::operator[]( const int index ) {
  150. return ( &x )[ index ];
  151. }
  152. ID_INLINE idVec3_t::operator float *( void ) {
  153. return &x;
  154. }
  155. ID_INLINE idVec3_t idVec3_t::operator-() const {
  156. return idVec3_t( -x, -y, -z );
  157. }
  158. ID_INLINE idVec3_t &idVec3_t::operator=( const idVec3_t &a ) {
  159. x = a.x;
  160. y = a.y;
  161. z = a.z;
  162. return *this;
  163. }
  164. ID_INLINE void idVec3_t::set( const float x, const float y, const float z ) {
  165. this->x = x;
  166. this->y = y;
  167. this->z = z;
  168. }
  169. ID_INLINE idVec3_t idVec3_t::operator-( const idVec3_t &a ) const {
  170. return idVec3_t( x - a.x, y - a.y, z - a.z );
  171. }
  172. ID_INLINE float idVec3_t::operator*( const idVec3_t &a ) const {
  173. return x * a.x + y * a.y + z * a.z;
  174. }
  175. ID_INLINE idVec3_t idVec3_t::operator*( const float a ) const {
  176. return idVec3_t( x * a, y * a, z * a );
  177. }
  178. ID_INLINE idVec3_t operator*( const float a, const idVec3_t b ) {
  179. return idVec3_t( b.x * a, b.y * a, b.z * a );
  180. }
  181. ID_INLINE idVec3_t idVec3_t::operator+( const idVec3_t &a ) const {
  182. return idVec3_t( x + a.x, y + a.y, z + a.z );
  183. }
  184. ID_INLINE idVec3_t &idVec3_t::operator+=( const idVec3_t &a ) {
  185. x += a.x;
  186. y += a.y;
  187. z += a.z;
  188. return *this;
  189. }
  190. ID_INLINE idVec3_t &idVec3_t::operator-=( const idVec3_t &a ) {
  191. x -= a.x;
  192. y -= a.y;
  193. z -= a.z;
  194. return *this;
  195. }
  196. ID_INLINE idVec3_t &idVec3_t::operator*=( const float a ) {
  197. x *= a;
  198. y *= a;
  199. z *= a;
  200. return *this;
  201. }
  202. ID_INLINE int idVec3_t::operator==( const idVec3_t &a ) const {
  203. if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
  204. return false;
  205. }
  206. if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
  207. return false;
  208. }
  209. if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
  210. return false;
  211. }
  212. return true;
  213. }
  214. ID_INLINE int idVec3_t::operator!=( const idVec3_t &a ) const {
  215. if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
  216. return true;
  217. }
  218. if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
  219. return true;
  220. }
  221. if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
  222. return true;
  223. }
  224. return false;
  225. }
  226. ID_INLINE idVec3_t idVec3_t::Cross( const idVec3_t &a ) const {
  227. return idVec3_t( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
  228. }
  229. ID_INLINE idVec3_t &idVec3_t::Cross( const idVec3_t &a, const idVec3_t &b ) {
  230. x = a.y * b.z - a.z * b.y;
  231. y = a.z * b.x - a.x * b.z;
  232. z = a.x * b.y - a.y * b.x;
  233. return *this;
  234. }
  235. ID_INLINE float idVec3_t::Length( void ) const {
  236. float length;
  237. length = x * x + y * y + z * z;
  238. return ( float )idSqrt( length );
  239. }
  240. ID_INLINE float idVec3_t::Normalize( void ) {
  241. float length;
  242. float ilength;
  243. length = this->Length();
  244. if ( length ) {
  245. ilength = 1.0f / length;
  246. x *= ilength;
  247. y *= ilength;
  248. z *= ilength;
  249. }
  250. return length;
  251. }
  252. ID_INLINE void idVec3_t::Zero( void ) {
  253. x = 0.0f;
  254. y = 0.0f;
  255. z = 0.0f;
  256. }
  257. ID_INLINE void idVec3_t::Snap( void ) {
  258. x = float( int( x ) );
  259. y = float( int( y ) );
  260. z = float( int( z ) );
  261. }
  262. /*
  263. ======================
  264. SnapTowards
  265. Round a vector to integers for more efficient network
  266. transmission, but make sure that it rounds towards a given point
  267. rather than blindly truncating. This prevents it from truncating
  268. into a wall.
  269. ======================
  270. */
  271. ID_INLINE void idVec3_t::SnapTowards( const idVec3_t &to ) {
  272. if ( to.x <= x ) {
  273. x = float( int( x ) );
  274. } else {
  275. x = float( int( x ) + 1 );
  276. }
  277. if ( to.y <= y ) {
  278. y = float( int( y ) );
  279. } else {
  280. y = float( int( y ) + 1 );
  281. }
  282. if ( to.z <= z ) {
  283. z = float( int( z ) );
  284. } else {
  285. z = float( int( z ) + 1 );
  286. }
  287. }
  288. //===============================================================
  289. class Bounds {
  290. public:
  291. idVec3_t b[2];
  292. Bounds();
  293. Bounds( const idVec3_t &mins, const idVec3_t &maxs );
  294. void Clear();
  295. void Zero();
  296. float Radius(); // radius from origin, not from center
  297. idVec3_t Center();
  298. void AddPoint( const idVec3_t &v );
  299. void AddBounds( const Bounds &bb );
  300. bool IsCleared();
  301. bool ContainsPoint( const idVec3_t &p );
  302. bool IntersectsBounds( const Bounds &b2 ); // touching is NOT intersecting
  303. };
  304. extern Bounds boundsZero;
  305. ID_INLINE Bounds::Bounds(){
  306. }
  307. ID_INLINE bool Bounds::IsCleared() {
  308. return b[0][0] > b[1][0];
  309. }
  310. ID_INLINE bool Bounds::ContainsPoint( const idVec3_t &p ) {
  311. if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
  312. || p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
  313. return false;
  314. }
  315. return true;
  316. }
  317. ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
  318. if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
  319. || b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
  320. return false;
  321. }
  322. return true;
  323. }
  324. ID_INLINE Bounds::Bounds( const idVec3_t &mins, const idVec3_t &maxs ) {
  325. b[0] = mins;
  326. b[1] = maxs;
  327. }
  328. ID_INLINE idVec3_t Bounds::Center() {
  329. 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 );
  330. }
  331. ID_INLINE void Bounds::Clear() {
  332. b[0][0] = b[0][1] = b[0][2] = 99999;
  333. b[1][0] = b[1][1] = b[1][2] = -99999;
  334. }
  335. ID_INLINE void Bounds::Zero() {
  336. b[0][0] = b[0][1] = b[0][2] =
  337. b[1][0] = b[1][1] = b[1][2] = 0;
  338. }
  339. ID_INLINE void Bounds::AddPoint( const idVec3_t &v ) {
  340. if ( v[0] < b[0][0]) {
  341. b[0][0] = v[0];
  342. }
  343. if ( v[0] > b[1][0]) {
  344. b[1][0] = v[0];
  345. }
  346. if ( v[1] < b[0][1] ) {
  347. b[0][1] = v[1];
  348. }
  349. if ( v[1] > b[1][1]) {
  350. b[1][1] = v[1];
  351. }
  352. if ( v[2] < b[0][2] ) {
  353. b[0][2] = v[2];
  354. }
  355. if ( v[2] > b[1][2]) {
  356. b[1][2] = v[2];
  357. }
  358. }
  359. ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
  360. if ( bb.b[0][0] < b[0][0]) {
  361. b[0][0] = bb.b[0][0];
  362. }
  363. if ( bb.b[0][1] < b[0][1]) {
  364. b[0][1] = bb.b[0][1];
  365. }
  366. if ( bb.b[0][2] < b[0][2]) {
  367. b[0][2] = bb.b[0][2];
  368. }
  369. if ( bb.b[1][0] > b[1][0]) {
  370. b[1][0] = bb.b[1][0];
  371. }
  372. if ( bb.b[1][1] > b[1][1]) {
  373. b[1][1] = bb.b[1][1];
  374. }
  375. if ( bb.b[1][2] > b[1][2]) {
  376. b[1][2] = bb.b[1][2];
  377. }
  378. }
  379. ID_INLINE float Bounds::Radius( ) {
  380. int i;
  381. float total;
  382. float a, aa;
  383. total = 0;
  384. for (i=0 ; i<3 ; i++) {
  385. a = (float)fabs( b[0][i] );
  386. aa = (float)fabs( b[1][i] );
  387. if ( aa > a ) {
  388. a = aa;
  389. }
  390. total += a * a;
  391. }
  392. return (float)idSqrt( total );
  393. }
  394. //===============================================================
  395. class idVec2_t {
  396. public:
  397. float x;
  398. float y;
  399. operator float *();
  400. float operator[]( int index ) const;
  401. float &operator[]( int index );
  402. };
  403. ID_INLINE float idVec2_t::operator[]( int index ) const {
  404. return ( &x )[ index ];
  405. }
  406. ID_INLINE float& idVec2_t::operator[]( int index ) {
  407. return ( &x )[ index ];
  408. }
  409. ID_INLINE idVec2_t::operator float *( void ) {
  410. return &x;
  411. }
  412. class vec4_t : public idVec3_t {
  413. public:
  414. #ifndef FAT_VEC3
  415. float dist;
  416. #endif
  417. vec4_t();
  418. ~vec4_t() {};
  419. vec4_t( float x, float y, float z, float dist );
  420. float operator[]( int index ) const;
  421. float &operator[]( int index );
  422. };
  423. ID_INLINE vec4_t::vec4_t() {}
  424. ID_INLINE vec4_t::vec4_t( float x, float y, float z, float dist ) {
  425. this->x = x;
  426. this->y = y;
  427. this->z = z;
  428. this->dist = dist;
  429. }
  430. ID_INLINE float vec4_t::operator[]( int index ) const {
  431. return ( &x )[ index ];
  432. }
  433. ID_INLINE float& vec4_t::operator[]( int index ) {
  434. return ( &x )[ index ];
  435. }
  436. class idVec5_t : public idVec3_t {
  437. public:
  438. float s;
  439. float t;
  440. float operator[]( int index ) const;
  441. float &operator[]( int index );
  442. };
  443. ID_INLINE float idVec5_t::operator[]( int index ) const {
  444. return ( &x )[ index ];
  445. }
  446. ID_INLINE float& idVec5_t::operator[]( int index ) {
  447. return ( &x )[ index ];
  448. }
  449. #endif /* !__MATH_VECTOR_H__ */