PageRenderTime 29ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/game/q_math.c

https://bitbucket.org/bshaw/jk3game_sdk_mingw
C | 1700 lines | 977 code | 241 blank | 482 comment | 95 complexity | 0edfba73745e9826dbef6378c7103a87 MD5 | raw file
  1. // Copyright (C) 1999-2000 Id Software, Inc.
  2. //
  3. // q_math.c -- stateless support routines that are included in each code module
  4. #include "q_shared.h"
  5. vec3_t vec3_origin = {0,0,0};
  6. vec3_t axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
  7. vec4_t colorBlack = {0, 0, 0, 1};
  8. vec4_t colorRed = {1, 0, 0, 1};
  9. vec4_t colorGreen = {0, 1, 0, 1};
  10. vec4_t colorBlue = {0, 0, 1, 1};
  11. vec4_t colorYellow = {1, 1, 0, 1};
  12. vec4_t colorMagenta= {1, 0, 1, 1};
  13. vec4_t colorCyan = {0, 1, 1, 1};
  14. vec4_t colorWhite = {1, 1, 1, 1};
  15. vec4_t colorLtGrey = {0.75, 0.75, 0.75, 1};
  16. vec4_t colorMdGrey = {0.5, 0.5, 0.5, 1};
  17. vec4_t colorDkGrey = {0.25, 0.25, 0.25, 1};
  18. vec4_t colorLtBlue = {0.367f, 0.261f, 0.722f, 1};
  19. vec4_t colorDkBlue = {0.199f, 0.0f, 0.398f, 1};
  20. vec4_t g_color_table[8] =
  21. {
  22. {0.0, 0.0, 0.0, 1.0},
  23. {1.0, 0.0, 0.0, 1.0},
  24. {0.0, 1.0, 0.0, 1.0},
  25. {1.0, 1.0, 0.0, 1.0},
  26. {0.0, 0.0, 1.0, 1.0},
  27. {0.0, 1.0, 1.0, 1.0},
  28. {1.0, 0.0, 1.0, 1.0},
  29. {1.0, 1.0, 1.0, 1.0},
  30. };
  31. vec3_t bytedirs[NUMVERTEXNORMALS] =
  32. {
  33. {-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f},
  34. {-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f},
  35. {-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f},
  36. {0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f},
  37. {0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f},
  38. {0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f},
  39. {0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f},
  40. {0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f},
  41. {-0.809017f, 0.309017f, 0.500000f},{-0.587785f, 0.425325f, 0.688191f},
  42. {-0.850651f, 0.525731f, 0.000000f},{-0.864188f, 0.442863f, 0.238856f},
  43. {-0.716567f, 0.681718f, 0.147621f},{-0.688191f, 0.587785f, 0.425325f},
  44. {-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f},
  45. {-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f},
  46. {-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f},
  47. {0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f},
  48. {0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f},
  49. {0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f},
  50. {-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f},
  51. {0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f},
  52. {0.238856f, 0.864188f, -0.442863f},{0.262866f, 0.951056f, -0.162460f},
  53. {0.500000f, 0.809017f, -0.309017f},{0.850651f, 0.525731f, 0.000000f},
  54. {0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f},
  55. {0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f},
  56. {0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f},
  57. {0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f},
  58. {0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f},
  59. {1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f},
  60. {0.850651f, -0.525731f, 0.000000f},{0.955423f, -0.295242f, 0.000000f},
  61. {0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f},
  62. {0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f},
  63. {0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f},
  64. {0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f},
  65. {0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f},
  66. {0.681718f, -0.147621f, -0.716567f},{0.850651f, 0.000000f, -0.525731f},
  67. {0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f},
  68. {0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f},
  69. {0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f},
  70. {0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f},
  71. {0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f},
  72. {-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f},
  73. {-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f},
  74. {-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f},
  75. {0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f},
  76. {0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f},
  77. {-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f},
  78. {0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f},
  79. {0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f},
  80. {0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f},
  81. {0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f},
  82. {0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f},
  83. {0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f},
  84. {0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f},
  85. {0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f},
  86. {0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f},
  87. {0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f},
  88. {0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f},
  89. {0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f},
  90. {-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f},
  91. {-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f},
  92. {-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f},
  93. {-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f},
  94. {-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f},
  95. {-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f},
  96. {-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f},
  97. {-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f},
  98. {-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f},
  99. {-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f},
  100. {0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f},
  101. {0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f},
  102. {0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f},
  103. {0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f},
  104. {-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f},
  105. {-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f},
  106. {-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f},
  107. {-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f},
  108. {-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f},
  109. {-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f},
  110. {-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f},
  111. {-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f},
  112. {-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f},
  113. {-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f}
  114. };
  115. //==============================================================
  116. int Q_rand( int *seed ) {
  117. *seed = (69069 * *seed + 1);
  118. return *seed;
  119. }
  120. float Q_random( int *seed ) {
  121. return ( Q_rand( seed ) & 0xffff ) / (float)0x10000;
  122. }
  123. float Q_crandom( int *seed ) {
  124. return 2.0 * ( Q_random( seed ) - 0.5 );
  125. }
  126. #ifdef __LCC__
  127. int VectorCompare( const vec3_t v1, const vec3_t v2 ) {
  128. if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) {
  129. return 0;
  130. }
  131. return 1;
  132. }
  133. vec_t VectorLength( const vec3_t v ) {
  134. return (vec_t)sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  135. }
  136. vec_t VectorLengthSquared( const vec3_t v ) {
  137. return (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  138. }
  139. vec_t Distance( const vec3_t p1, const vec3_t p2 ) {
  140. vec3_t v;
  141. VectorSubtract (p2, p1, v);
  142. return VectorLength( v );
  143. }
  144. vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 ) {
  145. vec3_t v;
  146. VectorSubtract (p2, p1, v);
  147. return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  148. }
  149. // fast vector normalize routine that does not check to make sure
  150. // that length != 0, nor does it return length, uses rsqrt approximation
  151. void VectorNormalizeFast( vec3_t v )
  152. {
  153. float ilength;
  154. ilength = Q_rsqrt( DotProduct( v, v ) );
  155. v[0] *= ilength;
  156. v[1] *= ilength;
  157. v[2] *= ilength;
  158. }
  159. void VectorInverse( vec3_t v ){
  160. v[0] = -v[0];
  161. v[1] = -v[1];
  162. v[2] = -v[2];
  163. }
  164. //i wrote this function in a console test app and it appeared faster
  165. //in debug and release than the standard crossproduct asm generated
  166. //by the compiler. however, when inlining the crossproduct function
  167. //the compiler performs further optimizations and generally ends up
  168. //being faster than this asm version. but feel free to try this one
  169. //and see if you're heavily crossproducting in an area and looking
  170. //for a way to optimize. -rww
  171. #if 0
  172. void CrossProductA (float *v1, float *v2, float *cross)
  173. {
  174. #if 1
  175. static float scratch1, scratch2, scratch3, scratch4, scratch5, scratch6;
  176. __asm mov eax,v1
  177. __asm mov ecx,v2
  178. __asm mov edx,cross
  179. __asm fld dword ptr[eax+4]
  180. __asm fmul dword ptr[ecx+8]
  181. __asm fstp scratch1
  182. __asm fld dword ptr[eax+8]
  183. __asm fmul dword ptr[ecx+4]
  184. __asm fstp scratch2
  185. __asm fld dword ptr[eax+8]
  186. __asm fmul dword ptr[ecx]
  187. __asm fstp scratch3
  188. __asm fld dword ptr[eax]
  189. __asm fmul dword ptr[ecx+8]
  190. __asm fstp scratch4
  191. __asm fld dword ptr[eax]
  192. __asm fmul dword ptr[ecx+4]
  193. __asm fstp scratch5
  194. __asm fld dword ptr[eax+4]
  195. __asm fmul dword ptr[ecx]
  196. __asm fstp scratch6
  197. __asm fld scratch1
  198. __asm fsub scratch2
  199. __asm fstp dword ptr[edx]
  200. __asm fld scratch3
  201. __asm fsub scratch4
  202. __asm fstp dword ptr[edx+4]
  203. __asm fld scratch5
  204. __asm fsub scratch6
  205. __asm fstp dword ptr[edx+8]
  206. #else //doesn't require use of statics, but not nearly as fast.
  207. __asm mov eax,v1
  208. __asm mov ecx,v2
  209. __asm mov edx,cross
  210. __asm fld dword ptr[eax+4]
  211. __asm fmul dword ptr[ecx+8]
  212. __asm fld dword ptr[eax+8]
  213. __asm fmul dword ptr[ecx+4]
  214. __asm fsubp st(1),st
  215. __asm fstp dword ptr[edx]
  216. __asm fld dword ptr[eax+8]
  217. __asm fmul dword ptr[ecx]
  218. __asm fld dword ptr[eax]
  219. __asm fmul dword ptr[ecx+8]
  220. __asm fsubp st(1),st
  221. __asm fstp dword ptr[edx+4]
  222. __asm fld dword ptr[eax]
  223. __asm fmul dword ptr[ecx+4]
  224. __asm fld dword ptr[eax+4]
  225. __asm fmul dword ptr[ecx]
  226. __asm fsubp st(1),st
  227. __asm fstp dword ptr[edx+8]
  228. #endif
  229. }
  230. #endif
  231. void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ) {
  232. cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
  233. cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
  234. cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
  235. }
  236. #endif
  237. //=======================================================
  238. signed char ClampChar( int i ) {
  239. if ( i < -128 ) {
  240. return -128;
  241. }
  242. if ( i > 127 ) {
  243. return 127;
  244. }
  245. return i;
  246. }
  247. signed short ClampShort( int i ) {
  248. if ( i < -32768 ) {
  249. return -32768;
  250. }
  251. if ( i > 0x7fff ) {
  252. return 0x7fff;
  253. }
  254. return i;
  255. }
  256. // this isn't a real cheap function to call!
  257. int DirToByte( vec3_t dir ) {
  258. int i, best;
  259. float d, bestd;
  260. if ( !dir ) {
  261. return 0;
  262. }
  263. bestd = 0;
  264. best = 0;
  265. for (i=0 ; i<NUMVERTEXNORMALS ; i++)
  266. {
  267. d = DotProduct (dir, bytedirs[i]);
  268. if (d > bestd)
  269. {
  270. bestd = d;
  271. best = i;
  272. }
  273. }
  274. return best;
  275. }
  276. void ByteToDir( int b, vec3_t dir ) {
  277. if ( b < 0 || b >= NUMVERTEXNORMALS ) {
  278. VectorCopy( vec3_origin, dir );
  279. return;
  280. }
  281. VectorCopy (bytedirs[b], dir);
  282. }
  283. unsigned ColorBytes3 (float r, float g, float b) {
  284. unsigned i;
  285. ( (byte *)&i )[0] = r * 255;
  286. ( (byte *)&i )[1] = g * 255;
  287. ( (byte *)&i )[2] = b * 255;
  288. return i;
  289. }
  290. unsigned ColorBytes4 (float r, float g, float b, float a) {
  291. unsigned i;
  292. ( (byte *)&i )[0] = r * 255;
  293. ( (byte *)&i )[1] = g * 255;
  294. ( (byte *)&i )[2] = b * 255;
  295. ( (byte *)&i )[3] = a * 255;
  296. return i;
  297. }
  298. float NormalizeColor( const vec3_t in, vec3_t out ) {
  299. float max;
  300. max = in[0];
  301. if ( in[1] > max ) {
  302. max = in[1];
  303. }
  304. if ( in[2] > max ) {
  305. max = in[2];
  306. }
  307. if ( !max ) {
  308. VectorClear( out );
  309. } else {
  310. out[0] = in[0] / max;
  311. out[1] = in[1] / max;
  312. out[2] = in[2] / max;
  313. }
  314. return max;
  315. }
  316. /*
  317. =====================
  318. PlaneFromPoints
  319. Returns false if the triangle is degenrate.
  320. The normal will point out of the clock for clockwise ordered points
  321. =====================
  322. */
  323. qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
  324. vec3_t d1, d2;
  325. VectorSubtract( b, a, d1 );
  326. VectorSubtract( c, a, d2 );
  327. CrossProduct( d2, d1, plane );
  328. if ( VectorNormalize( plane ) == 0 ) {
  329. return qfalse;
  330. }
  331. plane[3] = DotProduct( a, plane );
  332. return qtrue;
  333. }
  334. /*
  335. ===============
  336. RotatePointAroundVector
  337. This is not implemented very well...
  338. ===============
  339. */
  340. void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
  341. float degrees ) {
  342. float m[3][3];
  343. float im[3][3];
  344. float zrot[3][3];
  345. float tmpmat[3][3];
  346. float rot[3][3];
  347. int i;
  348. vec3_t vr, vup, vf;
  349. float rad;
  350. vf[0] = dir[0];
  351. vf[1] = dir[1];
  352. vf[2] = dir[2];
  353. PerpendicularVector( vr, dir );
  354. CrossProduct( vr, vf, vup );
  355. m[0][0] = vr[0];
  356. m[1][0] = vr[1];
  357. m[2][0] = vr[2];
  358. m[0][1] = vup[0];
  359. m[1][1] = vup[1];
  360. m[2][1] = vup[2];
  361. m[0][2] = vf[0];
  362. m[1][2] = vf[1];
  363. m[2][2] = vf[2];
  364. memcpy( im, m, sizeof( im ) );
  365. im[0][1] = m[1][0];
  366. im[0][2] = m[2][0];
  367. im[1][0] = m[0][1];
  368. im[1][2] = m[2][1];
  369. im[2][0] = m[0][2];
  370. im[2][1] = m[1][2];
  371. memset( zrot, 0, sizeof( zrot ) );
  372. zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
  373. rad = DEG2RAD( degrees );
  374. zrot[0][0] = cos( rad );
  375. zrot[0][1] = sin( rad );
  376. zrot[1][0] = -sin( rad );
  377. zrot[1][1] = cos( rad );
  378. MatrixMultiply( m, zrot, tmpmat );
  379. MatrixMultiply( tmpmat, im, rot );
  380. for ( i = 0; i < 3; i++ ) {
  381. dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
  382. }
  383. }
  384. /*
  385. ===============
  386. RotateAroundDirection
  387. ===============
  388. */
  389. void RotateAroundDirection( vec3_t axis[3], float yaw ) {
  390. // create an arbitrary axis[1]
  391. PerpendicularVector( axis[1], axis[0] );
  392. // rotate it around axis[0] by yaw
  393. if ( yaw ) {
  394. vec3_t temp;
  395. VectorCopy( axis[1], temp );
  396. RotatePointAroundVector( axis[1], axis[0], temp, yaw );
  397. }
  398. // cross to get axis[2]
  399. CrossProduct( axis[0], axis[1], axis[2] );
  400. }
  401. void vectoangles( const vec3_t value1, vec3_t angles ) {
  402. float forward;
  403. float yaw, pitch;
  404. if ( value1[1] == 0 && value1[0] == 0 ) {
  405. yaw = 0;
  406. if ( value1[2] > 0 ) {
  407. pitch = 90;
  408. }
  409. else {
  410. pitch = 270;
  411. }
  412. }
  413. else {
  414. if ( value1[0] ) {
  415. yaw = ( atan2 ( value1[1], value1[0] ) * 180 / M_PI );
  416. }
  417. else if ( value1[1] > 0 ) {
  418. yaw = 90;
  419. }
  420. else {
  421. yaw = 270;
  422. }
  423. if ( yaw < 0 ) {
  424. yaw += 360;
  425. }
  426. forward = sqrt ( value1[0]*value1[0] + value1[1]*value1[1] );
  427. pitch = ( atan2(value1[2], forward) * 180 / M_PI );
  428. if ( pitch < 0 ) {
  429. pitch += 360;
  430. }
  431. }
  432. angles[PITCH] = -pitch;
  433. angles[YAW] = yaw;
  434. angles[ROLL] = 0;
  435. }
  436. /*
  437. =================
  438. AnglesToAxis
  439. =================
  440. */
  441. void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) {
  442. vec3_t right;
  443. // angle vectors returns "right" instead of "y axis"
  444. AngleVectors( angles, axis[0], right, axis[2] );
  445. VectorSubtract( vec3_origin, right, axis[1] );
  446. }
  447. void AxisClear( vec3_t axis[3] ) {
  448. axis[0][0] = 1;
  449. axis[0][1] = 0;
  450. axis[0][2] = 0;
  451. axis[1][0] = 0;
  452. axis[1][1] = 1;
  453. axis[1][2] = 0;
  454. axis[2][0] = 0;
  455. axis[2][1] = 0;
  456. axis[2][2] = 1;
  457. }
  458. void AxisCopy( vec3_t in[3], vec3_t out[3] ) {
  459. VectorCopy( in[0], out[0] );
  460. VectorCopy( in[1], out[1] );
  461. VectorCopy( in[2], out[2] );
  462. }
  463. void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
  464. {
  465. float d;
  466. vec3_t n;
  467. float inv_denom;
  468. inv_denom = DotProduct( normal, normal );
  469. #ifndef Q3_VM
  470. assert( Q_fabs(inv_denom) != 0.0f ); // bk010122 - zero vectors get here
  471. #endif
  472. inv_denom = 1.0f / inv_denom;
  473. d = DotProduct( normal, p ) * inv_denom;
  474. n[0] = normal[0] * inv_denom;
  475. n[1] = normal[1] * inv_denom;
  476. n[2] = normal[2] * inv_denom;
  477. dst[0] = p[0] - d * n[0];
  478. dst[1] = p[1] - d * n[1];
  479. dst[2] = p[2] - d * n[2];
  480. }
  481. /*
  482. ================
  483. MakeNormalVectors
  484. Given a normalized forward vector, create two
  485. other perpendicular vectors
  486. ================
  487. */
  488. void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up) {
  489. float d;
  490. // this rotate and negate guarantees a vector
  491. // not colinear with the original
  492. right[1] = -forward[0];
  493. right[2] = forward[1];
  494. right[0] = forward[2];
  495. d = DotProduct (right, forward);
  496. VectorMA (right, -d, forward, right);
  497. VectorNormalize (right);
  498. CrossProduct (right, forward, up);
  499. }
  500. void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out )
  501. {
  502. out[0] = DotProduct( in, matrix[0] );
  503. out[1] = DotProduct( in, matrix[1] );
  504. out[2] = DotProduct( in, matrix[2] );
  505. }
  506. //============================================================================
  507. #if !idppc
  508. /*
  509. ** float q_rsqrt( float number )
  510. */
  511. float Q_rsqrt( float number )
  512. {
  513. long i;
  514. float x2, y;
  515. const float threehalfs = 1.5F;
  516. x2 = number * 0.5F;
  517. y = number;
  518. i = * ( long * ) &y; // evil floating point bit level hacking
  519. i = 0x5f3759df - ( i >> 1 ); // what the fuck?
  520. y = * ( float * ) &i;
  521. y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  522. // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
  523. #ifndef Q3_VM
  524. #ifdef __linux__
  525. assert( !isnan(y) ); // bk010122 - FPE?
  526. #endif
  527. #endif
  528. return y;
  529. }
  530. float Q_fabs( float f ) {
  531. int tmp = * ( int * ) &f;
  532. tmp &= 0x7FFFFFFF;
  533. return * ( float * ) &tmp;
  534. }
  535. #endif
  536. //============================================================
  537. /*
  538. ===============
  539. LerpAngle
  540. ===============
  541. */
  542. float LerpAngle (float from, float to, float frac) {
  543. float a;
  544. if ( to - from > 180 ) {
  545. to -= 360;
  546. }
  547. if ( to - from < -180 ) {
  548. to += 360;
  549. }
  550. a = from + frac * (to - from);
  551. return a;
  552. }
  553. /*
  554. =================
  555. AngleSubtract
  556. Always returns a value from -180 to 180
  557. =================
  558. */
  559. float AngleSubtract( float a1, float a2 ) {
  560. float a;
  561. a = a1 - a2;
  562. a=fmod(a,360);//chop it down quickly, then level it out
  563. while ( a > 180 ) {
  564. a -= 360;
  565. }
  566. while ( a < -180 ) {
  567. a += 360;
  568. }
  569. return a;
  570. }
  571. void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ) {
  572. v3[0] = AngleSubtract( v1[0], v2[0] );
  573. v3[1] = AngleSubtract( v1[1], v2[1] );
  574. v3[2] = AngleSubtract( v1[2], v2[2] );
  575. }
  576. float AngleMod(float a) {
  577. a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
  578. return a;
  579. }
  580. /*
  581. =================
  582. AngleNormalize360
  583. returns angle normalized to the range [0 <= angle < 360]
  584. =================
  585. */
  586. float AngleNormalize360 ( float angle ) {
  587. return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535);
  588. }
  589. /*
  590. =================
  591. AngleNormalize180
  592. returns angle normalized to the range [-180 < angle <= 180]
  593. =================
  594. */
  595. float AngleNormalize180 ( float angle ) {
  596. angle = AngleNormalize360( angle );
  597. if ( angle > 180.0 ) {
  598. angle -= 360.0;
  599. }
  600. return angle;
  601. }
  602. /*
  603. =================
  604. AngleDelta
  605. returns the normalized delta from angle1 to angle2
  606. =================
  607. */
  608. float AngleDelta ( float angle1, float angle2 ) {
  609. return AngleNormalize180( angle1 - angle2 );
  610. }
  611. //============================================================
  612. /*
  613. =================
  614. SetPlaneSignbits
  615. =================
  616. */
  617. void SetPlaneSignbits (cplane_t *out) {
  618. int bits, j;
  619. // for fast box on planeside test
  620. bits = 0;
  621. for (j=0 ; j<3 ; j++) {
  622. if (out->normal[j] < 0) {
  623. bits |= 1<<j;
  624. }
  625. }
  626. out->signbits = bits;
  627. }
  628. /*
  629. ==================
  630. BoxOnPlaneSide
  631. Returns 1, 2, or 1 + 2
  632. // this is the slow, general version
  633. int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  634. {
  635. int i;
  636. float dist1, dist2;
  637. int sides;
  638. vec3_t corners[2];
  639. for (i=0 ; i<3 ; i++)
  640. {
  641. if (p->normal[i] < 0)
  642. {
  643. corners[0][i] = emins[i];
  644. corners[1][i] = emaxs[i];
  645. }
  646. else
  647. {
  648. corners[1][i] = emins[i];
  649. corners[0][i] = emaxs[i];
  650. }
  651. }
  652. dist1 = DotProduct (p->normal, corners[0]) - p->dist;
  653. dist2 = DotProduct (p->normal, corners[1]) - p->dist;
  654. sides = 0;
  655. if (dist1 >= 0)
  656. sides = 1;
  657. if (dist2 < 0)
  658. sides |= 2;
  659. return sides;
  660. }
  661. ==================
  662. */
  663. #if !( (defined __linux__ || __FreeBSD__) && (defined __i386__) && (!defined C_ONLY)) // rb010123
  664. #if defined __LCC__ || defined C_ONLY || !id386
  665. int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  666. {
  667. float dist1, dist2;
  668. int sides;
  669. // fast axial cases
  670. if (p->type < 3)
  671. {
  672. if (p->dist <= emins[p->type])
  673. return 1;
  674. if (p->dist >= emaxs[p->type])
  675. return 2;
  676. return 3;
  677. }
  678. // general case
  679. switch (p->signbits)
  680. {
  681. case 0:
  682. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  683. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  684. break;
  685. case 1:
  686. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  687. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  688. break;
  689. case 2:
  690. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  691. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  692. break;
  693. case 3:
  694. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  695. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  696. break;
  697. case 4:
  698. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  699. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  700. break;
  701. case 5:
  702. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  703. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  704. break;
  705. case 6:
  706. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  707. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  708. break;
  709. case 7:
  710. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  711. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  712. break;
  713. default:
  714. dist1 = dist2 = 0; // shut up compiler
  715. break;
  716. }
  717. sides = 0;
  718. if (dist1 >= p->dist)
  719. sides = 1;
  720. if (dist2 < p->dist)
  721. sides |= 2;
  722. return sides;
  723. }
  724. #else
  725. #pragma warning( disable: 4035 )
  726. int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  727. {
  728. int i;
  729. float dist1, dist2;
  730. int sides;
  731. vec3_t corners[2];
  732. for (i=0 ; i<3 ; i++)
  733. {
  734. if (p->normal[i] < 0)
  735. {
  736. corners[0][i] = emins[i];
  737. corners[1][i] = emaxs[i];
  738. }
  739. else
  740. {
  741. corners[1][i] = emins[i];
  742. corners[0][i] = emaxs[i];
  743. }
  744. }
  745. dist1 = DotProduct (p->normal, corners[0]) - p->dist;
  746. dist2 = DotProduct (p->normal, corners[1]) - p->dist;
  747. sides = 0;
  748. if (dist1 >= 0)
  749. sides = 1;
  750. if (dist2 < 0)
  751. sides |= 2;
  752. return sides;
  753. }
  754. //__declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
  755. //{
  756. // static int bops_initialized;
  757. // static int Ljmptab[8];
  758. //
  759. // __asm {
  760. //
  761. // push ebx
  762. //
  763. // cmp bops_initialized, 1
  764. // je initialized
  765. // mov bops_initialized, 1
  766. //
  767. // mov Ljmptab[0*4], offset Lcase0
  768. // mov Ljmptab[1*4], offset Lcase1
  769. // mov Ljmptab[2*4], offset Lcase2
  770. // mov Ljmptab[3*4], offset Lcase3
  771. // mov Ljmptab[4*4], offset Lcase4
  772. // mov Ljmptab[5*4], offset Lcase5
  773. // mov Ljmptab[6*4], offset Lcase6
  774. // mov Ljmptab[7*4], offset Lcase7
  775. //
  776. //initialized:
  777. //
  778. // mov edx,dword ptr[4+12+esp]
  779. // mov ecx,dword ptr[4+4+esp]
  780. // xor eax,eax
  781. // mov ebx,dword ptr[4+8+esp]
  782. // mov al,byte ptr[17+edx]
  783. // cmp al,8
  784. // jge Lerror
  785. // fld dword ptr[0+edx]
  786. // fld st(0)
  787. // jmp dword ptr[Ljmptab+eax*4]
  788. //Lcase0:
  789. // fmul dword ptr[ebx]
  790. // fld dword ptr[0+4+edx]
  791. // fxch st(2)
  792. // fmul dword ptr[ecx]
  793. // fxch st(2)
  794. // fld st(0)
  795. // fmul dword ptr[4+ebx]
  796. // fld dword ptr[0+8+edx]
  797. // fxch st(2)
  798. // fmul dword ptr[4+ecx]
  799. // fxch st(2)
  800. // fld st(0)
  801. // fmul dword ptr[8+ebx]
  802. // fxch st(5)
  803. // faddp st(3),st(0)
  804. // fmul dword ptr[8+ecx]
  805. // fxch st(1)
  806. // faddp st(3),st(0)
  807. // fxch st(3)
  808. // faddp st(2),st(0)
  809. // jmp LSetSides
  810. //Lcase1:
  811. // fmul dword ptr[ecx]
  812. // fld dword ptr[0+4+edx]
  813. // fxch st(2)
  814. // fmul dword ptr[ebx]
  815. // fxch st(2)
  816. // fld st(0)
  817. // fmul dword ptr[4+ebx]
  818. // fld dword ptr[0+8+edx]
  819. // fxch st(2)
  820. // fmul dword ptr[4+ecx]
  821. // fxch st(2)
  822. // fld st(0)
  823. // fmul dword ptr[8+ebx]
  824. // fxch st(5)
  825. // faddp st(3),st(0)
  826. // fmul dword ptr[8+ecx]
  827. // fxch st(1)
  828. // faddp st(3),st(0)
  829. // fxch st(3)
  830. // faddp st(2),st(0)
  831. // jmp LSetSides
  832. //Lcase2:
  833. // fmul dword ptr[ebx]
  834. // fld dword ptr[0+4+edx]
  835. // fxch st(2)
  836. // fmul dword ptr[ecx]
  837. // fxch st(2)
  838. // fld st(0)
  839. // fmul dword ptr[4+ecx]
  840. // fld dword ptr[0+8+edx]
  841. // fxch st(2)
  842. // fmul dword ptr[4+ebx]
  843. // fxch st(2)
  844. // fld st(0)
  845. // fmul dword ptr[8+ebx]
  846. // fxch st(5)
  847. // faddp st(3),st(0)
  848. // fmul dword ptr[8+ecx]
  849. // fxch st(1)
  850. // faddp st(3),st(0)
  851. // fxch st(3)
  852. // faddp st(2),st(0)
  853. // jmp LSetSides
  854. //Lcase3:
  855. // fmul dword ptr[ecx]
  856. // fld dword ptr[0+4+edx]
  857. // fxch st(2)
  858. // fmul dword ptr[ebx]
  859. // fxch st(2)
  860. // fld st(0)
  861. // fmul dword ptr[4+ecx]
  862. // fld dword ptr[0+8+edx]
  863. // fxch st(2)
  864. // fmul dword ptr[4+ebx]
  865. // fxch st(2)
  866. // fld st(0)
  867. // fmul dword ptr[8+ebx]
  868. // fxch st(5)
  869. // faddp st(3),st(0)
  870. // fmul dword ptr[8+ecx]
  871. // fxch st(1)
  872. // faddp st(3),st(0)
  873. // fxch st(3)
  874. // faddp st(2),st(0)
  875. // jmp LSetSides
  876. //Lcase4:
  877. // fmul dword ptr[ebx]
  878. // fld dword ptr[0+4+edx]
  879. // fxch st(2)
  880. // fmul dword ptr[ecx]
  881. // fxch st(2)
  882. // fld st(0)
  883. // fmul dword ptr[4+ebx]
  884. // fld dword ptr[0+8+edx]
  885. // fxch st(2)
  886. // fmul dword ptr[4+ecx]
  887. // fxch st(2)
  888. // fld st(0)
  889. // fmul dword ptr[8+ecx]
  890. // fxch st(5)
  891. // faddp st(3),st(0)
  892. // fmul dword ptr[8+ebx]
  893. // fxch st(1)
  894. // faddp st(3),st(0)
  895. // fxch st(3)
  896. // faddp st(2),st(0)
  897. // jmp LSetSides
  898. //Lcase5:
  899. // fmul dword ptr[ecx]
  900. // fld dword ptr[0+4+edx]
  901. // fxch st(2)
  902. // fmul dword ptr[ebx]
  903. // fxch st(2)
  904. // fld st(0)
  905. // fmul dword ptr[4+ebx]
  906. // fld dword ptr[0+8+edx]
  907. // fxch st(2)
  908. // fmul dword ptr[4+ecx]
  909. // fxch st(2)
  910. // fld st(0)
  911. // fmul dword ptr[8+ecx]
  912. // fxch st(5)
  913. // faddp st(3),st(0)
  914. // fmul dword ptr[8+ebx]
  915. // fxch st(1)
  916. // faddp st(3),st(0)
  917. // fxch st(3)
  918. // faddp st(2),st(0)
  919. // jmp LSetSides
  920. //Lcase6:
  921. // fmul dword ptr[ebx]
  922. // fld dword ptr[0+4+edx]
  923. // fxch st(2)
  924. // fmul dword ptr[ecx]
  925. // fxch st(2)
  926. // fld st(0)
  927. // fmul dword ptr[4+ecx]
  928. // fld dword ptr[0+8+edx]
  929. // fxch st(2)
  930. // fmul dword ptr[4+ebx]
  931. // fxch st(2)
  932. // fld st(0)
  933. // fmul dword ptr[8+ecx]
  934. // fxch st(5)
  935. // faddp st(3),st(0)
  936. // fmul dword ptr[8+ebx]
  937. // fxch st(1)
  938. // faddp st(3),st(0)
  939. // fxch st(3)
  940. // faddp st(2),st(0)
  941. // jmp LSetSides
  942. //Lcase7:
  943. // fmul dword ptr[ecx]
  944. // fld dword ptr[0+4+edx]
  945. // fxch st(2)
  946. // fmul dword ptr[ebx]
  947. // fxch st(2)
  948. // fld st(0)
  949. // fmul dword ptr[4+ecx]
  950. // fld dword ptr[0+8+edx]
  951. // fxch st(2)
  952. // fmul dword ptr[4+ebx]
  953. // fxch st(2)
  954. // fld st(0)
  955. // fmul dword ptr[8+ecx]
  956. // fxch st(5)
  957. // faddp st(3),st(0)
  958. // fmul dword ptr[8+ebx]
  959. // fxch st(1)
  960. // faddp st(3),st(0)
  961. // fxch st(3)
  962. // faddp st(2),st(0)
  963. //LSetSides:
  964. // faddp st(2),st(0)
  965. // fcomp dword ptr[12+edx]
  966. // xor ecx,ecx
  967. // fnstsw ax
  968. // fcomp dword ptr[12+edx]
  969. // and ah,1
  970. // xor ah,1
  971. // add cl,ah
  972. // fnstsw ax
  973. // and ah,1
  974. // add ah,ah
  975. // add cl,ah
  976. // pop ebx
  977. // mov eax,ecx
  978. // ret
  979. //Lerror:
  980. // int 3
  981. // }
  982. //}
  983. #pragma warning( default: 4035 )
  984. #endif
  985. #endif
  986. /*
  987. =================
  988. RadiusFromBounds
  989. =================
  990. */
  991. float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
  992. int i;
  993. vec3_t corner;
  994. float a, b;
  995. for (i=0 ; i<3 ; i++) {
  996. a = fabs( mins[i] );
  997. b = fabs( maxs[i] );
  998. corner[i] = a > b ? a : b;
  999. }
  1000. return VectorLength (corner);
  1001. }
  1002. void ClearBounds( vec3_t mins, vec3_t maxs ) {
  1003. mins[0] = mins[1] = mins[2] = 99999;
  1004. maxs[0] = maxs[1] = maxs[2] = -99999;
  1005. }
  1006. vec_t DistanceHorizontal( const vec3_t p1, const vec3_t p2 ) {
  1007. vec3_t v;
  1008. VectorSubtract( p2, p1, v );
  1009. return sqrt( v[0]*v[0] + v[1]*v[1] ); //Leave off the z component
  1010. }
  1011. vec_t DistanceHorizontalSquared( const vec3_t p1, const vec3_t p2 ) {
  1012. vec3_t v;
  1013. VectorSubtract( p2, p1, v );
  1014. return v[0]*v[0] + v[1]*v[1]; //Leave off the z component
  1015. }
  1016. void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) {
  1017. if ( v[0] < mins[0] ) {
  1018. mins[0] = v[0];
  1019. }
  1020. if ( v[0] > maxs[0]) {
  1021. maxs[0] = v[0];
  1022. }
  1023. if ( v[1] < mins[1] ) {
  1024. mins[1] = v[1];
  1025. }
  1026. if ( v[1] > maxs[1]) {
  1027. maxs[1] = v[1];
  1028. }
  1029. if ( v[2] < mins[2] ) {
  1030. mins[2] = v[2];
  1031. }
  1032. if ( v[2] > maxs[2]) {
  1033. maxs[2] = v[2];
  1034. }
  1035. }
  1036. vec_t VectorNormalize( vec3_t v ) {
  1037. float length, ilength;
  1038. length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  1039. length = sqrt (length);
  1040. if ( length ) {
  1041. ilength = 1/length;
  1042. v[0] *= ilength;
  1043. v[1] *= ilength;
  1044. v[2] *= ilength;
  1045. }
  1046. return length;
  1047. }
  1048. vec_t VectorNormalize2( const vec3_t v, vec3_t out) {
  1049. float length, ilength;
  1050. length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  1051. length = sqrt (length);
  1052. if (length)
  1053. {
  1054. #ifndef Q3_VM // bk0101022 - FPE related
  1055. // assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) );
  1056. #endif
  1057. ilength = 1/length;
  1058. out[0] = v[0]*ilength;
  1059. out[1] = v[1]*ilength;
  1060. out[2] = v[2]*ilength;
  1061. } else {
  1062. #ifndef Q3_VM // bk0101022 - FPE related
  1063. // assert( ((Q_fabs(v[0])==0.0f) && (Q_fabs(v[1])==0.0f) && (Q_fabs(v[2])==0.0f)) );
  1064. #endif
  1065. VectorClear( out );
  1066. }
  1067. return length;
  1068. }
  1069. void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) {
  1070. vecc[0] = veca[0] + scale*vecb[0];
  1071. vecc[1] = veca[1] + scale*vecb[1];
  1072. vecc[2] = veca[2] + scale*vecb[2];
  1073. }
  1074. vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ) {
  1075. return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
  1076. }
  1077. void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
  1078. out[0] = veca[0]-vecb[0];
  1079. out[1] = veca[1]-vecb[1];
  1080. out[2] = veca[2]-vecb[2];
  1081. }
  1082. void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
  1083. out[0] = veca[0]+vecb[0];
  1084. out[1] = veca[1]+vecb[1];
  1085. out[2] = veca[2]+vecb[2];
  1086. }
  1087. void _VectorCopy( const vec3_t in, vec3_t out ) {
  1088. out[0] = in[0];
  1089. out[1] = in[1];
  1090. out[2] = in[2];
  1091. }
  1092. void _VectorScale( const vec3_t in, vec_t scale, vec3_t out ) {
  1093. out[0] = in[0]*scale;
  1094. out[1] = in[1]*scale;
  1095. out[2] = in[2]*scale;
  1096. }
  1097. void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ) {
  1098. out[0] = in[0]*scale;
  1099. out[1] = in[1]*scale;
  1100. out[2] = in[2]*scale;
  1101. out[3] = in[3]*scale;
  1102. }
  1103. int Q_log2( int val ) {
  1104. int answer;
  1105. answer = 0;
  1106. while ( ( val>>=1 ) != 0 ) {
  1107. answer++;
  1108. }
  1109. return answer;
  1110. }
  1111. /*
  1112. =================
  1113. PlaneTypeForNormal
  1114. =================
  1115. */
  1116. /*
  1117. int PlaneTypeForNormal (vec3_t normal) {
  1118. if ( normal[0] == 1.0 )
  1119. return PLANE_X;
  1120. if ( normal[1] == 1.0 )
  1121. return PLANE_Y;
  1122. if ( normal[2] == 1.0 )
  1123. return PLANE_Z;
  1124. return PLANE_NON_AXIAL;
  1125. }
  1126. */
  1127. /*
  1128. ================
  1129. MatrixMultiply
  1130. ================
  1131. */
  1132. void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
  1133. out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
  1134. in1[0][2] * in2[2][0];
  1135. out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
  1136. in1[0][2] * in2[2][1];
  1137. out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
  1138. in1[0][2] * in2[2][2];
  1139. out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
  1140. in1[1][2] * in2[2][0];
  1141. out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
  1142. in1[1][2] * in2[2][1];
  1143. out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
  1144. in1[1][2] * in2[2][2];
  1145. out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
  1146. in1[2][2] * in2[2][0];
  1147. out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
  1148. in1[2][2] * in2[2][1];
  1149. out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
  1150. in1[2][2] * in2[2][2];
  1151. }
  1152. void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
  1153. float angle;
  1154. static float sr, sp, sy, cr, cp, cy;
  1155. // static to help MS compiler fp bugs
  1156. angle = angles[YAW] * (M_PI*2 / 360);
  1157. sy = sin(angle);
  1158. cy = cos(angle);
  1159. angle = angles[PITCH] * (M_PI*2 / 360);
  1160. sp = sin(angle);
  1161. cp = cos(angle);
  1162. angle = angles[ROLL] * (M_PI*2 / 360);
  1163. sr = sin(angle);
  1164. cr = cos(angle);
  1165. if (forward)
  1166. {
  1167. forward[0] = cp*cy;
  1168. forward[1] = cp*sy;
  1169. forward[2] = -sp;
  1170. }
  1171. if (right)
  1172. {
  1173. right[0] = (-1*sr*sp*cy+-1*cr*-sy);
  1174. right[1] = (-1*sr*sp*sy+-1*cr*cy);
  1175. right[2] = -1*sr*cp;
  1176. }
  1177. if (up)
  1178. {
  1179. up[0] = (cr*sp*cy+-sr*-sy);
  1180. up[1] = (cr*sp*sy+-sr*cy);
  1181. up[2] = cr*cp;
  1182. }
  1183. }
  1184. /*
  1185. ** assumes "src" is normalized
  1186. */
  1187. void PerpendicularVector( vec3_t dst, const vec3_t src )
  1188. {
  1189. int pos;
  1190. int i;
  1191. float minelem = 1.0F;
  1192. vec3_t tempvec;
  1193. /*
  1194. ** find the smallest magnitude axially aligned vector
  1195. */
  1196. for ( pos = 0, i = 0; i < 3; i++ )
  1197. {
  1198. if ( fabs( src[i] ) < minelem )
  1199. {
  1200. pos = i;
  1201. minelem = fabs( src[i] );
  1202. }
  1203. }
  1204. tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
  1205. tempvec[pos] = 1.0F;
  1206. /*
  1207. ** project the point onto the plane defined by src
  1208. */
  1209. ProjectPointOnPlane( dst, tempvec, src );
  1210. /*
  1211. ** normalize the result
  1212. */
  1213. VectorNormalize( dst );
  1214. }
  1215. /*
  1216. ** NormalToLatLong
  1217. **
  1218. ** We use two byte encoded normals in some space critical applications.
  1219. ** Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format
  1220. ** Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
  1221. **
  1222. */
  1223. //rwwRMG - added
  1224. void NormalToLatLong( const vec3_t normal, byte bytes[2] )
  1225. {
  1226. // check for singularities
  1227. if (!normal[0] && !normal[1])
  1228. {
  1229. if ( normal[2] > 0.0f )
  1230. {
  1231. bytes[0] = 0;
  1232. bytes[1] = 0; // lat = 0, long = 0
  1233. }
  1234. else
  1235. {
  1236. bytes[0] = 128;
  1237. bytes[1] = 0; // lat = 0, long = 128
  1238. }
  1239. }
  1240. else
  1241. {
  1242. int a, b;
  1243. a = (int)(RAD2DEG( (vec_t)atan2( normal[1], normal[0] ) ) * (255.0f / 360.0f ));
  1244. a &= 0xff;
  1245. b = (int)(RAD2DEG( (vec_t)acos( normal[2] ) ) * ( 255.0f / 360.0f ));
  1246. b &= 0xff;
  1247. bytes[0] = b; // longitude
  1248. bytes[1] = a; // lattitude
  1249. }
  1250. }
  1251. // This is the VC libc version of rand() without multiple seeds per thread or 12 levels
  1252. // of subroutine calls.
  1253. // Both calls have been designed to minimise the inherent number of float <--> int
  1254. // conversions and the additional math required to get the desired value.
  1255. // eg the typical tint = (rand() * 255) / 32768
  1256. // becomes tint = irand(0, 255)
  1257. static unsigned long holdrand = 0x89abcdef;
  1258. void Rand_Init(int seed)
  1259. {
  1260. holdrand = seed;
  1261. }
  1262. // Returns a float min <= x < max (exclusive; will get max - 0.00001; but never max)
  1263. float flrand(float min, float max)
  1264. {
  1265. float result;
  1266. holdrand = (holdrand * 214013L) + 2531011L;
  1267. result = (float)(holdrand >> 17); // 0 - 32767 range
  1268. result = ((result * (max - min)) / 32768.0F) + min;
  1269. return(result);
  1270. }
  1271. float Q_flrand(float min, float max)
  1272. {
  1273. return flrand(min,max);
  1274. }
  1275. // Returns an integer min <= x <= max (ie inclusive)
  1276. int irand(int min, int max)
  1277. {
  1278. int result;
  1279. assert((max - min) < 32768);
  1280. max++;
  1281. holdrand = (holdrand * 214013L) + 2531011L;
  1282. result = holdrand >> 17;
  1283. result = ((result * (max - min)) >> 15) + min;
  1284. return(result);
  1285. }
  1286. int Q_irand(int value1, int value2)
  1287. {
  1288. return irand(value1, value2);
  1289. }
  1290. /*float powf ( float x, int y )
  1291. {
  1292. float r = x;
  1293. for ( y--; y>0; y-- )
  1294. r = r * r;
  1295. return r;
  1296. }*/
  1297. #ifdef Q3_VM
  1298. //rwwRMG - needed for HandleEntityAdjustment
  1299. double fmod( double x, double y )
  1300. {
  1301. int result;
  1302. if (y == 0.0)
  1303. {
  1304. return 0.0;
  1305. }
  1306. result = x / y;
  1307. return x - (result * y);
  1308. }
  1309. #endif // Q3_VM
  1310. /*
  1311. -------------------------
  1312. DotProductNormalize
  1313. -------------------------
  1314. */
  1315. float DotProductNormalize( const vec3_t inVec1, const vec3_t inVec2 )
  1316. {
  1317. vec3_t v1, v2;
  1318. VectorNormalize2( inVec1, v1 );
  1319. VectorNormalize2( inVec2, v2 );
  1320. return DotProduct(v1, v2);
  1321. }
  1322. /*
  1323. -------------------------
  1324. G_FindClosestPointOnLineSegment
  1325. -------------------------
  1326. */
  1327. qboolean G_FindClosestPointOnLineSegment( const vec3_t start, const vec3_t end, const vec3_t from, vec3_t result )
  1328. {
  1329. vec3_t vecStart2From, vecStart2End, vecEnd2Start, vecEnd2From;
  1330. float distEnd2From, distEnd2Result, theta, cos_theta, dot;
  1331. //Find the perpendicular vector to vec from start to end
  1332. VectorSubtract( from, start, vecStart2From);
  1333. VectorSubtract( end, start, vecStart2End);
  1334. dot = DotProductNormalize( vecStart2From, vecStart2End );
  1335. if ( dot <= 0 )
  1336. {
  1337. //The perpendicular would be beyond or through the start point
  1338. VectorCopy( start, result );
  1339. return qfalse;
  1340. }
  1341. if ( dot == 1 )
  1342. {
  1343. //parallel, closer of 2 points will be the target
  1344. if( (VectorLengthSquared( vecStart2From )) < (VectorLengthSquared( vecStart2End )) )
  1345. {
  1346. VectorCopy( from, result );
  1347. }
  1348. else
  1349. {
  1350. VectorCopy( end, result );
  1351. }
  1352. return qfalse;
  1353. }
  1354. //Try other end
  1355. VectorSubtract( from, end, vecEnd2From);
  1356. VectorSubtract( start, end, vecEnd2Start);
  1357. dot = DotProductNormalize( vecEnd2From, vecEnd2Start );
  1358. if ( dot <= 0 )
  1359. {//The perpendicular would be beyond or through the start point
  1360. VectorCopy( end, result );
  1361. return qfalse;
  1362. }
  1363. if ( dot == 1 )
  1364. {//parallel, closer of 2 points will be the target
  1365. if( (VectorLengthSquared( vecEnd2From )) < (VectorLengthSquared( vecEnd2Start )))
  1366. {
  1367. VectorCopy( from, result );
  1368. }
  1369. else
  1370. {
  1371. VectorCopy( end, result );
  1372. }
  1373. return qfalse;
  1374. }
  1375. // /|
  1376. // c / |
  1377. // / |a
  1378. // theta /)__|
  1379. // b
  1380. //cos(theta) = b / c
  1381. //solve for b
  1382. //b = cos(theta) * c
  1383. //angle between vecs end2from and end2start, should be between 0 and 90
  1384. theta = 90 * (1 - dot);//theta
  1385. //Get length of side from End2Result using sine of theta
  1386. distEnd2From = VectorLength( vecEnd2From );//c
  1387. cos_theta = cos(DEG2RAD(theta));//cos(theta)
  1388. distEnd2Result = cos_theta * distEnd2From;//b
  1389. //Extrapolate to find result
  1390. VectorNormalize( vecEnd2Start );
  1391. VectorMA( end, distEnd2Result, vecEnd2Start, result );
  1392. //perpendicular intersection is between the 2 endpoints
  1393. return qtrue;
  1394. }
  1395. float G_PointDistFromLineSegment( const vec3_t start, const vec3_t end, const vec3_t from )
  1396. {
  1397. vec3_t vecStart2From, vecStart2End, vecEnd2Start, vecEnd2From, intersection;
  1398. float distEnd2From, distStart2From, distEnd2Result, theta, cos_theta, dot;
  1399. //Find the perpendicular vector to vec from start to end
  1400. VectorSubtract( from, start, vecStart2From);
  1401. VectorSubtract( end, start, vecStart2End);
  1402. VectorSubtract( from, end, vecEnd2From);
  1403. VectorSubtract( start, end, vecEnd2Start);
  1404. dot = DotProductNormalize( vecStart2From, vecStart2End );
  1405. distStart2From = Distance( start, from );
  1406. distEnd2From = Distance( end, from );
  1407. if ( dot <= 0 )
  1408. {
  1409. //The perpendicular would be beyond or through the start point
  1410. return distStart2From;
  1411. }
  1412. if ( dot == 1 )
  1413. {
  1414. //parallel, closer of 2 points will be the target
  1415. return ((distStart2From<distEnd2From)?distStart2From:distEnd2From);
  1416. }
  1417. //Try other end
  1418. dot = DotProductNormalize( vecEnd2From, vecEnd2Start );
  1419. if ( dot <= 0 )
  1420. {//The perpendicular would be beyond or through the end point
  1421. return distEnd2From;
  1422. }
  1423. if ( dot == 1 )
  1424. {//parallel, closer of 2 points will be the target
  1425. return ((distStart2From<distEnd2From)?distStart2From:distEnd2From);
  1426. }
  1427. // /|
  1428. // c / |
  1429. // / |a
  1430. // theta /)__|
  1431. // b
  1432. //cos(theta) = b / c
  1433. //solve for b
  1434. //b = cos(theta) * c
  1435. //angle between vecs end2from and end2start, should be between 0 and 90
  1436. theta = 90 * (1 - dot);//theta
  1437. //Get length of side from End2Result using sine of theta
  1438. cos_theta = cos(DEG2RAD(theta));//cos(theta)
  1439. distEnd2Result = cos_theta * distEnd2From;//b
  1440. //Extrapolate to find result
  1441. VectorNormalize( vecEnd2Start );
  1442. VectorMA( end, distEnd2Result, vecEnd2Start, intersection );
  1443. //perpendicular intersection is between the 2 endpoints, return dist to it from from
  1444. return Distance( intersection, from );
  1445. }