Fix for the problem that SDL applications exited
[AROS-Contrib.git] / Games / Quake / mathlib.c
blob9f5d6445f274b39c8762f07d250231c7bdb65416
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // mathlib.c -- math primitives
22 #include <math.h>
23 #include "quakedef.h"
25 void Sys_Error (char *error, ...);
27 vec3_t vec3_origin = {0,0,0};
28 int nanmask = 255<<23;
30 /*-----------------------------------------------------------------*/
32 #define DEG2RAD( a ) ( a * M_PI ) / 180.0F
34 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
36 float d;
37 vec3_t n;
38 float inv_denom;
40 inv_denom = 1.0F / DotProduct( normal, normal );
42 d = DotProduct( normal, p ) * inv_denom;
44 n[0] = normal[0] * inv_denom;
45 n[1] = normal[1] * inv_denom;
46 n[2] = normal[2] * inv_denom;
48 dst[0] = p[0] - d * n[0];
49 dst[1] = p[1] - d * n[1];
50 dst[2] = p[2] - d * n[2];
54 ** assumes "src" is normalized
56 void PerpendicularVector( vec3_t dst, const vec3_t src )
58 int pos;
59 int i;
60 float minelem = 1.0F;
61 vec3_t tempvec;
64 ** find the smallest magnitude axially aligned vector
66 for ( pos = 0, i = 0; i < 3; i++ )
68 if ( fabs( src[i] ) < minelem )
70 pos = i;
71 minelem = fabs( src[i] );
74 tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
75 tempvec[pos] = 1.0F;
78 ** project the point onto the plane defined by src
80 ProjectPointOnPlane( dst, tempvec, src );
83 ** normalize the result
85 VectorNormalize( dst );
88 #ifdef _WIN32
89 #pragma optimize( "", off )
90 #endif
93 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
95 float m[3][3];
96 float im[3][3];
97 float zrot[3][3];
98 float tmpmat[3][3];
99 float rot[3][3];
100 int i;
101 vec3_t vr, vup, vf;
103 vf[0] = dir[0];
104 vf[1] = dir[1];
105 vf[2] = dir[2];
107 PerpendicularVector( vr, dir );
108 CrossProduct( vr, vf, vup );
110 m[0][0] = vr[0];
111 m[1][0] = vr[1];
112 m[2][0] = vr[2];
114 m[0][1] = vup[0];
115 m[1][1] = vup[1];
116 m[2][1] = vup[2];
118 m[0][2] = vf[0];
119 m[1][2] = vf[1];
120 m[2][2] = vf[2];
122 memcpy( im, m, sizeof( im ) );
124 im[0][1] = m[1][0];
125 im[0][2] = m[2][0];
126 im[1][0] = m[0][1];
127 im[1][2] = m[2][1];
128 im[2][0] = m[0][2];
129 im[2][1] = m[1][2];
131 memset( zrot, 0, sizeof( zrot ) );
132 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
134 zrot[0][0] = cos( DEG2RAD( degrees ) );
135 zrot[0][1] = sin( DEG2RAD( degrees ) );
136 zrot[1][0] = -sin( DEG2RAD( degrees ) );
137 zrot[1][1] = cos( DEG2RAD( degrees ) );
139 R_ConcatRotations( m, zrot, tmpmat );
140 R_ConcatRotations( tmpmat, im, rot );
142 for ( i = 0; i < 3; i++ )
144 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
148 #ifdef _WIN32
149 #pragma optimize( "", on )
150 #endif
152 /*-----------------------------------------------------------------*/
155 float anglemod(float a)
157 #if 0
158 if (a >= 0)
159 a -= 360*(int)(a/360);
160 else
161 a += 360*( 1 + (int)(-a/360) );
162 #endif
163 a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
164 return a;
168 ==================
169 BOPS_Error
171 Split out like this for ASM to call.
172 ==================
174 void BOPS_Error (void)
176 Sys_Error ("BoxOnPlaneSide: Bad signbits");
180 #if !id386
183 ==================
184 BoxOnPlaneSide
186 Returns 1, 2, or 1 + 2
187 ==================
189 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p)
191 float dist1, dist2;
192 int sides;
194 #if 0 // this is done by the BOX_ON_PLANE_SIDE macro before calling this
195 // function
196 // fast axial cases
197 if (p->type < 3)
199 if (p->dist <= emins[p->type])
200 return 1;
201 if (p->dist >= emaxs[p->type])
202 return 2;
203 return 3;
205 #endif
207 // general case
208 switch (p->signbits)
210 case 0:
211 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
212 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
213 break;
214 case 1:
215 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
216 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
217 break;
218 case 2:
219 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
220 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
221 break;
222 case 3:
223 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
224 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
225 break;
226 case 4:
227 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
228 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
229 break;
230 case 5:
231 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
232 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
233 break;
234 case 6:
235 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
236 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
237 break;
238 case 7:
239 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
240 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
241 break;
242 default:
243 dist1 = dist2 = 0; // shut up compiler
244 BOPS_Error ();
245 break;
248 #if 0
249 int i;
250 vec3_t corners[2];
252 for (i=0 ; i<3 ; i++)
254 if (plane->normal[i] < 0)
256 corners[0][i] = emins[i];
257 corners[1][i] = emaxs[i];
259 else
261 corners[1][i] = emins[i];
262 corners[0][i] = emaxs[i];
265 dist = DotProduct (plane->normal, corners[0]) - plane->dist;
266 dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
267 sides = 0;
268 if (dist1 >= 0)
269 sides = 1;
270 if (dist2 < 0)
271 sides |= 2;
273 #endif
275 sides = 0;
276 if (dist1 >= p->dist)
277 sides = 1;
278 if (dist2 < p->dist)
279 sides |= 2;
281 #ifdef PARANOID
282 if (sides == 0)
283 Sys_Error ("BoxOnPlaneSide: sides==0");
284 #endif
286 return sides;
289 #endif
292 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
294 float angle;
295 float sr, sp, sy, cr, cp, cy;
297 angle = angles[YAW] * (M_PI*2 / 360);
298 sy = sin(angle);
299 cy = cos(angle);
300 angle = angles[PITCH] * (M_PI*2 / 360);
301 sp = sin(angle);
302 cp = cos(angle);
303 angle = angles[ROLL] * (M_PI*2 / 360);
304 sr = sin(angle);
305 cr = cos(angle);
307 forward[0] = cp*cy;
308 forward[1] = cp*sy;
309 forward[2] = -sp;
310 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
311 right[1] = (-1*sr*sp*sy+-1*cr*cy);
312 right[2] = -1*sr*cp;
313 up[0] = (cr*sp*cy+-sr*-sy);
314 up[1] = (cr*sp*sy+-sr*cy);
315 up[2] = cr*cp;
318 int VectorCompare (vec3_t v1, vec3_t v2)
320 int i;
322 for (i=0 ; i<3 ; i++)
323 if (v1[i] != v2[i])
324 return 0;
326 return 1;
329 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
331 vecc[0] = veca[0] + scale*vecb[0];
332 vecc[1] = veca[1] + scale*vecb[1];
333 vecc[2] = veca[2] + scale*vecb[2];
337 vec_t _DotProduct (vec3_t v1, vec3_t v2)
339 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
342 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
344 out[0] = veca[0]-vecb[0];
345 out[1] = veca[1]-vecb[1];
346 out[2] = veca[2]-vecb[2];
349 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
351 out[0] = veca[0]+vecb[0];
352 out[1] = veca[1]+vecb[1];
353 out[2] = veca[2]+vecb[2];
356 void _VectorCopy (vec3_t in, vec3_t out)
358 out[0] = in[0];
359 out[1] = in[1];
360 out[2] = in[2];
363 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
365 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
366 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
367 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
370 double sqrt(double x);
372 vec_t Length(vec3_t v)
374 int i;
375 float length;
377 length = 0;
378 for (i=0 ; i< 3 ; i++)
379 length += v[i]*v[i];
380 length = sqrt (length); // FIXME
382 return length;
385 float VectorNormalize (vec3_t v)
387 float length, ilength;
389 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
390 length = sqrt (length); // FIXME
392 if (length)
394 ilength = 1/length;
395 v[0] *= ilength;
396 v[1] *= ilength;
397 v[2] *= ilength;
400 return length;
404 void VectorInverse (vec3_t v)
406 v[0] = -v[0];
407 v[1] = -v[1];
408 v[2] = -v[2];
411 void VectorScale (vec3_t in, vec_t scale, vec3_t out)
413 out[0] = in[0]*scale;
414 out[1] = in[1]*scale;
415 out[2] = in[2]*scale;
419 int Q_log2(int val)
421 int answer=0;
422 while (val>>=1)
423 answer++;
424 return answer;
429 ================
430 R_ConcatRotations
431 ================
433 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
435 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
436 in1[0][2] * in2[2][0];
437 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
438 in1[0][2] * in2[2][1];
439 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
440 in1[0][2] * in2[2][2];
441 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
442 in1[1][2] * in2[2][0];
443 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
444 in1[1][2] * in2[2][1];
445 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
446 in1[1][2] * in2[2][2];
447 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
448 in1[2][2] * in2[2][0];
449 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
450 in1[2][2] * in2[2][1];
451 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
452 in1[2][2] * in2[2][2];
457 ================
458 R_ConcatTransforms
459 ================
461 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
463 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
464 in1[0][2] * in2[2][0];
465 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
466 in1[0][2] * in2[2][1];
467 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
468 in1[0][2] * in2[2][2];
469 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
470 in1[0][2] * in2[2][3] + in1[0][3];
471 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
472 in1[1][2] * in2[2][0];
473 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
474 in1[1][2] * in2[2][1];
475 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
476 in1[1][2] * in2[2][2];
477 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
478 in1[1][2] * in2[2][3] + in1[1][3];
479 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
480 in1[2][2] * in2[2][0];
481 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
482 in1[2][2] * in2[2][1];
483 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
484 in1[2][2] * in2[2][2];
485 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
486 in1[2][2] * in2[2][3] + in1[2][3];
491 ===================
492 FloorDivMod
494 Returns mathematically correct (floor-based) quotient and remainder for
495 numer and denom, both of which should contain no fractional part. The
496 quotient must fit in 32 bits.
497 ====================
500 void FloorDivMod (double numer, double denom, int *quotient,
501 int *rem)
503 int q, r;
504 double x;
506 #ifndef PARANOID
507 if (denom <= 0.0)
508 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
510 // if ((floor(numer) != numer) || (floor(denom) != denom))
511 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
512 // numer, denom);
513 #endif
515 if (numer >= 0.0)
518 x = floor(numer / denom);
519 q = (int)x;
520 r = (int)floor(numer - (x * denom));
522 else
525 // perform operations with positive values, and fix mod to make floor-based
527 x = floor(-numer / denom);
528 q = -(int)x;
529 r = (int)floor(-numer - (x * denom));
530 if (r != 0)
532 q--;
533 r = (int)denom - r;
537 *quotient = q;
538 *rem = r;
543 ===================
544 GreatestCommonDivisor
545 ====================
547 int GreatestCommonDivisor (int i1, int i2)
549 if (i1 > i2)
551 if (i2 == 0)
552 return (i1);
553 return GreatestCommonDivisor (i2, i1 % i2);
555 else
557 if (i1 == 0)
558 return (i2);
559 return GreatestCommonDivisor (i1, i2 % i1);
564 #if !id386
566 // TODO: move to nonintel.c
569 ===================
570 Invert24To16
572 Inverts an 8.24 value to a 16.16 value
573 ====================
576 fixed16_t Invert24To16(fixed16_t val)
578 if (val < 256)
579 return (0xFFFFFFFF);
581 return (fixed16_t)
582 (((double)0x10000 * (double)0x1000000 / (double)val) + 0.5);
585 #endif