PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/src/engine/qcommon/q_math.cpp

https://gitlab.com/xonotic/daemon
C++ | 3480 lines | 2503 code | 511 blank | 466 comment | 200 complexity | fc21da802296a58e12c0d2a582e8b7df MD5 | raw file
Possible License(s): BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * ===========================================================================
  3. *
  4. * Daemon GPL Source Code
  5. * Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
  6. *
  7. * This file is part of the Daemon GPL Source Code (Daemon Source Code).
  8. *
  9. * Daemon Source Code is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * Daemon Source Code is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with Daemon Source Code. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * In addition, the Daemon Source Code is also subject to certain additional terms.
  23. * You should have received a copy of these additional terms immediately following the
  24. * terms and conditions of the GNU General Public License which accompanied the Daemon
  25. * Source Code. If not, please request a copy in writing from id Software at the address
  26. * below.
  27. *
  28. * If you have questions concerning this license or the applicable additional terms, you
  29. * may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville,
  30. * Maryland 20850 USA.
  31. *
  32. * ===========================================================================
  33. */
  34. // q_math.c -- stateless support routines that are included in each code module
  35. #include "q_shared.h"
  36. // *INDENT-OFF*
  37. vec3_t vec3_origin = { 0, 0, 0 };
  38. vec3_t axisDefault[ 3 ] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
  39. matrix_t matrixIdentity = { 1, 0, 0, 0,
  40. 0, 1, 0, 0,
  41. 0, 0, 1, 0,
  42. 0, 0, 0, 1
  43. };
  44. quat_t quatIdentity = { 0, 0, 0, 1 };
  45. vec3_t bytedirs[ NUMVERTEXNORMALS ] =
  46. {
  47. { -0.525731, 0.000000, 0.850651 }, { -0.442863, 0.238856, 0.864188 },
  48. { -0.295242, 0.000000, 0.955423 }, { -0.309017, 0.500000, 0.809017 },
  49. { -0.162460, 0.262866, 0.951056 }, { 0.000000, 0.000000, 1.000000 },
  50. { 0.000000, 0.850651, 0.525731 }, { -0.147621, 0.716567, 0.681718 },
  51. { 0.147621, 0.716567, 0.681718 }, { 0.000000, 0.525731, 0.850651 },
  52. { 0.309017, 0.500000, 0.809017 }, { 0.525731, 0.000000, 0.850651 },
  53. { 0.295242, 0.000000, 0.955423 }, { 0.442863, 0.238856, 0.864188 },
  54. { 0.162460, 0.262866, 0.951056 }, { -0.681718, 0.147621, 0.716567 },
  55. { -0.809017, 0.309017, 0.500000 }, { -0.587785, 0.425325, 0.688191 },
  56. { -0.850651, 0.525731, 0.000000 }, { -0.864188, 0.442863, 0.238856 },
  57. { -0.716567, 0.681718, 0.147621 }, { -0.688191, 0.587785, 0.425325 },
  58. { -0.500000, 0.809017, 0.309017 }, { -0.238856, 0.864188, 0.442863 },
  59. { -0.425325, 0.688191, 0.587785 }, { -0.716567, 0.681718, -0.147621 },
  60. { -0.500000, 0.809017, -0.309017 }, { -0.525731, 0.850651, 0.000000 },
  61. { 0.000000, 0.850651, -0.525731 }, { -0.238856, 0.864188, -0.442863 },
  62. { 0.000000, 0.955423, -0.295242 }, { -0.262866, 0.951056, -0.162460 },
  63. { 0.000000, 1.000000, 0.000000 }, { 0.000000, 0.955423, 0.295242 },
  64. { -0.262866, 0.951056, 0.162460 }, { 0.238856, 0.864188, 0.442863 },
  65. { 0.262866, 0.951056, 0.162460 }, { 0.500000, 0.809017, 0.309017 },
  66. { 0.238856, 0.864188, -0.442863 }, { 0.262866, 0.951056, -0.162460 },
  67. { 0.500000, 0.809017, -0.309017 }, { 0.850651, 0.525731, 0.000000 },
  68. { 0.716567, 0.681718, 0.147621 }, { 0.716567, 0.681718, -0.147621 },
  69. { 0.525731, 0.850651, 0.000000 }, { 0.425325, 0.688191, 0.587785 },
  70. { 0.864188, 0.442863, 0.238856 }, { 0.688191, 0.587785, 0.425325 },
  71. { 0.809017, 0.309017, 0.500000 }, { 0.681718, 0.147621, 0.716567 },
  72. { 0.587785, 0.425325, 0.688191 }, { 0.955423, 0.295242, 0.000000 },
  73. { 1.000000, 0.000000, 0.000000 }, { 0.951056, 0.162460, 0.262866 },
  74. { 0.850651, -0.525731, 0.000000 }, { 0.955423, -0.295242, 0.000000 },
  75. { 0.864188, -0.442863, 0.238856 }, { 0.951056, -0.162460, 0.262866 },
  76. { 0.809017, -0.309017, 0.500000 }, { 0.681718, -0.147621, 0.716567 },
  77. { 0.850651, 0.000000, 0.525731 }, { 0.864188, 0.442863, -0.238856 },
  78. { 0.809017, 0.309017, -0.500000 }, { 0.951056, 0.162460, -0.262866 },
  79. { 0.525731, 0.000000, -0.850651 }, { 0.681718, 0.147621, -0.716567 },
  80. { 0.681718, -0.147621, -0.716567 }, { 0.850651, 0.000000, -0.525731 },
  81. { 0.809017, -0.309017, -0.500000 }, { 0.864188, -0.442863, -0.238856 },
  82. { 0.951056, -0.162460, -0.262866 }, { 0.147621, 0.716567, -0.681718 },
  83. { 0.309017, 0.500000, -0.809017 }, { 0.425325, 0.688191, -0.587785 },
  84. { 0.442863, 0.238856, -0.864188 }, { 0.587785, 0.425325, -0.688191 },
  85. { 0.688191, 0.587785, -0.425325 }, { -0.147621, 0.716567, -0.681718 },
  86. { -0.309017, 0.500000, -0.809017 }, { 0.000000, 0.525731, -0.850651 },
  87. { -0.525731, 0.000000, -0.850651 }, { -0.442863, 0.238856, -0.864188 },
  88. { -0.295242, 0.000000, -0.955423 }, { -0.162460, 0.262866, -0.951056 },
  89. { 0.000000, 0.000000, -1.000000 }, { 0.295242, 0.000000, -0.955423 },
  90. { 0.162460, 0.262866, -0.951056 }, { -0.442863, -0.238856, -0.864188 },
  91. { -0.309017, -0.500000, -0.809017 }, { -0.162460, -0.262866, -0.951056 },
  92. { 0.000000, -0.850651, -0.525731 }, { -0.147621, -0.716567, -0.681718 },
  93. { 0.147621, -0.716567, -0.681718 }, { 0.000000, -0.525731, -0.850651 },
  94. { 0.309017, -0.500000, -0.809017 }, { 0.442863, -0.238856, -0.864188 },
  95. { 0.162460, -0.262866, -0.951056 }, { 0.238856, -0.864188, -0.442863 },
  96. { 0.500000, -0.809017, -0.309017 }, { 0.425325, -0.688191, -0.587785 },
  97. { 0.716567, -0.681718, -0.147621 }, { 0.688191, -0.587785, -0.425325 },
  98. { 0.587785, -0.425325, -0.688191 }, { 0.000000, -0.955423, -0.295242 },
  99. { 0.000000, -1.000000, 0.000000 }, { 0.262866, -0.951056, -0.162460 },
  100. { 0.000000, -0.850651, 0.525731 }, { 0.000000, -0.955423, 0.295242 },
  101. { 0.238856, -0.864188, 0.442863 }, { 0.262866, -0.951056, 0.162460 },
  102. { 0.500000, -0.809017, 0.309017 }, { 0.716567, -0.681718, 0.147621 },
  103. { 0.525731, -0.850651, 0.000000 }, { -0.238856, -0.864188, -0.442863 },
  104. { -0.500000, -0.809017, -0.309017 }, { -0.262866, -0.951056, -0.162460 },
  105. { -0.850651, -0.525731, 0.000000 }, { -0.716567, -0.681718, -0.147621 },
  106. { -0.716567, -0.681718, 0.147621 }, { -0.525731, -0.850651, 0.000000 },
  107. { -0.500000, -0.809017, 0.309017 }, { -0.238856, -0.864188, 0.442863 },
  108. { -0.262866, -0.951056, 0.162460 }, { -0.864188, -0.442863, 0.238856 },
  109. { -0.809017, -0.309017, 0.500000 }, { -0.688191, -0.587785, 0.425325 },
  110. { -0.681718, -0.147621, 0.716567 }, { -0.442863, -0.238856, 0.864188 },
  111. { -0.587785, -0.425325, 0.688191 }, { -0.309017, -0.500000, 0.809017 },
  112. { -0.147621, -0.716567, 0.681718 }, { -0.425325, -0.688191, 0.587785 },
  113. { -0.162460, -0.262866, 0.951056 }, { 0.442863, -0.238856, 0.864188 },
  114. { 0.162460, -0.262866, 0.951056 }, { 0.309017, -0.500000, 0.809017 },
  115. { 0.147621, -0.716567, 0.681718 }, { 0.000000, -0.525731, 0.850651 },
  116. { 0.425325, -0.688191, 0.587785 }, { 0.587785, -0.425325, 0.688191 },
  117. { 0.688191, -0.587785, 0.425325 }, { -0.955423, 0.295242, 0.000000 },
  118. { -0.951056, 0.162460, 0.262866 }, { -1.000000, 0.000000, 0.000000 },
  119. { -0.850651, 0.000000, 0.525731 }, { -0.955423, -0.295242, 0.000000 },
  120. { -0.951056, -0.162460, 0.262866 }, { -0.864188, 0.442863, -0.238856 },
  121. { -0.951056, 0.162460, -0.262866 }, { -0.809017, 0.309017, -0.500000 },
  122. { -0.864188, -0.442863, -0.238856 }, { -0.951056, -0.162460, -0.262866 },
  123. { -0.809017, -0.309017, -0.500000 }, { -0.681718, 0.147621, -0.716567 },
  124. { -0.681718, -0.147621, -0.716567 }, { -0.850651, 0.000000, -0.525731 },
  125. { -0.688191, 0.587785, -0.425325 }, { -0.587785, 0.425325, -0.688191 },
  126. { -0.425325, 0.688191, -0.587785 }, { -0.425325, -0.688191, -0.587785 },
  127. { -0.587785, -0.425325, -0.688191 }, { -0.688191, -0.587785, -0.425325 }
  128. };
  129. // *INDENT-ON*
  130. //==============================================================
  131. int Q_rand( int *seed )
  132. {
  133. *seed = ( 69069 * *seed + 1 );
  134. return *seed;
  135. }
  136. // Range of [0,1]
  137. float Q_random( int *seed )
  138. {
  139. return ( Q_rand( seed ) & 0xffff ) / ( float ) 0x10000;
  140. }
  141. // Range of [-1,1]
  142. float Q_crandom( int *seed )
  143. {
  144. return 2.0 * ( Q_random( seed ) - 0.5 );
  145. }
  146. //=======================================================
  147. byte ClampByte( int i )
  148. {
  149. if ( i < 0 )
  150. {
  151. return 0;
  152. }
  153. if ( i > 255 )
  154. {
  155. return 255;
  156. }
  157. return i;
  158. }
  159. signed char ClampChar( int i )
  160. {
  161. if ( i < -128 )
  162. {
  163. return -128;
  164. }
  165. if ( i > 127 )
  166. {
  167. return 127;
  168. }
  169. return i;
  170. }
  171. // this isn't a real cheap function to call!
  172. int DirToByte( vec3_t dir )
  173. {
  174. int i, best;
  175. float d, bestd;
  176. if ( !dir )
  177. {
  178. return 0;
  179. }
  180. bestd = 0;
  181. best = 0;
  182. for ( i = 0; i < NUMVERTEXNORMALS; i++ )
  183. {
  184. d = DotProduct( dir, bytedirs[ i ] );
  185. if ( d > bestd )
  186. {
  187. bestd = d;
  188. best = i;
  189. }
  190. }
  191. return best;
  192. }
  193. void ByteToDir( int b, vec3_t dir )
  194. {
  195. if ( b < 0 || b >= NUMVERTEXNORMALS )
  196. {
  197. VectorCopy( vec3_origin, dir );
  198. return;
  199. }
  200. VectorCopy( bytedirs[ b ], dir );
  201. }
  202. vec_t PlaneNormalize( vec4_t plane )
  203. {
  204. vec_t length2, ilength;
  205. length2 = DotProduct( plane, plane );
  206. if ( length2 == 0.0f )
  207. {
  208. VectorClear( plane );
  209. return 0.0f;
  210. }
  211. ilength = Q_rsqrt( length2 );
  212. plane[ 0 ] = plane[ 0 ] * ilength;
  213. plane[ 1 ] = plane[ 1 ] * ilength;
  214. plane[ 2 ] = plane[ 2 ] * ilength;
  215. plane[ 3 ] = plane[ 3 ] * ilength;
  216. return length2 * ilength;
  217. }
  218. /*
  219. * =====================
  220. * PlaneFromPoints
  221. *
  222. * Returns false if the triangle is degenerate.
  223. * The normal will point out of the clock for clockwise ordered points
  224. * =====================
  225. */
  226. bool PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c )
  227. {
  228. vec3_t d1, d2;
  229. VectorSubtract( b, a, d1 );
  230. VectorSubtract( c, a, d2 );
  231. CrossProduct( d2, d1, plane );
  232. if ( VectorNormalize( plane ) == 0 )
  233. {
  234. return false;
  235. }
  236. plane[ 3 ] = DotProduct( a, plane );
  237. return true;
  238. }
  239. /*
  240. * =====================
  241. * PlaneFromPoints
  242. *
  243. * Returns false if the triangle is degenerate.
  244. * =====================
  245. */
  246. bool PlaneFromPointsOrder( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c, bool cw )
  247. {
  248. vec3_t d1, d2;
  249. VectorSubtract( b, a, d1 );
  250. VectorSubtract( c, a, d2 );
  251. if ( cw )
  252. {
  253. CrossProduct( d2, d1, plane );
  254. }
  255. else
  256. {
  257. CrossProduct( d1, d2, plane );
  258. }
  259. if ( VectorNormalize( plane ) == 0 )
  260. {
  261. return false;
  262. }
  263. plane[ 3 ] = DotProduct( a, plane );
  264. return true;
  265. }
  266. bool PlanesGetIntersectionPoint( const vec4_t plane1, const vec4_t plane2, const vec4_t plane3, vec3_t out )
  267. {
  268. // http://www.cgafaq.info/wiki/Intersection_of_three_planes
  269. vec3_t n1, n2, n3;
  270. vec3_t n1n2, n2n3, n3n1;
  271. vec_t denom;
  272. VectorNormalize2( plane1, n1 );
  273. VectorNormalize2( plane2, n2 );
  274. VectorNormalize2( plane3, n3 );
  275. CrossProduct( n1, n2, n1n2 );
  276. CrossProduct( n2, n3, n2n3 );
  277. CrossProduct( n3, n1, n3n1 );
  278. denom = DotProduct( n1, n2n3 );
  279. // check if the denominator is zero (which would mean that no intersection is to be found
  280. if ( denom == 0 )
  281. {
  282. // no intersection could be found, return <0,0,0>
  283. VectorClear( out );
  284. return false;
  285. }
  286. VectorClear( out );
  287. VectorMA( out, plane1[ 3 ], n2n3, out );
  288. VectorMA( out, plane2[ 3 ], n3n1, out );
  289. VectorMA( out, plane3[ 3 ], n1n2, out );
  290. VectorScale( out, 1.0f / denom, out );
  291. return true;
  292. }
  293. void PlaneIntersectRay( const vec3_t rayPos, const vec3_t rayDir, const vec4_t plane, vec3_t res )
  294. {
  295. vec3_t dir;
  296. float sect;
  297. VectorNormalize2( rayDir, dir );
  298. sect = - ( DotProduct( plane, rayPos ) - plane[ 3 ] ) / DotProduct( plane, rayDir );
  299. VectorScale( dir, sect, dir );
  300. VectorAdd( rayPos, dir, res );
  301. }
  302. /*
  303. * ===============
  304. * RotatePointAroundVector
  305. * ===============
  306. */
  307. void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
  308. {
  309. float sind, cosd, expr;
  310. vec3_t dxp;
  311. degrees = DEG2RAD( degrees );
  312. sind = sin( degrees );
  313. cosd = cos( degrees );
  314. expr = ( 1 - cosd ) * DotProduct( dir, point );
  315. CrossProduct( dir, point, dxp );
  316. dst[ 0 ] = expr * dir[ 0 ] + cosd * point[ 0 ] + sind * dxp[ 0 ];
  317. dst[ 1 ] = expr * dir[ 1 ] + cosd * point[ 1 ] + sind * dxp[ 1 ];
  318. dst[ 2 ] = expr * dir[ 2 ] + cosd * point[ 2 ] + sind * dxp[ 2 ];
  319. }
  320. /*
  321. * ===============
  322. * RotateAroundDirection
  323. * ===============
  324. */
  325. void RotateAroundDirection( vec3_t axis[ 3 ], float yaw )
  326. {
  327. // create an arbitrary axis[1]
  328. PerpendicularVector( axis[ 1 ], axis[ 0 ] );
  329. // rotate it around axis[0] by yaw
  330. if ( yaw )
  331. {
  332. vec3_t temp;
  333. VectorCopy( axis[ 1 ], temp );
  334. RotatePointAroundVector( axis[ 1 ], axis[ 0 ], temp, yaw );
  335. }
  336. // cross to get axis[2]
  337. CrossProduct( axis[ 0 ], axis[ 1 ], axis[ 2 ] );
  338. }
  339. void vectoangles( const vec3_t value1, vec3_t angles )
  340. {
  341. float forward;
  342. float yaw, pitch;
  343. if ( value1[ 1 ] == 0 && value1[ 0 ] == 0 )
  344. {
  345. yaw = 0;
  346. if ( value1[ 2 ] > 0 )
  347. {
  348. pitch = 90;
  349. }
  350. else
  351. {
  352. pitch = 270;
  353. }
  354. }
  355. else
  356. {
  357. if ( value1[ 0 ] )
  358. {
  359. yaw = ( atan2( value1[ 1 ], value1[ 0 ] ) * 180 / M_PI );
  360. }
  361. else if ( value1[ 1 ] > 0 )
  362. {
  363. yaw = 90;
  364. }
  365. else
  366. {
  367. yaw = 270;
  368. }
  369. if ( yaw < 0 )
  370. {
  371. yaw += 360;
  372. }
  373. forward = sqrt( value1[ 0 ] * value1[ 0 ] + value1[ 1 ] * value1[ 1 ] );
  374. pitch = ( atan2( value1[ 2 ], forward ) * 180 / M_PI );
  375. if ( pitch < 0 )
  376. {
  377. pitch += 360;
  378. }
  379. }
  380. angles[ PITCH ] = -pitch;
  381. angles[ YAW ] = yaw;
  382. angles[ ROLL ] = 0;
  383. }
  384. /*
  385. * =================
  386. * AnglesToAxis
  387. * =================
  388. */
  389. void AnglesToAxis( const vec3_t angles, vec3_t axis[ 3 ] )
  390. {
  391. vec3_t right;
  392. // angle vectors returns "right" instead of "y axis"
  393. AngleVectors( angles, axis[ 0 ], right, axis[ 2 ] );
  394. VectorSubtract( vec3_origin, right, axis[ 1 ] );
  395. }
  396. void AxisClear( vec3_t axis[ 3 ] )
  397. {
  398. axis[ 0 ][ 0 ] = 1;
  399. axis[ 0 ][ 1 ] = 0;
  400. axis[ 0 ][ 2 ] = 0;
  401. axis[ 1 ][ 0 ] = 0;
  402. axis[ 1 ][ 1 ] = 1;
  403. axis[ 1 ][ 2 ] = 0;
  404. axis[ 2 ][ 0 ] = 0;
  405. axis[ 2 ][ 1 ] = 0;
  406. axis[ 2 ][ 2 ] = 1;
  407. }
  408. void AxisCopy( vec3_t in[ 3 ], vec3_t out[ 3 ] )
  409. {
  410. VectorCopy( in[ 0 ], out[ 0 ] );
  411. VectorCopy( in[ 1 ], out[ 1 ] );
  412. VectorCopy( in[ 2 ], out[ 2 ] );
  413. }
  414. void ProjectPointOnPlane( vec3_t dst, const vec3_t point, const vec3_t normal )
  415. {
  416. float d = -DotProduct( point, normal );
  417. VectorMA( point, d, normal, dst );
  418. }
  419. /*
  420. * ================
  421. * MakeNormalVectors
  422. *
  423. * Given a normalized forward vector, create two
  424. * other perpendicular vectors
  425. * ================
  426. */
  427. void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up )
  428. {
  429. float d;
  430. // this rotate and negate guarantees a vector
  431. // not colinear with the original
  432. right[ 1 ] = -forward[ 0 ];
  433. right[ 2 ] = forward[ 1 ];
  434. right[ 0 ] = forward[ 2 ];
  435. d = DotProduct( right, forward );
  436. VectorMA( right, -d, forward, right );
  437. VectorNormalize( right );
  438. CrossProduct( right, forward, up );
  439. }
  440. /*
  441. ==================
  442. ProjectPointOntoRectangleOutwards
  443. Traces a ray from inside a rectangle and returns the point of
  444. intersection with the rectangle
  445. ==================
  446. */
  447. float ProjectPointOntoRectangleOutwards( vec2_t out, const vec2_t point, const vec2_t dir,
  448. const vec2_t bounds[ 2 ] )
  449. {
  450. float t, ty;
  451. bool dsign[ 2 ];
  452. dsign[ 0 ] = ( dir[ 0 ] < 0 );
  453. dsign[ 1 ] = ( dir[ 1 ] < 0.0 );
  454. t = ( bounds[ 1 - dsign[ 0 ] ][ 0 ] - point[ 0 ] ) / dir[ 0 ];
  455. ty = ( bounds[ 1 - dsign[ 1 ] ][ 1 ] - point[ 1 ] ) / dir[ 1 ];
  456. if( ty < t )
  457. t = ty;
  458. out[ 0 ] = point[ 0 ] + dir[ 0 ] * t;
  459. out[ 1 ] = point[ 1 ] + dir[ 1 ] * t;
  460. return t;
  461. }
  462. //============================================================
  463. /*
  464. =============
  465. ExponentialFade
  466. Fades one value towards another exponentially
  467. =============
  468. */
  469. void ExponentialFade( float *value, float target, float lambda, float timedelta )
  470. {
  471. *value = target + ( *value - target ) * exp( - lambda * timedelta );
  472. }
  473. /*
  474. * ===============
  475. * LerpAngle
  476. *
  477. * ===============
  478. */
  479. float LerpAngle( float from, float to, float frac )
  480. {
  481. if ( to - from > 180 )
  482. {
  483. to -= 360;
  484. }
  485. if ( to - from < -180 )
  486. {
  487. to += 360;
  488. }
  489. return ( from + frac * ( to - from ) );
  490. }
  491. /*
  492. * =================
  493. * AngleSubtract
  494. *
  495. * Always returns a value from -180 to 180
  496. * =================
  497. */
  498. float AngleSubtract( float a1, float a2 )
  499. {
  500. float a = a1 - a2;
  501. return a - 360.0f * floor( ( a + 180.0f ) / 360.0f );
  502. }
  503. void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 )
  504. {
  505. v3[ 0 ] = AngleSubtract( v1[ 0 ], v2[ 0 ] );
  506. v3[ 1 ] = AngleSubtract( v1[ 1 ], v2[ 1 ] );
  507. v3[ 2 ] = AngleSubtract( v1[ 2 ], v2[ 2 ] );
  508. }
  509. float AngleMod( float a )
  510. {
  511. return ( ( 360.0 / 65536 ) * ( ( int )( a * ( 65536 / 360.0 ) ) & 65535 ) );
  512. }
  513. /*
  514. * =================
  515. * AngleNormalize360
  516. *
  517. * returns angle normalized to the range [0 <= angle < 360]
  518. * =================
  519. */
  520. float AngleNormalize360( float angle )
  521. {
  522. return ( 360.0 / 65536 ) * ( ( int )( angle * ( 65536 / 360.0 ) ) & 65535 );
  523. }
  524. /*
  525. * =================
  526. * AngleNormalize180
  527. *
  528. * returns angle normalized to the range [-180 < angle <= 180]
  529. * =================
  530. */
  531. float AngleNormalize180( float angle )
  532. {
  533. angle = AngleNormalize360( angle );
  534. if ( angle > 180.0 )
  535. {
  536. angle -= 360.0;
  537. }
  538. return angle;
  539. }
  540. /*
  541. * =================
  542. * AngleDelta
  543. *
  544. * returns the normalized delta from angle1 to angle2
  545. * =================
  546. */
  547. float AngleDelta( float angle1, float angle2 )
  548. {
  549. return AngleNormalize180( angle1 - angle2 );
  550. }
  551. /*
  552. * =================
  553. * AngleBetweenVectors
  554. *
  555. * returns the angle between two vectors normalized to the range [0 <= angle <= 180]
  556. * =================
  557. */
  558. float AngleBetweenVectors( const vec3_t a, const vec3_t b )
  559. {
  560. vec_t alen, blen;
  561. alen = VectorLength( a );
  562. blen = VectorLength( b );
  563. if ( !alen || !blen )
  564. {
  565. return 0;
  566. }
  567. // complete dot product of two vectors a, b is |a| * |b| * cos(angle)
  568. // this results in:
  569. //
  570. // angle = acos( (a * b) / (|a| * |b|) )
  571. return RAD2DEG( acos( DotProduct( a, b ) / ( alen * blen ) ) );
  572. }
  573. //============================================================
  574. /*
  575. * =================
  576. * SetPlaneSignbits
  577. * =================
  578. */
  579. void SetPlaneSignbits( cplane_t *out )
  580. {
  581. int bits, j;
  582. // for fast box on planeside test
  583. bits = 0;
  584. for ( j = 0; j < 3; j++ )
  585. {
  586. if ( out->normal[ j ] < 0 )
  587. {
  588. bits |= 1 << j;
  589. }
  590. }
  591. out->signbits = bits;
  592. }
  593. /*
  594. * ==================
  595. * BoxOnPlaneSide
  596. *
  597. * Returns 1, 2, or 1 + 2
  598. * ==================
  599. */
  600. int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const cplane_t *p )
  601. {
  602. float dist[ 2 ];
  603. int sides, b, i;
  604. // fast axial cases
  605. if ( p->type < 3 )
  606. {
  607. if ( p->dist <= emins[ p->type ] )
  608. {
  609. return 1;
  610. }
  611. if ( p->dist >= emaxs[ p->type ] )
  612. {
  613. return 2;
  614. }
  615. return 3;
  616. }
  617. // general case
  618. dist[ 0 ] = dist[ 1 ] = 0;
  619. if ( p->signbits < 8 ) // >= 8: default case is original code (dist[0]=dist[1]=0)
  620. {
  621. for ( i = 0; i < 3; i++ )
  622. {
  623. b = ( p->signbits >> i ) & 1;
  624. dist[ b ] += p->normal[ i ] * emaxs[ i ];
  625. dist[ !b ] += p->normal[ i ] * emins[ i ];
  626. }
  627. }
  628. sides = 0;
  629. if ( dist[ 0 ] >= p->dist )
  630. {
  631. sides = 1;
  632. }
  633. if ( dist[ 1 ] < p->dist )
  634. {
  635. sides |= 2;
  636. }
  637. return sides;
  638. }
  639. /*
  640. * =================
  641. * RadiusFromBounds
  642. * =================
  643. */
  644. float RadiusFromBounds( const vec3_t mins, const vec3_t maxs )
  645. {
  646. int i;
  647. vec3_t corner;
  648. float a, b;
  649. for ( i = 0; i < 3; i++ )
  650. {
  651. a = Q_fabs( mins[ i ] );
  652. b = Q_fabs( maxs[ i ] );
  653. corner[ i ] = a > b ? a : b;
  654. }
  655. return VectorLength( corner );
  656. }
  657. void ZeroBounds( vec3_t mins, vec3_t maxs )
  658. {
  659. mins[ 0 ] = mins[ 1 ] = mins[ 2 ] = 0;
  660. maxs[ 0 ] = maxs[ 1 ] = maxs[ 2 ] = 0;
  661. }
  662. void ClearBounds( vec3_t mins, vec3_t maxs )
  663. {
  664. mins[ 0 ] = mins[ 1 ] = mins[ 2 ] = 99999;
  665. maxs[ 0 ] = maxs[ 1 ] = maxs[ 2 ] = -99999;
  666. }
  667. void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs )
  668. {
  669. if ( v[ 0 ] < mins[ 0 ] )
  670. {
  671. mins[ 0 ] = v[ 0 ];
  672. }
  673. if ( v[ 0 ] > maxs[ 0 ] )
  674. {
  675. maxs[ 0 ] = v[ 0 ];
  676. }
  677. if ( v[ 1 ] < mins[ 1 ] )
  678. {
  679. mins[ 1 ] = v[ 1 ];
  680. }
  681. if ( v[ 1 ] > maxs[ 1 ] )
  682. {
  683. maxs[ 1 ] = v[ 1 ];
  684. }
  685. if ( v[ 2 ] < mins[ 2 ] )
  686. {
  687. mins[ 2 ] = v[ 2 ];
  688. }
  689. if ( v[ 2 ] > maxs[ 2 ] )
  690. {
  691. maxs[ 2 ] = v[ 2 ];
  692. }
  693. }
  694. void BoundsAdd( vec3_t mins, vec3_t maxs, const vec3_t mins2, const vec3_t maxs2 )
  695. {
  696. if ( mins2[ 0 ] < mins[ 0 ] )
  697. {
  698. mins[ 0 ] = mins2[ 0 ];
  699. }
  700. if ( mins2[ 1 ] < mins[ 1 ] )
  701. {
  702. mins[ 1 ] = mins2[ 1 ];
  703. }
  704. if ( mins2[ 2 ] < mins[ 2 ] )
  705. {
  706. mins[ 2 ] = mins2[ 2 ];
  707. }
  708. if ( maxs2[ 0 ] > maxs[ 0 ] )
  709. {
  710. maxs[ 0 ] = maxs2[ 0 ];
  711. }
  712. if ( maxs2[ 1 ] > maxs[ 1 ] )
  713. {
  714. maxs[ 1 ] = maxs2[ 1 ];
  715. }
  716. if ( maxs2[ 2 ] > maxs[ 2 ] )
  717. {
  718. maxs[ 2 ] = maxs2[ 2 ];
  719. }
  720. }
  721. bool BoundsIntersect( const vec3_t mins, const vec3_t maxs, const vec3_t mins2, const vec3_t maxs2 )
  722. {
  723. if ( maxs[ 0 ] < mins2[ 0 ] ||
  724. maxs[ 1 ] < mins2[ 1 ] || maxs[ 2 ] < mins2[ 2 ] || mins[ 0 ] > maxs2[ 0 ] || mins[ 1 ] > maxs2[ 1 ] || mins[ 2 ] > maxs2[ 2 ] )
  725. {
  726. return false;
  727. }
  728. return true;
  729. }
  730. bool BoundsIntersectSphere( const vec3_t mins, const vec3_t maxs, const vec3_t origin, vec_t radius )
  731. {
  732. if ( origin[ 0 ] - radius > maxs[ 0 ] ||
  733. origin[ 0 ] + radius < mins[ 0 ] ||
  734. origin[ 1 ] - radius > maxs[ 1 ] ||
  735. origin[ 1 ] + radius < mins[ 1 ] || origin[ 2 ] - radius > maxs[ 2 ] || origin[ 2 ] + radius < mins[ 2 ] )
  736. {
  737. return false;
  738. }
  739. return true;
  740. }
  741. bool BoundsIntersectPoint( const vec3_t mins, const vec3_t maxs, const vec3_t origin )
  742. {
  743. if ( origin[ 0 ] > maxs[ 0 ] ||
  744. origin[ 0 ] < mins[ 0 ] || origin[ 1 ] > maxs[ 1 ] || origin[ 1 ] < mins[ 1 ] || origin[ 2 ] > maxs[ 2 ] || origin[ 2 ] < mins[ 2 ] )
  745. {
  746. return false;
  747. }
  748. return true;
  749. }
  750. float BoundsMaxExtent( const vec3_t mins, const vec3_t maxs ) {
  751. float result = Q_fabs( mins[0] );
  752. result = std::max( result, Q_fabs( mins[ 1 ] ) );
  753. result = std::max( result, Q_fabs( mins[ 2 ] ) );
  754. result = std::max( result, Q_fabs( maxs[ 0 ] ) );
  755. result = std::max( result, Q_fabs( maxs[ 1 ] ) );
  756. result = std::max( result, Q_fabs( maxs[ 2 ] ) );
  757. return result;
  758. }
  759. int VectorCompare( const vec3_t v1, const vec3_t v2 )
  760. {
  761. if ( v1[ 0 ] != v2[ 0 ] || v1[ 1 ] != v2[ 1 ] || v1[ 2 ] != v2[ 2 ] )
  762. {
  763. return 0;
  764. }
  765. return 1;
  766. }
  767. vec_t VectorNormalize( vec3_t v )
  768. {
  769. float length, ilength;
  770. length = DotProduct( v, v );
  771. if ( length != 0.0f )
  772. {
  773. ilength = Q_rsqrt( length );
  774. /* sqrt(length) = length * (1 / sqrt(length)) */
  775. length *= ilength;
  776. VectorScale( v, ilength, v );
  777. }
  778. return length;
  779. }
  780. //
  781. // fast vector normalize routine that does not check to make sure
  782. // that length != 0, nor does it return length
  783. //
  784. void VectorNormalizeFast( vec3_t v )
  785. {
  786. float ilength;
  787. ilength = Q_rsqrt( DotProduct( v, v ) );
  788. VectorScale( v, ilength, v );
  789. }
  790. vec_t VectorNormalize2( const vec3_t v, vec3_t out )
  791. {
  792. float length, ilength;
  793. length = v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ];
  794. if ( length )
  795. {
  796. ilength = Q_rsqrt( length );
  797. /* sqrt(length) = length * (1 / sqrt(length)) */
  798. length *= ilength;
  799. VectorScale( v, ilength, out );
  800. }
  801. else
  802. {
  803. VectorClear( out );
  804. }
  805. return length;
  806. }
  807. void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross )
  808. {
  809. cross[ 0 ] = v1[ 1 ] * v2[ 2 ] - v1[ 2 ] * v2[ 1 ];
  810. cross[ 1 ] = v1[ 2 ] * v2[ 0 ] - v1[ 0 ] * v2[ 2 ];
  811. cross[ 2 ] = v1[ 0 ] * v2[ 1 ] - v1[ 1 ] * v2[ 0 ];
  812. }
  813. vec_t VectorLength( const vec3_t v )
  814. {
  815. return sqrt( v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ] );
  816. }
  817. vec_t VectorLengthSquared( const vec3_t v )
  818. {
  819. return ( v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ] );
  820. }
  821. vec_t Distance( const vec3_t p1, const vec3_t p2 )
  822. {
  823. vec3_t v;
  824. VectorSubtract( p2, p1, v );
  825. return VectorLength( v );
  826. }
  827. vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 )
  828. {
  829. vec3_t v;
  830. VectorSubtract( p2, p1, v );
  831. return v[ 0 ] * v[ 0 ] + v[ 1 ] * v[ 1 ] + v[ 2 ] * v[ 2 ];
  832. }
  833. void VectorInverse( vec3_t v )
  834. {
  835. v[ 0 ] = -v[ 0 ];
  836. v[ 1 ] = -v[ 1 ];
  837. v[ 2 ] = -v[ 2 ];
  838. }
  839. int NearestPowerOfTwo( int val )
  840. {
  841. int answer;
  842. for ( answer = 1; answer < val; answer <<= 1 )
  843. {
  844. ;
  845. }
  846. return answer;
  847. }
  848. /*
  849. * =================
  850. * PlaneTypeForNormal
  851. * =================
  852. */
  853. /*
  854. * int PlaneTypeForNormal (vec3_t normal) {
  855. * if ( normal[0] == 1.0 )
  856. * return PLANE_X;
  857. * if ( normal[1] == 1.0 )
  858. * return PLANE_Y;
  859. * if ( normal[2] == 1.0 )
  860. * return PLANE_Z;
  861. *
  862. * return PLANE_NON_AXIAL;
  863. * }
  864. */
  865. /*
  866. * ================
  867. * AxisMultiply
  868. * ================
  869. */
  870. void AxisMultiply( float in1[ 3 ][ 3 ], float in2[ 3 ][ 3 ], float out[ 3 ][ 3 ] )
  871. {
  872. out[ 0 ][ 0 ] = in1[ 0 ][ 0 ] * in2[ 0 ][ 0 ] + in1[ 0 ][ 1 ] * in2[ 1 ][ 0 ] + in1[ 0 ][ 2 ] * in2[ 2 ][ 0 ];
  873. out[ 0 ][ 1 ] = in1[ 0 ][ 0 ] * in2[ 0 ][ 1 ] + in1[ 0 ][ 1 ] * in2[ 1 ][ 1 ] + in1[ 0 ][ 2 ] * in2[ 2 ][ 1 ];
  874. out[ 0 ][ 2 ] = in1[ 0 ][ 0 ] * in2[ 0 ][ 2 ] + in1[ 0 ][ 1 ] * in2[ 1 ][ 2 ] + in1[ 0 ][ 2 ] * in2[ 2 ][ 2 ];
  875. out[ 1 ][ 0 ] = in1[ 1 ][ 0 ] * in2[ 0 ][ 0 ] + in1[ 1 ][ 1 ] * in2[ 1 ][ 0 ] + in1[ 1 ][ 2 ] * in2[ 2 ][ 0 ];
  876. out[ 1 ][ 1 ] = in1[ 1 ][ 0 ] * in2[ 0 ][ 1 ] + in1[ 1 ][ 1 ] * in2[ 1 ][ 1 ] + in1[ 1 ][ 2 ] * in2[ 2 ][ 1 ];
  877. out[ 1 ][ 2 ] = in1[ 1 ][ 0 ] * in2[ 0 ][ 2 ] + in1[ 1 ][ 1 ] * in2[ 1 ][ 2 ] + in1[ 1 ][ 2 ] * in2[ 2 ][ 2 ];
  878. out[ 2 ][ 0 ] = in1[ 2 ][ 0 ] * in2[ 0 ][ 0 ] + in1[ 2 ][ 1 ] * in2[ 1 ][ 0 ] + in1[ 2 ][ 2 ] * in2[ 2 ][ 0 ];
  879. out[ 2 ][ 1 ] = in1[ 2 ][ 0 ] * in2[ 0 ][ 1 ] + in1[ 2 ][ 1 ] * in2[ 1 ][ 1 ] + in1[ 2 ][ 2 ] * in2[ 2 ][ 1 ];
  880. out[ 2 ][ 2 ] = in1[ 2 ][ 0 ] * in2[ 0 ][ 2 ] + in1[ 2 ][ 1 ] * in2[ 1 ][ 2 ] + in1[ 2 ][ 2 ] * in2[ 2 ][ 2 ];
  881. }
  882. void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up )
  883. {
  884. float angle;
  885. static float sr, sp, sy, cr, cp, cy;
  886. // static to help MS compiler fp bugs
  887. angle = angles[ YAW ] * ( M_PI * 2 / 360 );
  888. sy = sin( angle );
  889. cy = cos( angle );
  890. angle = angles[ PITCH ] * ( M_PI * 2 / 360 );
  891. sp = sin( angle );
  892. cp = cos( angle );
  893. angle = angles[ ROLL ] * ( M_PI * 2 / 360 );
  894. sr = sin( angle );
  895. cr = cos( angle );
  896. if ( forward )
  897. {
  898. forward[ 0 ] = cp * cy;
  899. forward[ 1 ] = cp * sy;
  900. forward[ 2 ] = -sp;
  901. }
  902. if ( right )
  903. {
  904. right[ 0 ] = ( -1 * sr * sp * cy + -1 * cr * -sy );
  905. right[ 1 ] = ( -1 * sr * sp * sy + -1 * cr * cy );
  906. right[ 2 ] = -1 * sr * cp;
  907. }
  908. if ( up )
  909. {
  910. up[ 0 ] = ( cr * sp * cy + -sr * -sy );
  911. up[ 1 ] = ( cr * sp * sy + -sr * cy );
  912. up[ 2 ] = cr * cp;
  913. }
  914. }
  915. /*
  916. * =================
  917. * PerpendicularVector
  918. *
  919. * assumes "src" is normalized
  920. * =================
  921. */
  922. void PerpendicularVector( vec3_t dst, const vec3_t src )
  923. {
  924. int pos;
  925. int i;
  926. float minelem = 1.0F;
  927. vec3_t tempvec;
  928. /*
  929. * * find the smallest magnitude axially aligned vector
  930. */
  931. for ( pos = 0, i = 0; i < 3; i++ )
  932. {
  933. if ( Q_fabs( src[ i ] ) < minelem )
  934. {
  935. pos = i;
  936. minelem = Q_fabs( src[ i ] );
  937. }
  938. }
  939. tempvec[ 0 ] = tempvec[ 1 ] = tempvec[ 2 ] = 0.0F;
  940. tempvec[ pos ] = 1.0F;
  941. /*
  942. * * project the point onto the plane defined by src
  943. */
  944. ProjectPointOnPlane( dst, tempvec, src );
  945. /*
  946. * * normalize the result
  947. */
  948. VectorNormalize( dst );
  949. }
  950. // Ridah
  951. /*
  952. * =================
  953. * GetPerpendicularViewVector
  954. *
  955. * Used to find an "up" vector for drawing a sprite so that it always faces the view as best as possible
  956. * =================
  957. */
  958. void GetPerpendicularViewVector( const vec3_t point, const vec3_t p1, const vec3_t p2, vec3_t up )
  959. {
  960. vec3_t v1, v2;
  961. VectorSubtract( point, p1, v1 );
  962. VectorNormalize( v1 );
  963. VectorSubtract( point, p2, v2 );
  964. VectorNormalize( v2 );
  965. CrossProduct( v1, v2, up );
  966. VectorNormalize( up );
  967. }
  968. /*
  969. * ================
  970. * ProjectPointOntoVector
  971. * ================
  972. */
  973. void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
  974. {
  975. vec3_t pVec, vec;
  976. VectorSubtract( point, vStart, pVec );
  977. VectorSubtract( vEnd, vStart, vec );
  978. VectorNormalize( vec );
  979. // project onto the directional vector for this segment
  980. VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
  981. }
  982. /*
  983. * ================
  984. * DistanceBetweenLineSegmentsSquared
  985. * Return the smallest distance between two line segments, squared
  986. * ================
  987. */
  988. vec_t DistanceBetweenLineSegmentsSquared( const vec3_t sP0, const vec3_t sP1,
  989. const vec3_t tP0, const vec3_t tP1, float *s, float *t )
  990. {
  991. vec3_t sMag, tMag, diff;
  992. float a, b, c, d, e;
  993. float D;
  994. float sN, sD;
  995. float tN, tD;
  996. vec3_t separation;
  997. VectorSubtract( sP1, sP0, sMag );
  998. VectorSubtract( tP1, tP0, tMag );
  999. VectorSubtract( sP0, tP0, diff );
  1000. a = DotProduct( sMag, sMag );
  1001. b = DotProduct( sMag, tMag );
  1002. c = DotProduct( tMag, tMag );
  1003. d = DotProduct( sMag, diff );
  1004. e = DotProduct( tMag, diff );
  1005. sD = tD = D = a * c - b * b;
  1006. if ( D < LINE_DISTANCE_EPSILON )
  1007. {
  1008. // the lines are almost parallel
  1009. sN = 0.0; // force using point P0 on segment S1
  1010. sD = 1.0; // to prevent possible division by 0.0 later
  1011. tN = e;
  1012. tD = c;
  1013. }
  1014. else
  1015. {
  1016. // get the closest points on the infinite lines
  1017. sN = ( b * e - c * d );
  1018. tN = ( a * e - b * d );
  1019. if ( sN < 0.0 )
  1020. {
  1021. // sN < 0 => the s=0 edge is visible
  1022. sN = 0.0;
  1023. tN = e;
  1024. tD = c;
  1025. }
  1026. else if ( sN > sD )
  1027. {
  1028. // sN > sD => the s=1 edge is visible
  1029. sN = sD;
  1030. tN = e + b;
  1031. tD = c;
  1032. }
  1033. }
  1034. if ( tN < 0.0 )
  1035. {
  1036. // tN < 0 => the t=0 edge is visible
  1037. tN = 0.0;
  1038. // recompute sN for this edge
  1039. if ( -d < 0.0 )
  1040. {
  1041. sN = 0.0;
  1042. }
  1043. else if ( -d > a )
  1044. {
  1045. sN = sD;
  1046. }
  1047. else
  1048. {
  1049. sN = -d;
  1050. sD = a;
  1051. }
  1052. }
  1053. else if ( tN > tD )
  1054. {
  1055. // tN > tD => the t=1 edge is visible
  1056. tN = tD;
  1057. // recompute sN for this edge
  1058. if ( ( -d + b ) < 0.0 )
  1059. {
  1060. sN = 0;
  1061. }
  1062. else if ( ( -d + b ) > a )
  1063. {
  1064. sN = sD;
  1065. }
  1066. else
  1067. {
  1068. sN = ( -d + b );
  1069. sD = a;
  1070. }
  1071. }
  1072. // finally do the division to get *s and *t
  1073. *s = ( fabs( sN ) < LINE_DISTANCE_EPSILON ? 0.0 : sN / sD );
  1074. *t = ( fabs( tN ) < LINE_DISTANCE_EPSILON ? 0.0 : tN / tD );
  1075. // get the difference of the two closest points
  1076. VectorScale( sMag, *s, sMag );
  1077. VectorScale( tMag, *t, tMag );
  1078. VectorAdd( diff, sMag, separation );
  1079. VectorSubtract( separation, tMag, separation );
  1080. return VectorLengthSquared( separation );
  1081. }
  1082. /*
  1083. * ================
  1084. * ProjectPointOntoVectorBounded
  1085. * ================
  1086. */
  1087. void ProjectPointOntoVectorBounded( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
  1088. {
  1089. vec3_t pVec, vec;
  1090. int j;
  1091. VectorSubtract( point, vStart, pVec );
  1092. VectorSubtract( vEnd, vStart, vec );
  1093. VectorNormalize( vec );
  1094. // project onto the directional vector for this segment
  1095. VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
  1096. // check bounds
  1097. for ( j = 0; j < 3; j++ )
  1098. {
  1099. if ( ( vProj[ j ] > vStart[ j ] && vProj[ j ] > vEnd[ j ] ) || ( vProj[ j ] < vStart[ j ] && vProj[ j ] < vEnd[ j ] ) )
  1100. {
  1101. break;
  1102. }
  1103. }
  1104. if ( j < 3 )
  1105. {
  1106. if ( Q_fabs( vProj[ j ] - vStart[ j ] ) < Q_fabs( vProj[ j ] - vEnd[ j ] ) )
  1107. {
  1108. VectorCopy( vStart, vProj );
  1109. }
  1110. else
  1111. {
  1112. VectorCopy( vEnd, vProj );
  1113. }
  1114. }
  1115. }
  1116. /*
  1117. * ================
  1118. * DistanceFromLineSquared
  1119. * ================
  1120. */
  1121. float DistanceFromLineSquared( vec3_t p, vec3_t lp1, vec3_t lp2 )
  1122. {
  1123. vec3_t proj, t;
  1124. int j;
  1125. ProjectPointOntoVector( p, lp1, lp2, proj );
  1126. for ( j = 0; j < 3; j++ )
  1127. {
  1128. if ( ( proj[ j ] > lp1[ j ] && proj[ j ] > lp2[ j ] ) || ( proj[ j ] < lp1[ j ] && proj[ j ] < lp2[ j ] ) )
  1129. {
  1130. break;
  1131. }
  1132. }
  1133. if ( j < 3 )
  1134. {
  1135. if ( Q_fabs( proj[ j ] - lp1[ j ] ) < Q_fabs( proj[ j ] - lp2[ j ] ) )
  1136. {
  1137. VectorSubtract( p, lp1, t );
  1138. }
  1139. else
  1140. {
  1141. VectorSubtract( p, lp2, t );
  1142. }
  1143. return VectorLengthSquared( t );
  1144. }
  1145. VectorSubtract( p, proj, t );
  1146. return VectorLengthSquared( t );
  1147. }
  1148. /*
  1149. * =================
  1150. * AxisToAngles
  1151. *
  1152. * Used to convert the MD3 tag axis to MDC tag angles, which are much smaller
  1153. *
  1154. * This doesn't have to be fast, since it's only used for conversion in utils, try to avoid
  1155. * using this during gameplay
  1156. * =================
  1157. */
  1158. void AxisToAngles( /*const*/ vec3_t axis[ 3 ], vec3_t angles )
  1159. {
  1160. float length1;
  1161. float yaw, pitch, roll = 0.0f;
  1162. if ( axis[ 0 ][ 1 ] == 0 && axis[ 0 ][ 0 ] == 0 )
  1163. {
  1164. yaw = 0;
  1165. if ( axis[ 0 ][ 2 ] > 0 )
  1166. {
  1167. pitch = 90;
  1168. }
  1169. else
  1170. {
  1171. pitch = 270;
  1172. }
  1173. }
  1174. else
  1175. {
  1176. if ( axis[ 0 ][ 0 ] )
  1177. {
  1178. yaw = ( atan2( axis[ 0 ][ 1 ], axis[ 0 ][ 0 ] ) * 180 / M_PI );
  1179. }
  1180. else if ( axis[ 0 ][ 1 ] > 0 )
  1181. {
  1182. yaw = 90;
  1183. }
  1184. else
  1185. {
  1186. yaw = 270;
  1187. }
  1188. if ( yaw < 0 )
  1189. {
  1190. yaw += 360;
  1191. }
  1192. length1 = sqrt( axis[ 0 ][ 0 ] * axis[ 0 ][ 0 ] + axis[ 0 ][ 1 ] * axis[ 0 ][ 1 ] );
  1193. pitch = ( atan2( axis[ 0 ][ 2 ], length1 ) * 180 / M_PI );
  1194. if ( pitch < 0 )
  1195. {
  1196. pitch += 360;
  1197. }
  1198. roll = ( atan2( axis[ 1 ][ 2 ], axis[ 2 ][ 2 ] ) * 180 / M_PI );
  1199. if ( roll < 0 )
  1200. {
  1201. roll += 360;
  1202. }
  1203. }
  1204. angles[ PITCH ] = -pitch;
  1205. angles[ YAW ] = yaw;
  1206. angles[ ROLL ] = roll;
  1207. }
  1208. float VectorDistanceSquared( vec3_t v1, vec3_t v2 )
  1209. {
  1210. vec3_t dir;
  1211. VectorSubtract( v2, v1, dir );
  1212. return VectorLengthSquared( dir );
  1213. }
  1214. // done.
  1215. //=============================================
  1216. // RB: XreaL matrix math functions
  1217. // *INDENT-OFF*
  1218. void MatrixIdentity( matrix_t m )
  1219. {
  1220. m[ 0 ] = 1;
  1221. m[ 4 ] = 0;
  1222. m[ 8 ] = 0;
  1223. m[ 12 ] = 0;
  1224. m[ 1 ] = 0;
  1225. m[ 5 ] = 1;
  1226. m[ 9 ] = 0;
  1227. m[ 13 ] = 0;
  1228. m[ 2 ] = 0;
  1229. m[ 6 ] = 0;
  1230. m[ 10 ] = 1;
  1231. m[ 14 ] = 0;
  1232. m[ 3 ] = 0;
  1233. m[ 7 ] = 0;
  1234. m[ 11 ] = 0;
  1235. m[ 15 ] = 1;
  1236. }
  1237. void MatrixClear( matrix_t m )
  1238. {
  1239. m[ 0 ] = 0;
  1240. m[ 4 ] = 0;
  1241. m[ 8 ] = 0;
  1242. m[ 12 ] = 0;
  1243. m[ 1 ] = 0;
  1244. m[ 5 ] = 0;
  1245. m[ 9 ] = 0;
  1246. m[ 13 ] = 0;
  1247. m[ 2 ] = 0;
  1248. m[ 6 ] = 0;
  1249. m[ 10 ] = 0;
  1250. m[ 14 ] = 0;
  1251. m[ 3 ] = 0;
  1252. m[ 7 ] = 0;
  1253. m[ 11 ] = 0;
  1254. m[ 15 ] = 0;
  1255. }
  1256. void MatrixCopy( const matrix_t in, matrix_t out )
  1257. {
  1258. out[ 0 ] = in[ 0 ];
  1259. out[ 4 ] = in[ 4 ];
  1260. out[ 8 ] = in[ 8 ];
  1261. out[ 12 ] = in[ 12 ];
  1262. out[ 1 ] = in[ 1 ];
  1263. out[ 5 ] = in[ 5 ];
  1264. out[ 9 ] = in[ 9 ];
  1265. out[ 13 ] = in[ 13 ];
  1266. out[ 2 ] = in[ 2 ];
  1267. out[ 6 ] = in[ 6 ];
  1268. out[ 10 ] = in[ 10 ];
  1269. out[ 14 ] = in[ 14 ];
  1270. out[ 3 ] = in[ 3 ];
  1271. out[ 7 ] = in[ 7 ];
  1272. out[ 11 ] = in[ 11 ];
  1273. out[ 15 ] = in[ 15 ];
  1274. }
  1275. bool MatrixCompare( const matrix_t a, const matrix_t b )
  1276. {
  1277. return ( a[ 0 ] == b[ 0 ] && a[ 4 ] == b[ 4 ] && a[ 8 ] == b[ 8 ] && a[ 12 ] == b[ 12 ] &&
  1278. a[ 1 ] == b[ 1 ] && a[ 5 ] == b[ 5 ] && a[ 9 ] == b[ 9 ] && a[ 13 ] == b[ 13 ] &&
  1279. a[ 2 ] == b[ 2 ] && a[ 6 ] == b[ 6 ] && a[ 10 ] == b[ 10 ] && a[ 14 ] == b[ 14 ] &&
  1280. a[ 3 ] == b[ 3 ] && a[ 7 ] == b[ 7 ] && a[ 11 ] == b[ 11 ] && a[ 15 ] == b[ 15 ] );
  1281. }
  1282. void MatrixTranspose( const matrix_t in, matrix_t out )
  1283. {
  1284. out[ 0 ] = in[ 0 ];
  1285. out[ 1 ] = in[ 4 ];
  1286. out[ 2 ] = in[ 8 ];
  1287. out[ 3 ] = in[ 12 ];
  1288. out[ 4 ] = in[ 1 ];
  1289. out[ 5 ] = in[ 5 ];
  1290. out[ 6 ] = in[ 9 ];
  1291. out[ 7 ] = in[ 13 ];
  1292. out[ 8 ] = in[ 2 ];
  1293. out[ 9 ] = in[ 6 ];
  1294. out[ 10 ] = in[ 10 ];
  1295. out[ 11 ] = in[ 14 ];
  1296. out[ 12 ] = in[ 3 ];
  1297. out[ 13 ] = in[ 7 ];
  1298. out[ 14 ] = in[ 11 ];
  1299. out[ 15 ] = in[ 15 ];
  1300. }
  1301. // helper functions for MatrixInverse from GtkRadiant C mathlib
  1302. static float m3_det( matrix3x3_t mat )
  1303. {
  1304. float det;
  1305. det = mat[ 0 ] * ( mat[ 4 ] * mat[ 8 ] - mat[ 7 ] * mat[ 5 ] )
  1306. - mat[ 1 ] * ( mat[ 3 ] * mat[ 8 ] - mat[ 6 ] * mat[ 5 ] )
  1307. + mat[ 2 ] * ( mat[ 3 ] * mat[ 7 ] - mat[ 6 ] * mat[ 4 ] );
  1308. return ( det );
  1309. }
  1310. /*static int m3_inverse( matrix3x3_t mr, matrix3x3_t ma )
  1311. * {
  1312. * float det = m3_det( ma );
  1313. *
  1314. * if (det == 0 )
  1315. * {
  1316. * return 1;
  1317. * }
  1318. *
  1319. *
  1320. * mr[0] = ma[4]*ma[8] - ma[5]*ma[7] / det;
  1321. * mr[1] = -( ma[1]*ma[8] - ma[7]*ma[2] ) / det;
  1322. * mr[2] = ma[1]*ma[5] - ma[4]*ma[2] / det;
  1323. *
  1324. * mr[3] = -( ma[3]*ma[8] - ma[5]*ma[6] ) / det;
  1325. * mr[4] = ma[0]*ma[8] - ma[6]*ma[2] / det;
  1326. * mr[5] = -( ma[0]*ma[5] - ma[3]*ma[2] ) / det;
  1327. *
  1328. * mr[6] = ma[3]*ma[7] - ma[6]*ma[4] / det;
  1329. * mr[7] = -( ma[0]*ma[7] - ma[6]*ma[1] ) / det;
  1330. * mr[8] = ma[0]*ma[4] - ma[1]*ma[3] / det;
  1331. *
  1332. * return 0;
  1333. * }*/
  1334. static void m4_submat( matrix_t mr, matrix3x3_t mb, int i, int j )
  1335. {
  1336. int ti, tj, idst = 0, jdst = 0;
  1337. for ( ti = 0; ti < 4; ti++ )
  1338. {
  1339. if ( ti < i )
  1340. {
  1341. idst = ti;
  1342. }
  1343. else if ( ti > i )
  1344. {
  1345. idst = ti - 1;
  1346. }
  1347. for ( tj = 0; tj < 4; tj++ )
  1348. {
  1349. if ( tj < j )
  1350. {
  1351. jdst = tj;
  1352. }
  1353. else if ( tj > j )
  1354. {
  1355. jdst = tj - 1;
  1356. }
  1357. if ( ti != i && tj != j )
  1358. {
  1359. mb[ idst * 3 + jdst ] = mr[ ti * 4 + tj ];
  1360. }
  1361. }
  1362. }
  1363. }
  1364. static float m4_det( matrix_t mr )
  1365. {
  1366. float det, result = 0, i = 1;
  1367. matrix3x3_t msub3;
  1368. int n;
  1369. for ( n = 0; n < 4; n++, i *= -1 )
  1370. {
  1371. m4_submat( mr, msub3, 0, n );
  1372. det = m3_det( msub3 );
  1373. result += mr[ n ] * det * i;
  1374. }
  1375. return result;
  1376. }
  1377. bool MatrixInverse( matrix_t matrix )
  1378. {
  1379. float mdet = m4_det( matrix );
  1380. matrix3x3_t mtemp;
  1381. int i, j, sign;
  1382. matrix_t m4x4_temp;
  1383. #if 0
  1384. if ( fabs( mdet ) < 0.0000000001 )
  1385. {
  1386. return true;
  1387. }
  1388. #endif
  1389. MatrixCopy( matrix, m4x4_temp );
  1390. for ( i = 0; i < 4; i++ )
  1391. {
  1392. for ( j = 0; j < 4; j++ )
  1393. {
  1394. sign = 1 - ( ( i + j ) % 2 ) * 2;
  1395. m4_submat( m4x4_temp, mtemp, i, j );
  1396. // FIXME: try using * inverse det and see if speed/accuracy are good enough
  1397. matrix[ i + j * 4 ] = ( m3_det( mtemp ) * sign ) / mdet;
  1398. }
  1399. }
  1400. return false;
  1401. }
  1402. void MatrixSetupXRotation( matrix_t m, vec_t degrees )
  1403. {
  1404. vec_t a = DEG2RAD( degrees );
  1405. m[ 0 ] = 1;
  1406. m[ 4 ] = 0;
  1407. m[ 8 ] = 0;
  1408. m[ 12 ] = 0;
  1409. m[ 1 ] = 0;
  1410. m[ 5 ] = cos( a );
  1411. m[ 9 ] = -sin( a );
  1412. m[ 13 ] = 0;
  1413. m[ 2 ] = 0;
  1414. m[ 6 ] = sin( a );
  1415. m[ 10 ] = cos( a );
  1416. m[ 14 ] = 0;
  1417. m[ 3 ] = 0;
  1418. m[ 7 ] = 0;
  1419. m[ 11 ] = 0;
  1420. m[ 15 ] = 1;
  1421. }
  1422. void MatrixSetupYRotation( matrix_t m, vec_t degrees )
  1423. {
  1424. vec_t a = DEG2RAD( degrees );
  1425. m[ 0 ] = cos( a );
  1426. m[ 4 ] = 0;
  1427. m[ 8 ] = sin( a );
  1428. m[ 12 ] = 0;
  1429. m[ 1 ] = 0;
  1430. m[ 5 ] = 1;
  1431. m[ 9 ] = 0;
  1432. m[ 13 ] = 0;
  1433. m[ 2 ] = -sin( a );
  1434. m[ 6 ] = 0;
  1435. m[ 10 ] = cos( a );
  1436. m[ 14 ] = 0;
  1437. m[ 3 ] = 0;
  1438. m[ 7 ] = 0;
  1439. m[ 11 ] = 0;
  1440. m[ 15 ] = 1;
  1441. }
  1442. void MatrixSetupZRotation( matrix_t m, vec_t degrees )
  1443. {
  1444. vec_t a = DEG2RAD( degrees );
  1445. m[ 0 ] = cos( a );
  1446. m[ 4 ] = -sin( a );
  1447. m[ 8 ] = 0;
  1448. m[ 12 ] = 0;
  1449. m[ 1 ] = sin( a );
  1450. m[ 5 ] = cos( a );
  1451. m[ 9 ] = 0;
  1452. m[ 13 ] = 0;
  1453. m[ 2 ] = 0;
  1454. m[ 6 ] = 0;
  1455. m[ 10 ] = 1;
  1456. m[ 14 ] = 0;
  1457. m[ 3 ] = 0;
  1458. m[ 7 ] = 0;
  1459. m[ 11 ] = 0;
  1460. m[ 15 ] = 1;
  1461. }
  1462. void MatrixSetupTranslation( matrix_t m, vec_t x, vec_t y, vec_t z )
  1463. {
  1464. m[ 0 ] = 1;
  1465. m[ 4 ] = 0;
  1466. m[ 8 ] = 0;
  1467. m[ 12 ] = x;
  1468. m[ 1 ] = 0;
  1469. m[ 5 ] = 1;
  1470. m[ 9 ] = 0;
  1471. m[ 13 ] = y;
  1472. m[ 2 ] = 0;
  1473. m[ 6 ] = 0;
  1474. m[ 10 ] = 1;
  1475. m[ 14 ] = z;
  1476. m[ 3 ] = 0;
  1477. m[ 7 ] = 0;
  1478. m[ 11 ] = 0;
  1479. m[ 15 ] = 1;
  1480. }
  1481. void MatrixSetupScale( matrix_t m, vec_t x, vec_t y, vec_t z )
  1482. {
  1483. m[ 0 ] = x;
  1484. m[ 4 ] = 0;
  1485. m[ 8 ] = 0;
  1486. m[ 12 ] = 0;
  1487. m[ 1 ] = 0;
  1488. m[ 5 ] = y;
  1489. m[ 9 ] = 0;
  1490. m[ 13 ] = 0;
  1491. m[ 2 ] = 0;
  1492. m[ 6 ] = 0;
  1493. m[ 10 ] = z;
  1494. m[ 14 ] = 0;
  1495. m[ 3 ] = 0;
  1496. m[ 7 ] = 0;
  1497. m[ 11 ] = 0;
  1498. m[ 15 ] = 1;
  1499. }
  1500. void MatrixSetupShear( matrix_t m, vec_t x, vec_t y )
  1501. {
  1502. m[ 0 ] = 1;
  1503. m[ 4 ] = x;
  1504. m[ 8 ] = 0;
  1505. m[ 12 ] = 0;
  1506. m[ 1 ] = y;
  1507. m[ 5 ] = 1;
  1508. m[ 9 ] = 0;
  1509. m[ 13 ] = 0;
  1510. m[ 2 ] = 0;
  1511. m[ 6 ] = 0;
  1512. m[ 10 ] = 1;
  1513. m[ 14 ] = 0;
  1514. m[ 3 ] = 0;
  1515. m[ 7 ] = 0;
  1516. m[ 11 ] = 0;
  1517. m[ 15 ] = 1;
  1518. }
  1519. void MatrixMultiply( const matrix_t a, const matrix_t b, matrix_t out )
  1520. {
  1521. #if idx86_sse
  1522. //#error MatrixMultiply
  1523. int i;
  1524. __m128 _t0, _t1, _t2, _t3, _t4, _t5, _t6, _t7;
  1525. _t4 = _mm_loadu_ps( &a[ 0 ] );
  1526. _t5 = _mm_loadu_ps( &a[ 4 ] );
  1527. _t6 = _mm_loadu_ps( &a[ 8 ] );
  1528. _t7 = _mm_loadu_ps( &a[ 12 ] );
  1529. for ( i = 0; i < 4; i++ )
  1530. {
  1531. _t0 = _mm_load1_ps( &b[ i * 4 + 0 ] );
  1532. _t0 = _mm_mul_ps( _t4, _t0 );
  1533. _t1 = _mm_load1_ps( &b[ i * 4 + 1 ] );
  1534. _t1 = _mm_mul_ps( _t5, _t1 );
  1535. _t2 = _mm_load1_ps( &b[ i * 4 + 2 ] );
  1536. _t2 = _mm_mul_ps( _t6, _t2 );
  1537. _t3 = _mm_load1_ps( &b[ i * 4 + 3 ] );
  1538. _t3 = _mm_mul_ps( _t7, _t3 );
  1539. _t1 = _mm_add_ps( _t0, _t1 );
  1540. _t2 = _mm_add_ps( _t1, _t2 );
  1541. _t3 = _mm_add_ps( _t2, _t3 );
  1542. _mm_storeu_ps( &out[ i * 4 ], _t3 );
  1543. }
  1544. #else
  1545. out[ 0 ] = b[ 0 ] * a[ 0 ] + b[ 1 ] * a[ 4 ] + b[ 2 ] * a[ 8 ] + b[ 3 ] * a[ 12 ];
  1546. out[ 1 ] = b[ 0 ] * a[ 1 ] + b[ 1 ] * a[ 5 ] + b[ 2 ] * a[ 9 ] + b[ 3 ] * a[ 13 ];
  1547. out[ 2 ] = b[ 0 ] * a[ 2 ] + b[ 1 ] * a[ 6 ] + b[ 2 ] * a[ 10 ] + b[ 3 ] * a[ 14 ];
  1548. out[ 3 ] = b[ 0 ] * a[ 3 ] + b[ 1 ] * a[ 7 ] + b[ 2 ] * a[ 11 ] + b[ 3 ] * a[ 15 ];
  1549. out[ 4 ] = b[ 4 ] * a[ 0 ] + b[ 5 ] * a[ 4 ] + b[ 6 ] * a[ 8 ] + b[ 7 ] * a[ 12 ];
  1550. out[ 5 ] = b[ 4 ] * a[ 1 ] + b[ 5 ] * a[ 5 ] + b[ 6 ] * a[ 9 ] + b[ 7 ] * a[ 13 ];
  1551. out[ 6 ] = b[ 4 ] * a[ 2 ] + b[ 5 ] * a[ 6 ] + b[ 6 ] * a[ 10 ] + b[ 7 ] * a[ 14 ];
  1552. out[ 7 ] = b[ 4 ] * a[ 3 ] + b[ 5 ] * a[ 7 ] + b[ 6 ] * a[ 11 ] + b[ 7 ] * a[ 15 ];
  1553. out[ 8 ] = b[ 8 ] * a[ 0 ] + b[ 9 ] * a[ 4 ] + b[ 10 ] * a[ 8 ] + b[ 11 ] * a[ 12 ];
  1554. out[ 9 ] = b[ 8 ] * a[ 1 ] + b[ 9 ] * a[ 5 ] + b[ 10 ] * a[ 9 ] + b[ 11 ] * a[ 13 ];
  1555. out[ 10 ] = b[ 8 ] * a[ 2 ] + b[ 9 ] * a[ 6 ] + b[ 10 ] * a[ 10 ] + b[ 11 ] * a[ 14 ];
  1556. out[ 11 ] = b[ 8 ] * a[ 3 ] + b[ 9 ] * a[ 7 ] + b[ 10 ] * a[ 11 ] + b[ 11 ] * a[ 15 ];
  1557. out[ 12 ] = b[ 12 ] * a[ 0 ] + b[ 13 ] * a[ 4 ] + b[ 14 ] * a[ 8 ] + b[ 15 ] * a[ 12 ];
  1558. out[ 13 ] = b[ 12 ] * a[ 1 ] + b[ 13 ] * a[ 5 ] + b[ 14 ] * a[ 9 ] + b[ 15 ] * a[ 13 ];
  1559. out[ 14 ] = b[ 12 ] * a[ 2 ] + b[ 13 ] * a[ 6 ] + b[ 14 ] * a[ 10 ] + b[ 15 ] * a[ 14 ];
  1560. out[ 15 ] = b[ 12 ] * a[ 3 ] + b[ 13 ] * a[ 7 ] + b[ 14 ] * a[ 11 ] + b[ 15 ] * a[ 15 ];
  1561. #endif
  1562. }
  1563. void MatrixMultiply2( matrix_t m, const matrix_t m2 )
  1564. {
  1565. matrix_t tmp;
  1566. MatrixCopy( m, tmp );
  1567. MatrixMultiply( tmp, m2, m );
  1568. }
  1569. void MatrixMultiplyRotation( matrix_t m, vec_t pitch, vec_t yaw, vec_t roll )
  1570. {
  1571. matrix_t tmp, rot;
  1572. MatrixCopy( m, tmp );
  1573. MatrixFromAngles( rot, pitch, yaw, roll );
  1574. MatrixMultiply( tmp, rot, m );
  1575. }
  1576. void MatrixMultiplyZRotation( matrix_t m, vec_t degrees )
  1577. {
  1578. matrix_t tmp;
  1579. float angle = DEG2RAD( degrees );
  1580. float s = sin( angle );
  1581. float c = cos( angle );
  1582. MatrixCopy( m, tmp );
  1583. m[ 0 ] = tmp[ 0 ] * c + tmp[ 4 ] * s;
  1584. m[ 1 ] = tmp[ 1 ] * c + tmp[ 5 ] * s;
  1585. m[ 2 ] = tmp[ 2 ] * c + tmp[ 6 ] * s;
  1586. m[ 3 ] = tmp[ 3 ] * c + tmp[ 7 ] * s;
  1587. m[ 4 ] = tmp[ 0 ] * -s + tmp[ 4 ] * c;
  1588. m[ 5 ] = tmp[ 1 ] * -s + tmp[ 5 ] * c;
  1589. m[ 6 ] = tmp[ 2 ] * -s + tmp[ 6 ] * c;
  1590. m[ 7 ] = tmp[ 3 ] * -s + tmp[ 7 ] * c;
  1591. }
  1592. void MatrixMultiplyTranslation( matrix_t m, vec_t x, vec_t y, vec_t z )
  1593. {
  1594. m[ 12 ] += m[ 0 ] * x + m[ 4 ] * y + m[ 8 ] * z;
  1595. m[ 13 ] += m[ 1 ] * x + m[ 5 ] * y + m[ 9 ] * z;
  1596. m[ 14 ] += m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z;
  1597. m[ 15 ] += m[ 3 ] * x + m[ 7 ] * y + m[ 11 ] * z;
  1598. }
  1599. void MatrixMultiplyScale( matrix_t m, vec_t x, vec_t y, vec_t z )
  1600. {
  1601. m[ 0 ] *= x;
  1602. m[ 4 ] *= y;
  1603. m[ 8 ] *= z;
  1604. m[ 1 ] *= x;
  1605. m[ 5 ] *= y;
  1606. m[ 9 ] *= z;
  1607. m[ 2 ] *= x;
  1608. m[ 6 ] *= y;
  1609. m[ 10 ] *= z;
  1610. m[ 3 ] *= x;
  1611. m[ 7 ] *= y;
  1612. m[ 11 ] *= z;
  1613. }
  1614. void MatrixMultiplyShear( matrix_t m, vec_t x, vec_t y )
  1615. {
  1616. matrix_t tmp;
  1617. MatrixCopy( m, tmp );
  1618. m[ 0 ] += m[ 4 ] * y;
  1619. m[ 1 ] += m[ 5 ] * y;
  1620. m[ 2 ] += m[ 6 ] * y;
  1621. m[ 3 ] += m[ 7 ] * y;
  1622. m[ 4 ] += tmp[ 0 ] * x;
  1623. m[ 5 ] += tmp[ 1 ] * x;
  1624. m[ 6 ] += tmp[ 2 ] * x;
  1625. m[ 7 ] += tmp[ 3 ] * x;
  1626. }
  1627. void MatrixToAngles( const matrix_t m, vec3_t angles )
  1628. {
  1629. #if 1
  1630. float theta;
  1631. float cp;
  1632. float sp;
  1633. sp = m[ 2 ];
  1634. // cap off our sin value so that we don't get any NANs
  1635. if ( sp > 1.0 )
  1636. {
  1637. sp = 1.0;
  1638. }
  1639. else if ( sp < -1.0 )
  1640. {
  1641. sp = -1.0;
  1642. }
  1643. theta = -asin( sp );
  1644. cp = cos( theta );
  1645. if ( cp > 8192 * FLT_EPSILON )
  1646. {
  1647. angles[ PITCH ] = RAD2DEG( theta );
  1648. angles[ YAW ] = RAD2DEG( atan2( m[ 1 ], m[ 0 ] ) );
  1649. angles[ ROLL ] = RAD2DEG( atan2( m[ 6 ], m[ 10 ] ) );
  1650. }
  1651. else
  1652. {
  1653. angles[ PITCH ] = RAD2DEG( theta );
  1654. angles[ YAW ] = RAD2DEG( -atan2( m[ 4 ], m[ 5 ] ) );
  1655. angles[ ROLL ] = 0;
  1656. }
  1657. #else
  1658. float a;
  1659. float ca;
  1660. a = asin( -m[ 2 ] );
  1661. ca = cos( a );
  1662. if ( fabs( ca ) > 0.005 ) // Gimbal lock?
  1663. {
  1664. angles[ PITCH ] = RAD2DEG( atan2( m[ 6 ] / ca, m[ 10 ] / ca ) );
  1665. angles[ YAW ] = RAD2DEG( a );
  1666. angles[ ROLL ] = RAD2DEG( atan2( m[ 1 ] / ca, m[ 0 ] / ca ) );
  1667. }
  1668. else
  1669. {
  1670. // Gimbal lock has occurred
  1671. angles[ PITCH ] = RAD2DEG( atan2( -m[ 9 ], m[ 5 ] ) );
  1672. angles[ YAW ] = RAD2DEG( a );
  1673. angles[ ROLL ] = 0;
  1674. }
  1675. #endif
  1676. }
  1677. // Tait-Bryan angles z-y-x
  1678. void MatrixFromAngles( matrix_t m, vec_t pitch, vec_t yaw, vec_t roll )
  1679. {
  1680. static float sr, sp, sy, cr, cp, cy;
  1681. // static to help MS compiler fp bugs
  1682. sp = sin( DEG2RAD( pitch ) );
  1683. cp = cos( DEG2RAD( pitch ) );
  1684. sy = sin( DEG2RAD( yaw ) );
  1685. cy = cos( DEG2RAD( yaw ) );
  1686. sr = sin( DEG2RAD( roll ) );
  1687. cr = cos( DEG2RAD( roll ) );
  1688. m[ 0 ] = cp * cy;
  1689. m[ 4 ] = ( sr * sp * cy + cr * -sy );
  1690. m[ 8 ] = ( cr * sp * cy + -sr * -sy );
  1691. m[ 12 ] = 0;
  1692. m[ 1 ] = cp * sy;
  1693. m[ 5 ] = ( sr * sp * sy + cr * cy );
  1694. m[ 9 ] = ( cr * sp * sy + -sr * cy );
  1695. m[ 13 ] = 0;
  1696. m[ 2 ] = -sp;
  1697. m[ 6 ] = sr * cp;
  1698. m[ 10 ] = cr * cp;
  1699. m[ 14 ] = 0;
  1700. m[ 3 ] = 0;
  1701. m[ 7 ] = 0;
  1702. m[ 11 ] = 0;
  1703. m[ 15 ] = 1;
  1704. }
  1705. void MatrixFromVectorsFLU( matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up )
  1706. {
  1707. m[ 0 ] = forward[ 0 ];
  1708. m[ 4 ] = left[ 0 ];
  1709. m[ 8 ] = up[ 0 ];
  1710. m[ 12 ] = 0;
  1711. m[ 1 ] = forward[ 1 ];
  1712. m[ 5 ] = left[ 1 ];
  1713. m[ 9 ] = up[ 1 ];
  1714. m[ 13 ] = 0;
  1715. m[ 2 ] = forward[ 2 ];
  1716. m[ 6 ] = left[ 2 ];
  1717. m[ 10 ] = up[ 2 ];
  1718. m[ 14 ] = 0;
  1719. m[ 3 ] = 0;
  1720. m[ 7 ] = 0;
  1721. m[ 11 ] = 0;
  1722. m[ 15 ] = 1;
  1723. }
  1724. void MatrixFromVectorsFRU( matrix_t m, const vec3_t forward, const vec3_t right, const vec3_t up )
  1725. {
  1726. m[ 0 ] = forward[ 0 ];
  1727. m[ 4 ] = -right[ 0 ];
  1728. m[ 8 ] = up[ 0 ];
  1729. m[ 12 ] = 0;
  1730. m[ 1 ] = forward[ 1 ];
  1731. m[ 5 ] = -right[ 1 ];
  1732. m[ 9 ] = up[ 1 ];
  1733. m[ 13 ] = 0;
  1734. m[ 2 ] = forward[ 2 ];
  1735. m[ 6 ] = -right[ 2 ];
  1736. m[ 10 ] = up[ 2 ];
  1737. m[ 14 ] = 0;
  1738. m[ 3 ] = 0;
  1739. m[ 7 ] = 0;
  1740. m[ 11 ] = 0;
  1741. m[ 15 ] = 1;
  1742. }
  1743. void MatrixFromQuat( matrix_t m, const quat_t q )
  1744. {
  1745. #if 1
  1746. /*
  1747. * From Quaternion to Matrix and Back
  1748. * February 27th 2005
  1749. * J.M.P. van Waveren
  1750. *
  1751. * http://www.intel.com/cd/ids/developer/asmo-na/eng/293748.htm
  1752. */
  1753. float x2, y2, z2 /*, w2*/;
  1754. float yy2, xy2;
  1755. float xz2, yz2, zz2;
  1756. float wz2, wy2, wx2, xx2;
  1757. x2 = q[ 0 ] + q[ 0 ];
  1758. y2 = q[ 1 ] + q[ 1 ];
  1759. z2 = q[ 2 ] + q[ 2 ];
  1760. //w2 = q[3] + q[3]; //Is this used for some underlying optimization?
  1761. yy2 = q[ 1 ] * y2;
  1762. xy2 = q[ 0 ] * y2;
  1763. xz2 = q[ 0 ] * z2;
  1764. yz2 = q[ 1 ] * z2;
  1765. zz2 = q[ 2 ] * z2;
  1766. wz2 = q[ 3 ] * z2;
  1767. wy2 = q[ 3 ] * y2;
  1768. wx2 = q[ 3 ] * x2;
  1769. xx2 = q[ 0 ] * x2;
  1770. m[ 0 ] = -yy2 - zz2 + 1.0f;
  1771. m[ 1 ] = xy2 + wz2;
  1772. m[ 2 ] = xz2 - wy2;
  1773. m[ 4 ] = xy2 - wz2;
  1774. m[ 5 ] = -xx2 - zz2 + 1.0f;
  1775. m[ 6 ] = yz2 + wx2;
  1776. m[ 8 ] = xz2 + wy2;
  1777. m[ 9 ] = yz2 - wx2;
  1778. m[ 10 ] = -xx2 - yy2 + 1.0f;
  1779. m[ 3 ] = m[ 7 ] = m[ 11 ] = m[ 12 ] = m[ 13 ] = m[ 14 ] = 0;
  1780. m[ 15 ] = 1;
  1781. #else
  1782. /*
  1783. * http://www.gamedev.net/reference/articles/article1691.asp#Q54
  1784. * Q54. How do I convert a quaternion to a rotation matrix?
  1785. *
  1786. * Assuming that a quaternion has been created in the form:
  1787. *
  1788. * Q = |X Y Z W|
  1789. *
  1790. * Then the quaternion can then be converted into a 4x4 rotation
  1791. * matrix using the following expression (Warning: you might have to
  1792. * transpose this matrix if you (do not) follow the OpenGL order!):
  1793. *
  1794. * ? 2 2 ?
  1795. * ? 1 - (2Y + 2Z ) 2XY - 2ZW 2XZ + 2YW ?
  1796. * ? ?
  1797. * ? 2 2 ?
  1798. * M = ? 2XY + 2ZW 1 - (2X + 2Z ) 2YZ - 2XW ?
  1799. * ? ?
  1800. * ? 2 2 ?
  1801. * ? 2XZ - 2YW 2YZ + 2XW 1 - (2X + 2Y ) ?
  1802. * ? ?
  1803. */
  1804. // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm
  1805. float xx, xy, xz, xw, yy, yz, yw, zz, zw;
  1806. xx = q[ 0 ] * q[ 0 ];
  1807. xy = q[ 0 ] * q[ 1 ];
  1808. xz = q[ 0 ] * q[ 2 ];
  1809. xw = q[ 0 ] * q[ 3 ];
  1810. yy = q[ 1 ] * q[ 1 ];
  1811. yz = q[ 1 ] * q[ 2 ];
  1812. yw = q[ 1 ] * q[ 3 ];
  1813. zz = q[ 2 ] * q[ 2 ];
  1814. zw = q[ 2 ] * q[ 3 ];
  1815. m[ 0 ] = 1 - 2 * ( yy + zz );
  1816. m[ 1 ] = 2 * ( xy + zw );
  1817. m[ 2 ] = 2 * ( xz - yw );
  1818. m[ 4 ] = 2 * ( xy - zw );
  1819. m[ 5 ] = 1 - 2 * ( xx + zz );
  1820. m[ 6 ] = 2 * ( yz + xw );
  1821. m[ 8 ] = 2 * ( xz + yw );
  1822. m[ 9 ] = 2 * ( yz - xw );
  1823. m[ 10 ] = 1 - 2 * ( xx + yy );
  1824. m[ 3 ] = m[ 7 ] = m[ 11 ] = m[ 12 ] = m[ 13 ] = m[ 14 ] = 0;
  1825. m[ 15 ] = 1;
  1826. #endif
  1827. }
  1828. void MatrixFromPlanes( matrix_t m, const vec4_t left, const vec4_t right, const vec4_t bottom, const vec4_t top, const vec4_t near, const vec4_t far )
  1829. {
  1830. m[ 0 ] = ( right[ 0 ] - left[ 0 ] ) / 2;
  1831. m[ 1 ] = ( top[ 0 ] - bottom[ 0 ] ) / 2;
  1832. m[ 2 ] = ( far[ 0 ] - near[ 0 ] ) / 2;
  1833. m[ 3 ] = right[ 0 ] - ( right[ 0 ] - left[ 0 ] ) / 2;
  1834. m[ 4 ] = ( right[ 1 ] - left[ 1 ] ) / 2;
  1835. m[ 5 ] = ( top[ 1 ] - bottom[ 1 ] ) / 2;
  1836. m[ 6 ] = ( far[ 1 ] - near[ 1 ] ) / 2;
  1837. m[ 7 ] = right[ 1 ] - ( right[ 1 ] - left[ 1 ] ) / 2;
  1838. m[ 8 ] = ( right[ 2 ] - left[ 2 ] ) / 2;
  1839. m[ 9 ] = ( top[ 2 ] - bottom[ 2 ] ) / 2;
  1840. m[ 10 ] = ( far[ 2 ] - near[ 2 ] ) / 2;
  1841. m[ 11 ] = right[ 2 ] - ( right[ 2 ] - left[ 2 ] ) / 2;
  1842. #if 0
  1843. m[ 12 ] = ( right[ 3 ] - left[ 3 ] ) / 2;
  1844. m[ 13 ] = ( top[ 3 ] - bottom[ 3 ] ) / 2;
  1845. m[ 14 ] = ( far[ 3 ] - near[ 3 ] ) / 2;
  1846. m[ 15 ] = right[ 3 ] - ( right[ 3 ] - left[ 3 ] ) / 2;
  1847. #else
  1848. m[ 12 ] = ( -right[ 3 ] - -left[ 3 ] ) / 2;
  1849. m[ 13 ] = ( -top[ 3 ] - -bottom[ 3 ] ) / 2;
  1850. m[ 14 ] = ( -far[ 3 ] - -near[ 3 ] ) / 2;
  1851. m[ 15 ] = -right[ 3 ] - ( -right[ 3 ] - -left[ 3 ] ) / 2;
  1852. #endif
  1853. }
  1854. void MatrixToVectorsFLU( const matrix_t m, vec3_t forward, vec3_t left, vec3_t up )
  1855. {
  1856. if ( forward )
  1857. {
  1858. forward[ 0 ] = m[ 0 ]; // cp*cy;
  1859. forward[ 1 ] = m[ 1 ]; // cp*sy;
  1860. forward[ 2 ] = m[ 2 ]; //-sp;
  1861. }
  1862. if ( left )
  1863. {
  1864. left[ 0 ] = m[ 4 ]; // sr*sp*cy+cr*-sy;
  1865. left[ 1 ] = m[ 5 ]; // sr*sp*sy+cr*cy;
  1866. left[ 2 ] = m[ 6 ]; // sr*cp;
  1867. }
  1868. if ( up )
  1869. {
  1870. up[ 0 ] = m[ 8 ]; // cr*sp*cy+-sr*-sy;
  1871. up[ 1 ] = m[ 9 ]; // cr*sp*sy+-sr*cy;
  1872. up[ 2 ] = m[ 10 ]; // cr*cp;
  1873. }
  1874. }
  1875. void MatrixToVectorsFRU( const matrix_t m, vec3_t forward, vec3_t right, vec3_t up )
  1876. {
  1877. if ( forward )
  1878. {
  1879. forward[ 0 ] = m[ 0 ];
  1880. forward[ 1 ] = m[ 1 ];
  1881. forward[ 2 ] = m[ 2 ];
  1882. }
  1883. if ( right )
  1884. {
  1885. right[ 0 ] = -m[ 4 ];
  1886. right[ 1 ] = -m[ 5 ];
  1887. right[ 2 ] = -m[ 6 ];
  1888. }
  1889. if ( up )
  1890. {
  1891. up[ 0 ] = m[ 8 ];
  1892. up[ 1 ] = m[ 9 ];
  1893. up[ 2 ] = m[ 10 ];
  1894. }
  1895. }
  1896. void MatrixSetupTransformFromVectorsFLU( matrix_t m, const vec3_t forward, const vec3_t left, const vec3_t up

Large files files are truncated, but you can click here to view the full file