mathlib.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // mathlib.c -- math primitives
  19. #include "cmdlib.h"
  20. #include "mathlib.h"
  21. #ifdef _WIN32
  22. //Improve floating-point consistency.
  23. //without this option weird floating point issues occur
  24. #pragma optimize( "p", on )
  25. #endif
  26. vec3_t vec3_origin = {0,0,0};
  27. /*
  28. ** NormalToLatLong
  29. **
  30. ** We use two byte encoded normals in some space critical applications.
  31. ** Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format
  32. ** Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
  33. **
  34. */
  35. void NormalToLatLong( const vec3_t normal, byte bytes[2] ) {
  36. // check for singularities
  37. if ( normal[0] == 0 && normal[1] == 0 ) {
  38. if ( normal[2] > 0 ) {
  39. bytes[0] = 0;
  40. bytes[1] = 0; // lat = 0, long = 0
  41. } else {
  42. bytes[0] = 128;
  43. bytes[1] = 0; // lat = 0, long = 128
  44. }
  45. } else {
  46. int a, b;
  47. a = RAD2DEG( atan2( normal[1], normal[0] ) ) * (255.0f / 360.0f );
  48. a &= 0xff;
  49. b = RAD2DEG( acos( normal[2] ) ) * ( 255.0f / 360.0f );
  50. b &= 0xff;
  51. bytes[0] = b; // longitude
  52. bytes[1] = a; // lattitude
  53. }
  54. }
  55. /*
  56. =====================
  57. PlaneFromPoints
  58. Returns false if the triangle is degenrate.
  59. The normal will point out of the clock for clockwise ordered points
  60. =====================
  61. */
  62. qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
  63. vec3_t d1, d2;
  64. VectorSubtract( b, a, d1 );
  65. VectorSubtract( c, a, d2 );
  66. CrossProduct( d2, d1, plane );
  67. if ( VectorNormalize( plane, plane ) == 0 ) {
  68. return qfalse;
  69. }
  70. plane[3] = DotProduct( a, plane );
  71. return qtrue;
  72. }
  73. /*
  74. ================
  75. MakeNormalVectors
  76. Given a normalized forward vector, create two
  77. other perpendicular vectors
  78. ================
  79. */
  80. void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
  81. {
  82. float d;
  83. // this rotate and negate guarantees a vector
  84. // not colinear with the original
  85. right[1] = -forward[0];
  86. right[2] = forward[1];
  87. right[0] = forward[2];
  88. d = DotProduct (right, forward);
  89. VectorMA (right, -d, forward, right);
  90. VectorNormalize (right, right);
  91. CrossProduct (right, forward, up);
  92. }
  93. void Vec10Copy( vec_t *in, vec_t *out ) {
  94. out[0] = in[0];
  95. out[1] = in[1];
  96. out[2] = in[2];
  97. out[3] = in[3];
  98. out[4] = in[4];
  99. out[5] = in[5];
  100. out[6] = in[6];
  101. out[7] = in[7];
  102. out[8] = in[8];
  103. out[9] = in[9];
  104. }
  105. void VectorRotate3x3( vec3_t v, float r[3][3], vec3_t d )
  106. {
  107. d[0] = v[0] * r[0][0] + v[1] * r[1][0] + v[2] * r[2][0];
  108. d[1] = v[0] * r[0][1] + v[1] * r[1][1] + v[2] * r[2][1];
  109. d[2] = v[0] * r[0][2] + v[1] * r[1][2] + v[2] * r[2][2];
  110. }
  111. double VectorLength( const vec3_t v ) {
  112. int i;
  113. double length;
  114. length = 0;
  115. for (i=0 ; i< 3 ; i++)
  116. length += v[i]*v[i];
  117. length = sqrt (length); // FIXME
  118. return length;
  119. }
  120. qboolean VectorCompare( const vec3_t v1, const vec3_t v2 ) {
  121. int i;
  122. for (i=0 ; i<3 ; i++)
  123. if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
  124. return qfalse;
  125. return qtrue;
  126. }
  127. vec_t Q_rint (vec_t in)
  128. {
  129. return floor (in + 0.5);
  130. }
  131. void VectorMA( const vec3_t va, double scale, const vec3_t vb, vec3_t vc ) {
  132. vc[0] = va[0] + scale*vb[0];
  133. vc[1] = va[1] + scale*vb[1];
  134. vc[2] = va[2] + scale*vb[2];
  135. }
  136. void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ) {
  137. cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
  138. cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
  139. cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
  140. }
  141. vec_t _DotProduct (vec3_t v1, vec3_t v2)
  142. {
  143. return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
  144. }
  145. void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
  146. {
  147. out[0] = va[0]-vb[0];
  148. out[1] = va[1]-vb[1];
  149. out[2] = va[2]-vb[2];
  150. }
  151. void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
  152. {
  153. out[0] = va[0]+vb[0];
  154. out[1] = va[1]+vb[1];
  155. out[2] = va[2]+vb[2];
  156. }
  157. void _VectorCopy (vec3_t in, vec3_t out)
  158. {
  159. out[0] = in[0];
  160. out[1] = in[1];
  161. out[2] = in[2];
  162. }
  163. void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
  164. {
  165. out[0] = v[0] * scale;
  166. out[1] = v[1] * scale;
  167. out[2] = v[2] * scale;
  168. }
  169. vec_t VectorNormalize( const vec3_t in, vec3_t out ) {
  170. vec_t length, ilength;
  171. length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
  172. if (length == 0)
  173. {
  174. VectorClear (out);
  175. return 0;
  176. }
  177. ilength = 1.0/length;
  178. out[0] = in[0]*ilength;
  179. out[1] = in[1]*ilength;
  180. out[2] = in[2]*ilength;
  181. return length;
  182. }
  183. vec_t ColorNormalize( const vec3_t in, vec3_t out ) {
  184. float max, scale;
  185. max = in[0];
  186. if (in[1] > max)
  187. max = in[1];
  188. if (in[2] > max)
  189. max = in[2];
  190. if (max == 0) {
  191. out[0] = out[1] = out[2] = 1.0;
  192. return 0;
  193. }
  194. scale = 1.0 / max;
  195. VectorScale (in, scale, out);
  196. return max;
  197. }
  198. void VectorInverse (vec3_t v)
  199. {
  200. v[0] = -v[0];
  201. v[1] = -v[1];
  202. v[2] = -v[2];
  203. }
  204. void ClearBounds (vec3_t mins, vec3_t maxs)
  205. {
  206. mins[0] = mins[1] = mins[2] = 99999;
  207. maxs[0] = maxs[1] = maxs[2] = -99999;
  208. }
  209. void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) {
  210. int i;
  211. vec_t val;
  212. for (i=0 ; i<3 ; i++)
  213. {
  214. val = v[i];
  215. if (val < mins[i])
  216. mins[i] = val;
  217. if (val > maxs[i])
  218. maxs[i] = val;
  219. }
  220. }
  221. /*
  222. =================
  223. PlaneTypeForNormal
  224. =================
  225. */
  226. int PlaneTypeForNormal (vec3_t normal) {
  227. if (normal[0] == 1.0 || normal[0] == -1.0)
  228. return PLANE_X;
  229. if (normal[1] == 1.0 || normal[1] == -1.0)
  230. return PLANE_Y;
  231. if (normal[2] == 1.0 || normal[2] == -1.0)
  232. return PLANE_Z;
  233. return PLANE_NON_AXIAL;
  234. }
  235. /*
  236. ================
  237. MatrixMultiply
  238. ================
  239. */
  240. void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
  241. out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
  242. in1[0][2] * in2[2][0];
  243. out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
  244. in1[0][2] * in2[2][1];
  245. out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
  246. in1[0][2] * in2[2][2];
  247. out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
  248. in1[1][2] * in2[2][0];
  249. out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
  250. in1[1][2] * in2[2][1];
  251. out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
  252. in1[1][2] * in2[2][2];
  253. out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
  254. in1[2][2] * in2[2][0];
  255. out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
  256. in1[2][2] * in2[2][1];
  257. out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
  258. in1[2][2] * in2[2][2];
  259. }
  260. void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
  261. {
  262. float d;
  263. vec3_t n;
  264. float inv_denom;
  265. inv_denom = 1.0F / DotProduct( normal, normal );
  266. d = DotProduct( normal, p ) * inv_denom;
  267. n[0] = normal[0] * inv_denom;
  268. n[1] = normal[1] * inv_denom;
  269. n[2] = normal[2] * inv_denom;
  270. dst[0] = p[0] - d * n[0];
  271. dst[1] = p[1] - d * n[1];
  272. dst[2] = p[2] - d * n[2];
  273. }
  274. /*
  275. ** assumes "src" is normalized
  276. */
  277. void PerpendicularVector( vec3_t dst, const vec3_t src )
  278. {
  279. int pos;
  280. int i;
  281. float minelem = 1.0F;
  282. vec3_t tempvec;
  283. /*
  284. ** find the smallest magnitude axially aligned vector
  285. */
  286. for ( pos = 0, i = 0; i < 3; i++ )
  287. {
  288. if ( fabs( src[i] ) < minelem )
  289. {
  290. pos = i;
  291. minelem = fabs( src[i] );
  292. }
  293. }
  294. tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
  295. tempvec[pos] = 1.0F;
  296. /*
  297. ** project the point onto the plane defined by src
  298. */
  299. ProjectPointOnPlane( dst, tempvec, src );
  300. /*
  301. ** normalize the result
  302. */
  303. VectorNormalize( dst, dst );
  304. }
  305. /*
  306. ===============
  307. RotatePointAroundVector
  308. This is not implemented very well...
  309. ===============
  310. */
  311. void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
  312. float degrees ) {
  313. float m[3][3];
  314. float im[3][3];
  315. float zrot[3][3];
  316. float tmpmat[3][3];
  317. float rot[3][3];
  318. int i;
  319. vec3_t vr, vup, vf;
  320. float rad;
  321. vf[0] = dir[0];
  322. vf[1] = dir[1];
  323. vf[2] = dir[2];
  324. PerpendicularVector( vr, dir );
  325. CrossProduct( vr, vf, vup );
  326. m[0][0] = vr[0];
  327. m[1][0] = vr[1];
  328. m[2][0] = vr[2];
  329. m[0][1] = vup[0];
  330. m[1][1] = vup[1];
  331. m[2][1] = vup[2];
  332. m[0][2] = vf[0];
  333. m[1][2] = vf[1];
  334. m[2][2] = vf[2];
  335. memcpy( im, m, sizeof( im ) );
  336. im[0][1] = m[1][0];
  337. im[0][2] = m[2][0];
  338. im[1][0] = m[0][1];
  339. im[1][2] = m[2][1];
  340. im[2][0] = m[0][2];
  341. im[2][1] = m[1][2];
  342. memset( zrot, 0, sizeof( zrot ) );
  343. zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
  344. rad = DEG2RAD( degrees );
  345. zrot[0][0] = cos( rad );
  346. zrot[0][1] = sin( rad );
  347. zrot[1][0] = -sin( rad );
  348. zrot[1][1] = cos( rad );
  349. MatrixMultiply( m, zrot, tmpmat );
  350. MatrixMultiply( tmpmat, im, rot );
  351. for ( i = 0; i < 3; i++ ) {
  352. dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
  353. }
  354. }