vector.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /*
  2. Copyright (C) 2005 Michael Liebscher <johnnycanuck@users.sourceforge.net>
  3. Copyright (C) 1997-2001 Id Software, Inc.
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. /*
  17. * vector.h: 2D and 3D vector math routines.
  18. *
  19. * Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
  20. *
  21. * Acknowledgement:
  22. * Portion of this code was derived from Quake II, and was originally
  23. * written by Id Software, Inc.
  24. *
  25. */
  26. #include "../wolfiphone.h"
  27. vec3_t vec3_origin = { 0, 0, 0 };
  28. vec_t _VectorNormalize( vec3_t v );
  29. vec_t (*pfVectorNormalize)( vec3_t v ) = _VectorNormalize;
  30. /*
  31. -----------------------------------------------------------------------------
  32. Function: _VectorNormalize -Normalize a 3D vector.
  33. Parameters: v -[in] 3D vector to normalize.
  34. Returns: Unit vector value.
  35. Notes:
  36. For a given vector, the process of finding a unit vector which is
  37. parallel to it. This is done by dividing the given vector by its
  38. magnitude.
  39. -----------------------------------------------------------------------------
  40. */
  41. PUBLIC vec_t _VectorNormalize( vec3_t v )
  42. {
  43. float length, ilength;
  44. length = (float)pfSqrt( v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ] );
  45. if( length )
  46. {
  47. ilength = 1 / length;
  48. v[ 0 ] *= ilength;
  49. v[ 1 ] *= ilength;
  50. v[ 2 ] *= ilength;
  51. }
  52. return length;
  53. }
  54. /*
  55. -----------------------------------------------------------------------------
  56. Function: ProjectPointOnPlane -Project a point onto a plane.
  57. Parameters: dst -[out] Destination Point on Plane.
  58. p -[in] Point to project onto the plane.
  59. normal -[in] A vector to specify the orientation of the plane.
  60. Returns: Nothing.
  61. Notes:
  62. -----------------------------------------------------------------------------
  63. */
  64. PUBLIC void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
  65. {
  66. float d;
  67. vec3_t n;
  68. float inv_denom;
  69. inv_denom = 1.0f / DotProduct( normal, normal );
  70. d = DotProduct( normal, p ) * inv_denom;
  71. n[ 0 ] = normal[ 0 ] * inv_denom;
  72. n[ 1 ] = normal[ 1 ] * inv_denom;
  73. n[ 2 ] = normal[ 2 ] * inv_denom;
  74. dst[ 0 ] = p[ 0 ] - d * n[ 0 ];
  75. dst[ 1 ] = p[ 1 ] - d * n[ 1 ];
  76. dst[ 2 ] = p[ 2 ] - d * n[ 2 ];
  77. }
  78. /*
  79. -----------------------------------------------------------------------------
  80. Function: PerpendicularVector -
  81. Parameters:dst -[out] Perpendicular Vector.
  82. src -[in] Normalized vector.
  83. Returns: Nothing.
  84. Notes:
  85. -----------------------------------------------------------------------------
  86. */
  87. PUBLIC void PerpendicularVector( vec3_t dst, const vec3_t src )
  88. {
  89. int pos;
  90. int i;
  91. float minelem = 1.0F;
  92. vec3_t tempvec;
  93. /* find the smallest magnitude axially aligned vector */
  94. for( pos = 0, i = 0 ; i < 3 ; ++i )
  95. {
  96. if( fabs( src[ i ] ) < minelem )
  97. {
  98. pos = i;
  99. minelem = (float)fabs( src[ i ] );
  100. }
  101. }
  102. tempvec[ 0 ] = tempvec[ 1 ] = tempvec[ 2 ] = 0.0F;
  103. tempvec[ pos ] = 1.0F;
  104. /* project the point onto the plane defined by src */
  105. ProjectPointOnPlane( dst, tempvec, src );
  106. /* normalize the result */
  107. pfVectorNormalize( dst );
  108. }
  109. /*
  110. -----------------------------------------------------------------------------
  111. Function: RotatePointAroundVector -Rotate a point around a vector.
  112. Parameters: dst -[out] Point after rotation.
  113. dir -[in] vector.
  114. point -[in] Point.
  115. degrees -[in] Degrees of rotation.
  116. Returns: Nothing.
  117. Notes:
  118. -----------------------------------------------------------------------------
  119. */
  120. PUBLIC void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
  121. {
  122. mat3_t m;
  123. mat3_t im;
  124. mat3_t zrot;
  125. mat3_t tmpmat;
  126. mat3_t rot;
  127. vec3_t vr, vup, vf;
  128. float rad;
  129. vf[0] = dir[0];
  130. vf[1] = dir[1];
  131. vf[2] = dir[2];
  132. PerpendicularVector( vr, dir );
  133. vectorCrossProduct( vr, vf, vup );
  134. m[0] = vr[0];
  135. m[3] = vr[1];
  136. m[6] = vr[2];
  137. m[1] = vup[0];
  138. m[4] = vup[1];
  139. m[7] = vup[2];
  140. m[2] = vf[0];
  141. m[5] = vf[1];
  142. m[8] = vf[2];
  143. memcpy( im, m, sizeof( im ) );
  144. im[1] = m[3];
  145. im[2] = m[6];
  146. im[3] = m[1];
  147. im[5] = m[7];
  148. im[6] = m[2];
  149. im[7] = m[5];
  150. memset( zrot, 0, sizeof( zrot ) );
  151. zrot[0] = zrot[4] = zrot[8] = 1.0F;
  152. rad = DEG2RAD( degrees );
  153. zrot[0] = (float)cos( rad );
  154. zrot[1] = (float)sin( rad );
  155. zrot[3] = (float)-sin( rad );
  156. zrot[4] = (float)cos( rad );
  157. Matrix3x3Multiply( m, zrot, tmpmat );
  158. Matrix3x3Multiply( tmpmat, im, rot );
  159. dst[0] = rot[0] * point[0] + rot[1] * point[1] + rot[2] * point[2];
  160. dst[1] = rot[3] * point[0] + rot[4] * point[1] + rot[5] * point[2];
  161. dst[2] = rot[6] * point[0] + rot[7] * point[1] + rot[8] * point[2];
  162. }
  163. /*
  164. -----------------------------------------------------------------------------
  165. Function:
  166. Parameters:
  167. Returns:
  168. Notes:
  169. -----------------------------------------------------------------------------
  170. */
  171. PUBLIC float RadiusFromBounds( const vec3_t mins, const vec3_t maxs )
  172. {
  173. int i;
  174. vec3_t corner;
  175. float a, b;
  176. for( i = 0; i < 3; ++i )
  177. {
  178. a = (float)fabs( mins[i] );
  179. b = (float)fabs( maxs[i] );
  180. corner[i] = a > b ? a : b;
  181. }
  182. return vectorLength( corner );
  183. }
  184. /*
  185. -----------------------------------------------------------------------------
  186. Function:
  187. Parameters:
  188. Returns:
  189. Notes:
  190. -----------------------------------------------------------------------------
  191. */
  192. PUBLIC void AddPointToBounds( vec3_t v, vec3_t mins, vec3_t maxs )
  193. {
  194. if ( v[0] < mins[0] )
  195. {
  196. mins[0] = v[0];
  197. }
  198. if ( v[0] > maxs[0])
  199. {
  200. maxs[0] = v[0];
  201. }
  202. if ( v[1] < mins[1] )
  203. {
  204. mins[1] = v[1];
  205. }
  206. if ( v[1] > maxs[1])
  207. {
  208. maxs[1] = v[1];
  209. }
  210. if ( v[2] < mins[2] )
  211. {
  212. mins[2] = v[2];
  213. }
  214. if ( v[2] > maxs[2])
  215. {
  216. maxs[2] = v[2];
  217. }
  218. }
  219. /*
  220. -----------------------------------------------------------------------------
  221. Function:
  222. Parameters:
  223. Returns:
  224. Notes:
  225. -----------------------------------------------------------------------------
  226. */
  227. PUBLIC void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up )
  228. {
  229. float angle;
  230. static float sr, sp, sy, cr, cp, cy;
  231. // static to help MS compiler fp bugs
  232. angle = angles[YAW] * ( M_PI*2 / 360 );
  233. sy = (float)sin( angle );
  234. cy = (float)cos( angle );
  235. angle = angles[PITCH] * ( M_PI*2 / 360 );
  236. sp = (float)sin( angle );
  237. cp = (float)cos( angle );
  238. angle = angles[ROLL] * ( M_PI*2 / 360 );
  239. sr = (float)sin( angle );
  240. cr = (float)cos( angle );
  241. if( forward )
  242. {
  243. forward[0] = cp*cy;
  244. forward[1] = cp*sy;
  245. forward[2] = -sp;
  246. }
  247. if( right )
  248. {
  249. right[0] = (-1*sr*sp*cy+-1*cr*-sy);
  250. right[1] = (-1*sr*sp*sy+-1*cr*cy);
  251. right[2] = -1*sr*cp;
  252. }
  253. if( up )
  254. {
  255. up[0] = (cr*sp*cy+-sr*-sy);
  256. up[1] = (cr*sp*sy+-sr*cy);
  257. up[2] = cr*cp;
  258. }
  259. }
  260. /*
  261. -----------------------------------------------------------------------------
  262. Function: vectorCompare -Compares two vectors for equality.
  263. Parameters: v1, v2 -[in] 3d vectors to compare.
  264. Returns: 1 if they are equal, otherwise 0.
  265. Notes:
  266. -----------------------------------------------------------------------------
  267. */
  268. INLINECALL int vectorCompare( const vec3_t v1, const vec3_t v2 )
  269. {
  270. if( v1[ 0 ] != v2[ 0 ] ||
  271. v1[ 1 ] != v2[ 1 ] ||
  272. v1[ 2 ] != v2[ 2 ] )
  273. {
  274. return 0;
  275. }
  276. return 1;
  277. }
  278. /*
  279. -----------------------------------------------------------------------------
  280. Function: vectorLength -Get the length of a vector.
  281. Parameters: v -[in] 3D vector to get the length of.
  282. Returns: The length of the vector.
  283. Notes:
  284. Since the square of length is a sum of squares, and squares
  285. (of real numbers) are always positive, length is always positive.
  286. The only time the length of a 3D vector is zero is when the vector
  287. is the zero vector.
  288. -----------------------------------------------------------------------------
  289. */
  290. INLINECALL vec_t vectorLength( const vec3_t v )
  291. {
  292. return (vec_t)pfSqrt( v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ] );
  293. }
  294. /*
  295. -----------------------------------------------------------------------------
  296. Function: CrossProduct -Calulates the cross product of two vectors.
  297. Parameters: v1, v2 -[in] 3D vectors.
  298. cross -[out] The vector cross product.
  299. Returns: Nothing
  300. Notes:
  301. The vector cross product takes two vector operands to produce a
  302. vector result. The result, like all geometric vectors, has two
  303. properties: length and orientation.
  304. To find a vector perpendicular to a particular plane, compute the
  305. cross product of two vectors in that plane. But there are two
  306. directions perpendicular to the plane. Which one does the cross
  307. product give you? That is determined by the right hand rule.
  308. The cross product of two vectors is perpendicular to both; the right
  309. hand rule picks the one out of two possible perpendicular directions.
  310. Computing Cross Product from Column Matrices:
  311. u × v = ( uj vk - uk vj , uk vi - ui vk , ui vj - uj vi )T
  312. -----------------------------------------------------------------------------
  313. */
  314. PUBLIC void vectorCrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross )
  315. {
  316. cross[ 0 ] = v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ]; // X
  317. cross[ 1 ] = v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ]; // Y
  318. cross[ 2 ] = v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ]; // Z
  319. }
  320. #if defined(__i386__) && defined(_MSC_VER)
  321. // Taken from an article written by Michael Abrash that originally appeared in
  322. // Dr. Dobb's Journal.
  323. PUBLIC void vectorCrossProduct_asm( const vec3_t v1, const vec3_t v2, vec3_t cross )
  324. {
  325. __asm
  326. {
  327. mov eax, cross
  328. mov ecx, v2
  329. mov edx, v1
  330. ;optimized cross product; 22 cycles
  331. fld dword ptr [ecx+4] ;starts & ends on cycle 0
  332. fmul dword ptr [edx+8] ;starts on cycle 1
  333. fld dword ptr [ecx+8] ;starts & ends on cycle 2
  334. fmul dword ptr [edx+0] ;starts on cycle 3
  335. fld dword ptr [ecx+0] ;starts & ends on cycle 4
  336. fmul dword ptr [edx+4] ;starts on cycle 5
  337. fld dword ptr [ecx+8] ;starts & ends on cycle 6
  338. fmul dword ptr [edx+4] ;starts on cycle 7
  339. fld dword ptr [ecx+0] ;starts & ends on cycle 8
  340. fmul dword ptr [edx+8] ;starts on cycle 9
  341. fld dword ptr [ecx+4] ;starts & ends on cycle 10
  342. fmul dword ptr [edx+0] ;starts on cycle 11
  343. fxch st(2) ;no cost
  344. fsubrp st(5),st(0) ;starts on cycle 12
  345. fsubrp st(3),st(0) ;starts on cycle 13
  346. fsubrp st(1),st(0) ;starts on cycle 14
  347. fxch st(2) ;no cost, stalls for cycle 15
  348. fstp dword ptr [eax+0] ;starts on cycle 16, ends on cycle 17
  349. fstp dword ptr [eax+4] ;starts on cycle 18, ends on cycle 19
  350. fstp dword ptr [eax+8] ;starts on cycle 20, ends on cycle 21
  351. }
  352. }
  353. #endif /* __i386__ */
  354. /*
  355. -----------------------------------------------------------------------------
  356. Function: _DotProduct -Calculates the dot product.
  357. Parameters: v1, v2 -[in] 3D vectors to compute dot product.
  358. Returns: the dot product
  359. Notes:
  360. Dot product, which takes two vectors as operands and produces a real
  361. number as its output. Sometimes the dot product is called the inner
  362. product or the scalar product.
  363. The dot product is:
  364. a · b = a1b1 + a2b2 + a3b3
  365. -----------------------------------------------------------------------------
  366. */
  367. PUBLIC vec_t _vectorDotProduct( const vec3_t v1, const vec3_t v2 )
  368. {
  369. return v1[ 0 ] * v2[ 0 ] + v1[ 1 ] * v2[ 1 ] + v1[ 2 ] * v2[ 2 ];
  370. }
  371. #if defined(__i386__) && defined(_MSC_VER)
  372. // Taken from an article written by Michael Abrash that originally appeared in
  373. // Dr. Dobb's Journal.
  374. PUBLIC vec_t _vectorDotProduct_asm( const vec3_t v1, const vec3_t v2 )
  375. {
  376. float dotret;
  377. __asm
  378. {
  379. mov eax, v2
  380. mov ecx, v1
  381. ;optimized dot product; 15 cycles
  382. fld dword ptr [eax+0] ;starts & ends on cycle 0
  383. fmul dword ptr [ecx+0] ;starts on cycle 1
  384. fld dword ptr [eax+4] ;starts & ends on cycle 2
  385. fmul dword ptr [ecx+4] ;starts on cycle 3
  386. fld dword ptr [eax+8] ;starts & ends on cycle 4
  387. fmul dword ptr [ecx+8] ;starts on cycle 5
  388. fxch st(1) ;no cost
  389. faddp st(2),st(0) ;starts on cycle 6, stalls for cycles 7-8
  390. faddp st(1),st(0) ;starts on cycle 9, stalls for cycles 10-12
  391. fstp dword ptr [dotret] ;starts on cycle 13, ends on cycle 14
  392. }
  393. return dotret;
  394. }
  395. #endif /* __i386__ */
  396. /*
  397. -----------------------------------------------------------------------------
  398. Function: _vectorSubtract -Vector Difference.
  399. Parameters: veca, vecb -[in] 3D vectors.
  400. out -[out] The vector difference of vectors A and B.
  401. Returns: Nothing.
  402. Notes:
  403. -----------------------------------------------------------------------------
  404. */
  405. INLINECALL void _vectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out )
  406. {
  407. out[ 0 ] = veca[ 0 ] - vecb[ 0 ];
  408. out[ 1 ] = veca[ 1 ] - vecb[ 1 ];
  409. out[ 2 ] = veca[ 2 ] - vecb[ 2 ];
  410. }
  411. /*
  412. -----------------------------------------------------------------------------
  413. Function: _vectorAdd -Vector addition.
  414. Parameters: veca, vecb -[in] 3D vectors.
  415. out -[out] The vector sum of vectors A and B
  416. Returns: Nothing.
  417. Notes:
  418. -----------------------------------------------------------------------------
  419. */
  420. INLINECALL void _vectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out )
  421. {
  422. out[ 0 ] = veca[ 0 ] + vecb[ 0 ];
  423. out[ 1 ] = veca[ 1 ] + vecb[ 1 ];
  424. out[ 2 ] = veca[ 2 ] + vecb[ 2 ];
  425. }
  426. /*
  427. -----------------------------------------------------------------------------
  428. Function: _vectorCopy -Copy a vector.
  429. Parameters: in -[in] Source vector.
  430. out -[out] Destination vector.
  431. Returns: Nothing.
  432. Notes:
  433. -----------------------------------------------------------------------------
  434. */
  435. INLINECALL void _vectorCopy( const vec3_t in, vec3_t out )
  436. {
  437. out[ 0 ] = in[ 0 ];
  438. out[ 1 ] = in[ 1 ];
  439. out[ 2 ] = in[ 2 ];
  440. }
  441. /*
  442. -----------------------------------------------------------------------------
  443. Function: _vectorScale -Scale a vector.
  444. Parameters: in -[in] Source vector.
  445. scale -[in] Scale vector.
  446. out -[out] Destination vector.
  447. Returns: Nothing.
  448. Notes:
  449. -----------------------------------------------------------------------------
  450. */
  451. INLINECALL void _vectorScale( const vec3_t in, const vec_t scale, vec3_t out )
  452. {
  453. out[ 0 ] = in[ 0 ] * scale;
  454. out[ 1 ] = in[ 1 ] * scale;
  455. out[ 2 ] = in[ 2 ] * scale;
  456. }
  457. /*
  458. -----------------------------------------------------------------------------
  459. Function:
  460. Parameters:
  461. Returns:
  462. Notes:
  463. -----------------------------------------------------------------------------
  464. */
  465. INLINECALL void _vectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc )
  466. {
  467. vecc[ 0 ] = veca[ 0 ] + scale * vecb[ 0 ];
  468. vecc[ 1 ] = veca[ 1 ] + scale * vecb[ 1 ];
  469. vecc[ 2 ] = veca[ 2 ] + scale * vecb[ 2 ];
  470. }
  471. /////////////////////////////////////////////////////////////////////
  472. //
  473. // 2D Vector routines
  474. //
  475. /////////////////////////////////////////////////////////////////////
  476. /*
  477. -----------------------------------------------------------------------------
  478. Function: vector2DCompare -Compares two vectors for equality.
  479. Parameters: v1, v2 -[in] 2d vectors to compare.
  480. Returns: 1 if they are equal, otherwise 0.
  481. Notes:
  482. -----------------------------------------------------------------------------
  483. */
  484. INLINECALL W32 vector2DCompare( const vec2_t v1, const vec2_t v2 )
  485. {
  486. if( v1[ 0 ] != v2[ 0 ] || v1[ 1 ] != v2[ 1 ] )
  487. {
  488. return 0;
  489. }
  490. return 1;
  491. }
  492. /*
  493. -----------------------------------------------------------------------------
  494. Function: vector2DLength -Get the length of a vector.
  495. Parameters: v -[in] 2D vector to get the length of.
  496. Returns: The length of the vector.
  497. Notes:
  498. -----------------------------------------------------------------------------
  499. */
  500. INLINECALL vec_t vector2DLength( const vec2_t v )
  501. {
  502. return (vec_t)pfSqrt( v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] );
  503. }