mathlib.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // mathlib.c -- math primitives
  16. #include <math.h>
  17. #include "quakedef.h"
  18. void Sys_Error (char *error, ...);
  19. vec3_t vec3_origin = {0,0,0};
  20. int nanmask = 255<<23;
  21. /*-----------------------------------------------------------------*/
  22. #define DEG2RAD( a ) ( a * M_PI ) / 180.0F
  23. void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
  24. {
  25. float d;
  26. vec3_t n;
  27. float inv_denom;
  28. inv_denom = 1.0F / DotProduct( normal, normal );
  29. d = DotProduct( normal, p ) * inv_denom;
  30. n[0] = normal[0] * inv_denom;
  31. n[1] = normal[1] * inv_denom;
  32. n[2] = normal[2] * inv_denom;
  33. dst[0] = p[0] - d * n[0];
  34. dst[1] = p[1] - d * n[1];
  35. dst[2] = p[2] - d * n[2];
  36. }
  37. /*
  38. ** assumes "src" is normalized
  39. */
  40. void PerpendicularVector( vec3_t dst, const vec3_t src )
  41. {
  42. int pos;
  43. int i;
  44. float minelem = 1.0F;
  45. vec3_t tempvec;
  46. /*
  47. ** find the smallest magnitude axially aligned vector
  48. */
  49. for ( pos = 0, i = 0; i < 3; i++ )
  50. {
  51. if ( fabs( src[i] ) < minelem )
  52. {
  53. pos = i;
  54. minelem = fabs( src[i] );
  55. }
  56. }
  57. tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
  58. tempvec[pos] = 1.0F;
  59. /*
  60. ** project the point onto the plane defined by src
  61. */
  62. ProjectPointOnPlane( dst, tempvec, src );
  63. /*
  64. ** normalize the result
  65. */
  66. VectorNormalize( dst );
  67. }
  68. #ifdef _WIN32
  69. #pragma optimize( "", off )
  70. #endif
  71. void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
  72. {
  73. float m[3][3];
  74. float im[3][3];
  75. float zrot[3][3];
  76. float tmpmat[3][3];
  77. float rot[3][3];
  78. int i;
  79. vec3_t vr, vup, vf;
  80. vf[0] = dir[0];
  81. vf[1] = dir[1];
  82. vf[2] = dir[2];
  83. PerpendicularVector( vr, dir );
  84. CrossProduct( vr, vf, vup );
  85. m[0][0] = vr[0];
  86. m[1][0] = vr[1];
  87. m[2][0] = vr[2];
  88. m[0][1] = vup[0];
  89. m[1][1] = vup[1];
  90. m[2][1] = vup[2];
  91. m[0][2] = vf[0];
  92. m[1][2] = vf[1];
  93. m[2][2] = vf[2];
  94. memcpy( im, m, sizeof( im ) );
  95. im[0][1] = m[1][0];
  96. im[0][2] = m[2][0];
  97. im[1][0] = m[0][1];
  98. im[1][2] = m[2][1];
  99. im[2][0] = m[0][2];
  100. im[2][1] = m[1][2];
  101. memset( zrot, 0, sizeof( zrot ) );
  102. zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
  103. zrot[0][0] = cos( DEG2RAD( degrees ) );
  104. zrot[0][1] = sin( DEG2RAD( degrees ) );
  105. zrot[1][0] = -sin( DEG2RAD( degrees ) );
  106. zrot[1][1] = cos( DEG2RAD( degrees ) );
  107. R_ConcatRotations( m, zrot, tmpmat );
  108. R_ConcatRotations( tmpmat, im, rot );
  109. for ( i = 0; i < 3; i++ )
  110. {
  111. dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
  112. }
  113. }
  114. #ifdef _WIN32
  115. #pragma optimize( "", on )
  116. #endif
  117. /*-----------------------------------------------------------------*/
  118. float anglemod(float a)
  119. {
  120. #if 0
  121. if (a >= 0)
  122. a -= 360*(int)(a/360);
  123. else
  124. a += 360*( 1 + (int)(-a/360) );
  125. #endif
  126. a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
  127. return a;
  128. }
  129. /*
  130. ==================
  131. BOPS_Error
  132. Split out like this for ASM to call.
  133. ==================
  134. */
  135. void BOPS_Error (void)
  136. {
  137. Sys_Error ("BoxOnPlaneSide: Bad signbits");
  138. }
  139. #if !id386
  140. /*
  141. ==================
  142. BoxOnPlaneSide
  143. Returns 1, 2, or 1 + 2
  144. ==================
  145. */
  146. int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p)
  147. {
  148. float dist1, dist2;
  149. int sides;
  150. #if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this
  151. // function
  152. // fast axial cases
  153. if (p->type < 3)
  154. {
  155. if (p->dist <= emins[p->type])
  156. return 1;
  157. if (p->dist >= emaxs[p->type])
  158. return 2;
  159. return 3;
  160. }
  161. #endif
  162. // general case
  163. switch (p->signbits)
  164. {
  165. case 0:
  166. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  167. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  168. break;
  169. case 1:
  170. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  171. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  172. break;
  173. case 2:
  174. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  175. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  176. break;
  177. case 3:
  178. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  179. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  180. break;
  181. case 4:
  182. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  183. dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  184. break;
  185. case 5:
  186. dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
  187. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
  188. break;
  189. case 6:
  190. dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  191. dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  192. break;
  193. case 7:
  194. dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
  195. dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
  196. break;
  197. default:
  198. dist1 = dist2 = 0; // shut up compiler
  199. BOPS_Error ();
  200. break;
  201. }
  202. #if 0
  203. int i;
  204. vec3_t corners[2];
  205. for (i=0 ; i<3 ; i++)
  206. {
  207. if (plane->normal[i] < 0)
  208. {
  209. corners[0][i] = emins[i];
  210. corners[1][i] = emaxs[i];
  211. }
  212. else
  213. {
  214. corners[1][i] = emins[i];
  215. corners[0][i] = emaxs[i];
  216. }
  217. }
  218. dist = DotProduct (plane->normal, corners[0]) - plane->dist;
  219. dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
  220. sides = 0;
  221. if (dist1 >= 0)
  222. sides = 1;
  223. if (dist2 < 0)
  224. sides |= 2;
  225. #endif
  226. sides = 0;
  227. if (dist1 >= p->dist)
  228. sides = 1;
  229. if (dist2 < p->dist)
  230. sides |= 2;
  231. #ifdef PARANOID
  232. if (sides == 0)
  233. Sys_Error ("BoxOnPlaneSide: sides==0");
  234. #endif
  235. return sides;
  236. }
  237. #endif
  238. void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
  239. {
  240. float angle;
  241. float sr, sp, sy, cr, cp, cy;
  242. angle = angles[YAW] * (M_PI*2 / 360);
  243. sy = sin(angle);
  244. cy = cos(angle);
  245. angle = angles[PITCH] * (M_PI*2 / 360);
  246. sp = sin(angle);
  247. cp = cos(angle);
  248. angle = angles[ROLL] * (M_PI*2 / 360);
  249. sr = sin(angle);
  250. cr = cos(angle);
  251. forward[0] = cp*cy;
  252. forward[1] = cp*sy;
  253. forward[2] = -sp;
  254. right[0] = (-1*sr*sp*cy+-1*cr*-sy);
  255. right[1] = (-1*sr*sp*sy+-1*cr*cy);
  256. right[2] = -1*sr*cp;
  257. up[0] = (cr*sp*cy+-sr*-sy);
  258. up[1] = (cr*sp*sy+-sr*cy);
  259. up[2] = cr*cp;
  260. }
  261. int VectorCompare (vec3_t v1, vec3_t v2)
  262. {
  263. int i;
  264. for (i=0 ; i<3 ; i++)
  265. if (v1[i] != v2[i])
  266. return 0;
  267. return 1;
  268. }
  269. void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
  270. {
  271. vecc[0] = veca[0] + scale*vecb[0];
  272. vecc[1] = veca[1] + scale*vecb[1];
  273. vecc[2] = veca[2] + scale*vecb[2];
  274. }
  275. vec_t _DotProduct (vec3_t v1, vec3_t v2)
  276. {
  277. return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
  278. }
  279. void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
  280. {
  281. out[0] = veca[0]-vecb[0];
  282. out[1] = veca[1]-vecb[1];
  283. out[2] = veca[2]-vecb[2];
  284. }
  285. void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
  286. {
  287. out[0] = veca[0]+vecb[0];
  288. out[1] = veca[1]+vecb[1];
  289. out[2] = veca[2]+vecb[2];
  290. }
  291. void _VectorCopy (vec3_t in, vec3_t out)
  292. {
  293. out[0] = in[0];
  294. out[1] = in[1];
  295. out[2] = in[2];
  296. }
  297. void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
  298. {
  299. cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
  300. cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
  301. cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
  302. }
  303. double sqrt(double x);
  304. vec_t Length(vec3_t v)
  305. {
  306. int i;
  307. float length;
  308. length = 0;
  309. for (i=0 ; i< 3 ; i++)
  310. length += v[i]*v[i];
  311. length = sqrt (length); // FIXME
  312. return length;
  313. }
  314. float VectorNormalize (vec3_t v)
  315. {
  316. float length, ilength;
  317. length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
  318. length = sqrt (length); // FIXME
  319. if (length)
  320. {
  321. ilength = 1/length;
  322. v[0] *= ilength;
  323. v[1] *= ilength;
  324. v[2] *= ilength;
  325. }
  326. return length;
  327. }
  328. void VectorInverse (vec3_t v)
  329. {
  330. v[0] = -v[0];
  331. v[1] = -v[1];
  332. v[2] = -v[2];
  333. }
  334. void VectorScale (vec3_t in, vec_t scale, vec3_t out)
  335. {
  336. out[0] = in[0]*scale;
  337. out[1] = in[1]*scale;
  338. out[2] = in[2]*scale;
  339. }
  340. int Q_log2(int val)
  341. {
  342. int answer=0;
  343. while ((val>>=1) != 0)
  344. answer++;
  345. return answer;
  346. }
  347. /*
  348. ================
  349. R_ConcatRotations
  350. ================
  351. */
  352. void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
  353. {
  354. out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
  355. in1[0][2] * in2[2][0];
  356. out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
  357. in1[0][2] * in2[2][1];
  358. out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
  359. in1[0][2] * in2[2][2];
  360. out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
  361. in1[1][2] * in2[2][0];
  362. out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
  363. in1[1][2] * in2[2][1];
  364. out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
  365. in1[1][2] * in2[2][2];
  366. out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
  367. in1[2][2] * in2[2][0];
  368. out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
  369. in1[2][2] * in2[2][1];
  370. out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
  371. in1[2][2] * in2[2][2];
  372. }
  373. /*
  374. ================
  375. R_ConcatTransforms
  376. ================
  377. */
  378. void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
  379. {
  380. out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
  381. in1[0][2] * in2[2][0];
  382. out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
  383. in1[0][2] * in2[2][1];
  384. out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
  385. in1[0][2] * in2[2][2];
  386. out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
  387. in1[0][2] * in2[2][3] + in1[0][3];
  388. out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
  389. in1[1][2] * in2[2][0];
  390. out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
  391. in1[1][2] * in2[2][1];
  392. out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
  393. in1[1][2] * in2[2][2];
  394. out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
  395. in1[1][2] * in2[2][3] + in1[1][3];
  396. out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
  397. in1[2][2] * in2[2][0];
  398. out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
  399. in1[2][2] * in2[2][1];
  400. out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
  401. in1[2][2] * in2[2][2];
  402. out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
  403. in1[2][2] * in2[2][3] + in1[2][3];
  404. }
  405. /*
  406. ===================
  407. FloorDivMod
  408. Returns mathematically correct (floor-based) quotient and remainder for
  409. numer and denom, both of which should contain no fractional part. The
  410. quotient must fit in 32 bits.
  411. ====================
  412. */
  413. void FloorDivMod (double numer, double denom, int *quotient,
  414. int *rem)
  415. {
  416. int q, r;
  417. double x;
  418. #ifndef PARANOID
  419. if (denom <= 0.0)
  420. Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
  421. // if ((floor(numer) != numer) || (floor(denom) != denom))
  422. // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
  423. // numer, denom);
  424. #endif
  425. if (numer >= 0.0)
  426. {
  427. x = floor(numer / denom);
  428. q = (int)x;
  429. r = (int)floor(numer - (x * denom));
  430. }
  431. else
  432. {
  433. //
  434. // perform operations with positive values, and fix mod to make floor-based
  435. //
  436. x = floor(-numer / denom);
  437. q = -(int)x;
  438. r = (int)floor(-numer - (x * denom));
  439. if (r != 0)
  440. {
  441. q--;
  442. r = (int)denom - r;
  443. }
  444. }
  445. *quotient = q;
  446. *rem = r;
  447. }
  448. /*
  449. ===================
  450. GreatestCommonDivisor
  451. ====================
  452. */
  453. int GreatestCommonDivisor (int i1, int i2)
  454. {
  455. if (i1 > i2)
  456. {
  457. if (i2 == 0)
  458. return (i1);
  459. return GreatestCommonDivisor (i2, i1 % i2);
  460. }
  461. else
  462. {
  463. if (i1 == 0)
  464. return (i2);
  465. return GreatestCommonDivisor (i1, i2 % i1);
  466. }
  467. }
  468. #if !id386
  469. // TODO: move to nonintel.c
  470. /*
  471. ===================
  472. Invert24To16
  473. Inverts an 8.24 value to a 16.16 value
  474. ====================
  475. */
  476. fixed16_t Invert24To16(fixed16_t val)
  477. {
  478. if (val < 256)
  479. return (0xFFFFFFFF);
  480. return (fixed16_t)
  481. (((double)0x10000 * (double)0x1000000 / (double)val) + 0.5);
  482. }
  483. #endif