summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/mathlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/mathlib.c')
-rw-r--r--apps/plugins/sdl/progs/quake/mathlib.c550
1 files changed, 550 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/mathlib.c b/apps/plugins/sdl/progs/quake/mathlib.c
new file mode 100644
index 0000000000..ddd5435089
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/mathlib.c
@@ -0,0 +1,550 @@
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20// mathlib.c -- math primitives
21
22#include <math.h>
23#include "quakedef.h"
24
25void Sys_Error (char *error, ...);
26
27vec3_t vec3_origin = {0,0,0};
28int nanmask = 255<<23;
29
30/*-----------------------------------------------------------------*/
31
32#define DEG2RAD( a ) ( a * M_PI ) / 180.0F
33
34void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
35{
36 float d;
37 vec3_t n;
38 float inv_denom;
39
40 inv_denom = 1.0F / DotProduct( normal, normal );
41
42 d = DotProduct( normal, p ) * inv_denom;
43
44 n[0] = normal[0] * inv_denom;
45 n[1] = normal[1] * inv_denom;
46 n[2] = normal[2] * inv_denom;
47
48 dst[0] = p[0] - d * n[0];
49 dst[1] = p[1] - d * n[1];
50 dst[2] = p[2] - d * n[2];
51}
52
53/*
54** assumes "src" is normalized
55*/
56void PerpendicularVector( vec3_t dst, const vec3_t src )
57{
58 int pos;
59 int i;
60 float minelem = 1.0F;
61 vec3_t tempvec;
62
63 /*
64 ** find the smallest magnitude axially aligned vector
65 */
66 for ( pos = 0, i = 0; i < 3; i++ )
67 {
68 if ( fabs( src[i] ) < minelem )
69 {
70 pos = i;
71 minelem = fabs( src[i] );
72 }
73 }
74 tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
75 tempvec[pos] = 1.0F;
76
77 /*
78 ** project the point onto the plane defined by src
79 */
80 ProjectPointOnPlane( dst, tempvec, src );
81
82 /*
83 ** normalize the result
84 */
85 VectorNormalizeNoRet( dst );
86}
87
88#ifdef _WIN32
89#pragma optimize( "", off )
90#endif
91
92
93void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
94{
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;
102
103 vf[0] = dir[0];
104 vf[1] = dir[1];
105 vf[2] = dir[2];
106
107 PerpendicularVector( vr, dir );
108 CrossProduct( vr, vf, vup );
109
110 m[0][0] = vr[0];
111 m[1][0] = vr[1];
112 m[2][0] = vr[2];
113
114 m[0][1] = vup[0];
115 m[1][1] = vup[1];
116 m[2][1] = vup[2];
117
118 m[0][2] = vf[0];
119 m[1][2] = vf[1];
120 m[2][2] = vf[2];
121
122 memcpy( im, m, sizeof( im ) );
123
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];
130
131 memset( zrot, 0, sizeof( zrot ) );
132 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
133
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 ) );
138
139 R_ConcatRotations( m, zrot, tmpmat );
140 R_ConcatRotations( tmpmat, im, rot );
141
142 for ( i = 0; i < 3; i++ )
143 {
144 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
145 }
146}
147
148#ifdef _WIN32
149#pragma optimize( "", on )
150#endif
151
152/*-----------------------------------------------------------------*/
153
154
155float anglemod(float a)
156{
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;
165}
166
167/*
168==================
169BOPS_Error
170
171Split out like this for ASM to call.
172==================
173*/
174void BOPS_Error (void)
175{
176 Sys_Error ("BoxOnPlaneSide: Bad signbits");
177}
178
179
180#if !id386
181
182/*
183==================
184BoxOnPlaneSide
185
186Returns 1, 2, or 1 + 2
187==================
188*/
189int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, mplane_t *p)
190{
191 float dist1, dist2;
192 int sides;
193
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)
198 {
199 if (p->dist <= emins[p->type])
200 return 1;
201 if (p->dist >= emaxs[p->type])
202 return 2;
203 return 3;
204 }
205#endif
206
207// general case
208 switch (p->signbits)
209 {
210 case 0:
211dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
212dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
213 break;
214 case 1:
215dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
216dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
217 break;
218 case 2:
219dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
220dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
221 break;
222 case 3:
223dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
224dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
225 break;
226 case 4:
227dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
228dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
229 break;
230 case 5:
231dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
232dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
233 break;
234 case 6:
235dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
236dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
237 break;
238 case 7:
239dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
240dist2 = 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;
246 }
247
248#if 0
249 int i;
250 vec3_t corners[2];
251
252 for (i=0 ; i<3 ; i++)
253 {
254 if (plane->normal[i] < 0)
255 {
256 corners[0][i] = emins[i];
257 corners[1][i] = emaxs[i];
258 }
259 else
260 {
261 corners[1][i] = emins[i];
262 corners[0][i] = emaxs[i];
263 }
264 }
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;
272
273#endif
274
275 sides = 0;
276 if (dist1 >= p->dist)
277 sides = 1;
278 if (dist2 < p->dist)
279 sides |= 2;
280
281#ifdef PARANOID
282if (sides == 0)
283 Sys_Error ("BoxOnPlaneSide: sides==0");
284#endif
285
286 return sides;
287}
288
289#endif
290
291
292void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
293{
294 float angle;
295 float sr, sp, sy, cr, cp, cy;
296
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);
306
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;
316}
317
318int VectorCompare (vec3_t v1, vec3_t v2)
319{
320 int i;
321
322 for (i=0 ; i<3 ; i++)
323 if (v1[i] != v2[i])
324 return 0;
325
326 return 1;
327}
328
329void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
330{
331 vecc[0] = veca[0] + scale*vecb[0];
332 vecc[1] = veca[1] + scale*vecb[1];
333 vecc[2] = veca[2] + scale*vecb[2];
334}
335
336
337vec_t _DotProduct (vec3_t v1, vec3_t v2)
338{
339 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
340}
341
342void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
343{
344 out[0] = veca[0]-vecb[0];
345 out[1] = veca[1]-vecb[1];
346 out[2] = veca[2]-vecb[2];
347}
348
349void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
350{
351 out[0] = veca[0]+vecb[0];
352 out[1] = veca[1]+vecb[1];
353 out[2] = veca[2]+vecb[2];
354}
355
356void _VectorCopy (vec3_t in, vec3_t out)
357{
358 out[0] = in[0];
359 out[1] = in[1];
360 out[2] = in[2];
361}
362
363void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
364{
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];
368}
369
370vec_t Length(vec3_t v)
371{
372 int i;
373 float length;
374
375 length = 0;
376 for (i=0 ; i< 3 ; i++)
377 length += v[i]*v[i];
378 length = sqrt (length); // FIXME
379
380 return length;
381}
382
383
384int Q_log2(int val)
385{
386 int answer=0;
387 while (val>>=1)
388 answer++;
389 return answer;
390}
391
392
393/*
394================
395R_ConcatRotations
396================
397*/
398void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
399{
400 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
401 in1[0][2] * in2[2][0];
402 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
403 in1[0][2] * in2[2][1];
404 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
405 in1[0][2] * in2[2][2];
406 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
407 in1[1][2] * in2[2][0];
408 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
409 in1[1][2] * in2[2][1];
410 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
411 in1[1][2] * in2[2][2];
412 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
413 in1[2][2] * in2[2][0];
414 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
415 in1[2][2] * in2[2][1];
416 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
417 in1[2][2] * in2[2][2];
418}
419
420
421/*
422================
423R_ConcatTransforms
424================
425*/
426void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
427{
428 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
429 in1[0][2] * in2[2][0];
430 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
431 in1[0][2] * in2[2][1];
432 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
433 in1[0][2] * in2[2][2];
434 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
435 in1[0][2] * in2[2][3] + in1[0][3];
436 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
437 in1[1][2] * in2[2][0];
438 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
439 in1[1][2] * in2[2][1];
440 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
441 in1[1][2] * in2[2][2];
442 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
443 in1[1][2] * in2[2][3] + in1[1][3];
444 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
445 in1[2][2] * in2[2][0];
446 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
447 in1[2][2] * in2[2][1];
448 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
449 in1[2][2] * in2[2][2];
450 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
451 in1[2][2] * in2[2][3] + in1[2][3];
452}
453
454
455/*
456===================
457FloorDivMod
458
459Returns mathematically correct (floor-based) quotient and remainder for
460numer and denom, both of which should contain no fractional part. The
461quotient must fit in 32 bits.
462====================
463*/
464
465void FloorDivMod (double numer, double denom, int *quotient,
466 int *rem)
467{
468 int q, r;
469 double x;
470
471#ifndef PARANOID
472 if (denom <= 0.0)
473 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
474
475// if ((floor(numer) != numer) || (floor(denom) != denom))
476// Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
477// numer, denom);
478#endif
479
480 if (numer >= 0.0)
481 {
482
483 x = floor(numer / denom);
484 q = (int)x;
485 r = (int)floor(numer - (x * denom));
486 }
487 else
488 {
489 //
490 // perform operations with positive values, and fix mod to make floor-based
491 //
492 x = floor(-numer / denom);
493 q = -(int)x;
494 r = (int)floor(-numer - (x * denom));
495 if (r != 0)
496 {
497 q--;
498 r = (int)denom - r;
499 }
500 }
501
502 *quotient = q;
503 *rem = r;
504}
505
506
507/*
508===================
509GreatestCommonDivisor
510====================
511*/
512int GreatestCommonDivisor (int i1, int i2)
513{
514 if (i1 > i2)
515 {
516 if (i2 == 0)
517 return (i1);
518 return GreatestCommonDivisor (i2, i1 % i2);
519 }
520 else
521 {
522 if (i1 == 0)
523 return (i2);
524 return GreatestCommonDivisor (i1, i2 % i1);
525 }
526}
527
528
529#if !id386
530
531// TODO: move to nonintel.c
532
533/*
534===================
535Invert24To16
536
537Inverts an 8.24 value to a 16.16 value
538====================
539*/
540
541fixed16_t Invert24To16(fixed16_t val)
542{
543 if (val < 256)
544 return (0xFFFFFFFF);
545
546 return (fixed16_t)
547 (((double)0x10000 * (double)0x1000000 / (double)val) + 0.5);
548}
549
550#endif