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
25 void Sys_Error (char *error, ...);
27 vec3_t vec3_origin = {0,0,0};
28 int nanmask = 255<<23;
31 /*-----------------------------------------------------------------*/
33 float m_bytenormals[NUMVERTEXNORMALS][3] =
35 {-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188},
36 {-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017},
37 {-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000},
38 {0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718},
39 {0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651},
40 {0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651},
41 {0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188},
42 {0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567},
43 {-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191},
44 {-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856},
45 {-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325},
46 {-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863},
47 {-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621},
48 {-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000},
49 {0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863},
50 {0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460},
51 {0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242},
52 {-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863},
53 {0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017},
54 {0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460},
55 {0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000},
56 {0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621},
57 {0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785},
58 {0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325},
59 {0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567},
60 {0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000},
61 {1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866},
62 {0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000},
63 {0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866},
64 {0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
65 {0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856},
66 {0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866},
67 {0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567},
68 {0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731},
69 {0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856},
70 {0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718},
71 {0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785},
72 {0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191},
73 {0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718},
74 {-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651},
75 {-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188},
76 {-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056},
77 {0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423},
78 {0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188},
79 {-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056},
80 {0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718},
81 {0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651},
82 {0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188},
83 {0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863},
84 {0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785},
85 {0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325},
86 {0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242},
87 {0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460},
88 {0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242},
89 {0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460},
90 {0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621},
91 {0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863},
92 {-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460},
93 {-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621},
94 {-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000},
95 {-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
96 {-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856},
97 {-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325},
98 {-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188},
99 {-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017},
100 {-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785},
101 {-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188},
102 {0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017},
103 {0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651},
104 {0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191},
105 {0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000},
106 {-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000},
107 {-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000},
108 {-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856},
109 {-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000},
110 {-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866},
111 {-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567},
112 {-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731},
113 {-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191},
114 {-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785},
115 {-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325},
118 byte NormalToByte(vec3_t n)
121 float bestdistance, distance;
124 bestdistance = DotProduct (n, m_bytenormals[0]);
125 for (i = 1;i < NUMVERTEXNORMALS;i++)
127 distance = DotProduct (n, m_bytenormals[i]);
128 if (distance > bestdistance)
130 bestdistance = distance;
137 // note: uses byte partly to force unsigned for the validity check
138 void ByteToNormal(byte num, vec3_t n)
140 if (num < NUMVERTEXNORMALS)
141 VectorCopy(m_bytenormals[num], n)
143 VectorClear(n) // FIXME: complain?
146 float Q_RSqrt(float number)
153 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
154 return y * (1.5f - (number * 0.5f * y * y));
157 void _VectorNormalizeFast(vec3_t v)
161 number = DotProduct(v, v);
165 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
166 y = y * (1.5f - (number * 0.5f * y * y));
168 VectorScale(v, y, v);
173 // LordHavoc: no longer used at all
174 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
177 // LordHavoc: the old way...
182 inv_denom = 1.0F / DotProduct( normal, normal );
184 d = DotProduct( normal, p ) * inv_denom;
186 n[0] = normal[0] * inv_denom;
187 n[1] = normal[1] * inv_denom;
188 n[2] = normal[2] * inv_denom;
190 dst[0] = p[0] - d * n[0];
191 dst[1] = p[1] - d * n[1];
192 dst[2] = p[2] - d * n[2];
194 // LordHavoc: optimized to death and beyond
197 // LordHavoc: the normal is a unit vector by definition,
198 // therefore inv_denom was pointless.
199 d = DotProduct(normal, p);
200 dst[0] = p[0] - d * normal[0];
201 dst[1] = p[1] - d * normal[1];
202 dst[2] = p[2] - d * normal[2];
207 // assumes "src" is normalized
208 void PerpendicularVector( vec3_t dst, const vec3_t src )
211 // LordHavoc: the old way...
217 // find the smallest magnitude axially aligned vector
219 for ( pos = 0, i = 0; i < 3; i++ )
221 if ( fabs( src[i] ) < minelem )
224 minelem = fabs( src[i] );
227 VectorClear(tempvec);
230 // project the point onto the plane defined by src
231 ProjectPointOnPlane( dst, tempvec, src );
233 // normalize the result
234 VectorNormalize(dst);
236 // LordHavoc: optimized to death and beyond
250 minelem = fabs(src[0]);
251 if (fabs(src[1]) < minelem)
254 minelem = fabs(src[1]);
256 if (fabs(src[2]) < minelem)
260 dst[0] -= src[pos] * src[0];
261 dst[1] -= src[pos] * src[1];
262 dst[2] -= src[pos] * src[2];
264 // normalize the result
265 VectorNormalize(dst);
287 #pragma optimize( "", off )
291 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
292 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
296 right[0] = forward[2];
297 right[1] = -forward[0];
298 right[2] = forward[1];
300 d = DotProduct(forward, right);
301 right[0] -= d * forward[0];
302 right[1] -= d * forward[1];
303 right[2] -= d * forward[2];
304 VectorNormalizeFast(right);
305 CrossProduct(right, forward, up);
308 void VectorVectorsDouble(const double *forward, double *right, double *up)
312 right[0] = forward[2];
313 right[1] = -forward[0];
314 right[2] = forward[1];
316 d = DotProduct(forward, right);
317 right[0] -= d * forward[0];
318 right[1] -= d * forward[1];
319 right[2] -= d * forward[2];
320 VectorNormalize(right);
321 CrossProduct(right, forward, up);
324 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
327 // LordHavoc: the old way, cryptic brute force...
340 PerpendicularVector( vr, dir );
341 CrossProduct( vr, vf, vup );
355 memcpy( im, m, sizeof( im ) );
364 memset( zrot, 0, sizeof( zrot ) );
365 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
367 zrot[0][0] = cos( DEG2RAD( degrees ) );
368 zrot[0][1] = sin( DEG2RAD( degrees ) );
369 zrot[1][0] = -sin( DEG2RAD( degrees ) );
370 zrot[1][1] = cos( DEG2RAD( degrees ) );
372 R_ConcatRotations( m, zrot, tmpmat );
373 R_ConcatRotations( tmpmat, im, rot );
375 for ( i = 0; i < 3; i++ )
376 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
378 // LordHavoc: on the path to unintelligible code...
388 angle = DEG2RAD(degrees);
397 PerpendicularVector(vr, dir);
398 CrossProduct(vr, vf, vu);
400 // m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0];
401 // m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1];
402 // m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2];
403 // im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2];
404 // im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2];
405 // im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2];
406 // zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0;
407 // zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0;
408 // zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1;
410 // tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
411 // tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
412 // tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
413 // tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
414 // tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
415 // tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
416 // tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
417 // tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
418 // tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
420 tmpmat[0][0] = vr[0] * c + vu[0] * -s;
421 tmpmat[0][1] = vr[0] * s + vu[0] * c;
422 // tmpmat[0][2] = vf[0];
423 tmpmat[1][0] = vr[1] * c + vu[1] * -s;
424 tmpmat[1][1] = vr[1] * s + vu[1] * c;
425 // tmpmat[1][2] = vf[1];
426 tmpmat[2][0] = vr[2] * c + vu[2] * -s;
427 tmpmat[2][1] = vr[2] * s + vu[2] * c;
428 // tmpmat[2][2] = vf[2];
430 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
431 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
432 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
433 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
434 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
435 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
436 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
437 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
438 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
440 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
441 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
442 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
443 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
444 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
445 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
446 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
447 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
448 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
450 // dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
451 // dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
452 // dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
454 dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
455 + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
456 + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
457 dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
458 + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
459 + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
460 dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
461 + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
462 + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
464 // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
469 angle = DEG2RAD(degrees);
478 // PerpendicularVector(vr, dir);
479 // CrossProduct(vr, vf, vu);
480 VectorVectors(vf, vr, vu);
482 t0 = vr[0] * c + vu[0] * -s;
483 t1 = vr[0] * s + vu[0] * c;
484 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
485 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
486 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
488 t0 = vr[1] * c + vu[1] * -s;
489 t1 = vr[1] * s + vu[1] * c;
490 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
491 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
492 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
494 t0 = vr[2] * c + vu[2] * -s;
495 t1 = vr[2] * s + vu[2] * c;
496 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
497 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
498 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
503 #pragma optimize( "", on )
506 /*-----------------------------------------------------------------*/
510 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
511 // assembly in an attempt to accelerate it further, very inefficient
512 // considering that signbits of the frustum planes only changed each
513 // frame, and the world planes changed only at load time.
514 // So, to optimize it further I took the obvious route of storing a function
515 // pointer in the plane struct itself, and shrunk each of the individual
516 // cases to a single return statement.
518 // realized axial cases would be a nice speedup for world geometry, although
519 // never useful for the frustum planes.
520 int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
521 int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
522 int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
523 int BoxOnPlaneSide0 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) < p->dist) << 1));}
524 int BoxOnPlaneSide1 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) < p->dist) << 1));}
525 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]) < p->dist) << 1));}
526 int BoxOnPlaneSide3 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]) >= p->dist) | (((p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]) < p->dist) << 1));}
527 int BoxOnPlaneSide4 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]) < p->dist) << 1));}
528 int BoxOnPlaneSide5 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]) >= p->dist) | (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]) < p->dist) << 1));}
529 int BoxOnPlaneSide6 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) >= p->dist) | (((p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) < p->dist) << 1));}
530 int BoxOnPlaneSide7 (vec3_t emins, vec3_t emaxs, mplane_t *p) {return (((p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]) >= p->dist) | (((p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]) < p->dist) << 1));}
532 void BoxOnPlaneSideClassify(mplane_t *p)
537 p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
540 p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
543 p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
546 if (p->normal[2] < 0) // 4
548 if (p->normal[1] < 0) // 2
550 if (p->normal[0] < 0) // 1
551 p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
553 p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
557 if (p->normal[0] < 0) // 1
558 p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
560 p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
565 if (p->normal[1] < 0) // 2
567 if (p->normal[0] < 0) // 1
568 p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
570 p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
574 if (p->normal[0] < 0) // 1
575 p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
577 p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
584 void PlaneClassify(mplane_t *p)
586 if (p->normal[0] == 1)
588 else if (p->normal[1] == 1)
590 else if (p->normal[2] == 1)
594 BoxOnPlaneSideClassify(p);
597 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
599 double angle, sr, sp, sy, cr, cp, cy;
601 angle = angles[YAW] * (M_PI*2 / 360);
604 angle = angles[PITCH] * (M_PI*2 / 360);
615 angle = angles[ROLL] * (M_PI*2 / 360);
620 right[0] = -1*(sr*sp*cy+cr*-sy);
621 right[1] = -1*(sr*sp*sy+cr*cy);
622 right[2] = -1*(sr*cp);
626 up[0] = (cr*sp*cy+-sr*-sy);
627 up[1] = (cr*sp*sy+-sr*cy);
633 void AngleVectorsFLU (vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
635 double angle, sr, sp, sy, cr, cp, cy;
637 angle = angles[YAW] * (M_PI*2 / 360);
640 angle = angles[PITCH] * (M_PI*2 / 360);
651 angle = angles[ROLL] * (M_PI*2 / 360);
656 left[0] = sr*sp*cy+cr*-sy;
657 left[1] = sr*sp*sy+cr*cy;
662 up[0] = cr*sp*cy+-sr*-sy;
663 up[1] = cr*sp*sy+-sr*cy;
669 void AngleMatrix (vec3_t angles, vec3_t translate, vec_t matrix[][4])
671 double angle, sr, sp, sy, cr, cp, cy;
673 angle = angles[YAW] * (M_PI*2 / 360);
676 angle = angles[PITCH] * (M_PI*2 / 360);
679 angle = angles[ROLL] * (M_PI*2 / 360);
682 matrix[0][0] = cp*cy;
683 matrix[0][1] = sr*sp*cy+cr*-sy;
684 matrix[0][2] = cr*sp*cy+-sr*-sy;
685 matrix[0][3] = translate[0];
686 matrix[1][0] = cp*sy;
687 matrix[1][1] = sr*sp*sy+cr*cy;
688 matrix[1][2] = cr*sp*sy+-sr*cy;
689 matrix[1][3] = translate[1];
691 matrix[2][1] = sr*cp;
692 matrix[2][2] = cr*cp;
693 matrix[2][3] = translate[2];
696 int VectorCompare (vec3_t v1, vec3_t v2)
700 for (i=0 ; i<3 ; i++)
707 void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
709 vecc[0] = veca[0] + scale*vecb[0];
710 vecc[1] = veca[1] + scale*vecb[1];
711 vecc[2] = veca[2] + scale*vecb[2];
715 vec_t _DotProduct (vec3_t v1, vec3_t v2)
717 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
720 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
722 out[0] = veca[0]-vecb[0];
723 out[1] = veca[1]-vecb[1];
724 out[2] = veca[2]-vecb[2];
727 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
729 out[0] = veca[0]+vecb[0];
730 out[1] = veca[1]+vecb[1];
731 out[2] = veca[2]+vecb[2];
734 void _VectorCopy (vec3_t in, vec3_t out)
741 // LordHavoc: changed CrossProduct to a #define
743 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
745 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
746 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
747 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
751 double sqrt(double x);
753 vec_t Length(vec3_t v)
759 for (i=0 ; i< 3 ; i++)
761 length = sqrt (length); // FIXME
767 // LordHavoc: fixme: do more research on gcc assembly so that qftol_minushalf and result will not be considered unused
768 static double qftol_minushalf = -0.5;
780 #else // gcc hopefully
781 asm("fldl v\n\tfaddl qftol_minushalf\n\tfistpl result");
787 // LordHavoc: renamed these to Length, and made the normal ones #define
788 float VectorNormalizeLength (vec3_t v)
790 float length, ilength;
792 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
793 length = sqrt (length); // FIXME
807 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
809 float length, ilength;
811 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
812 length = sqrt (length); // FIXME
817 dest[0] = v[0] * ilength;
818 dest[1] = v[1] * ilength;
819 dest[2] = v[2] * ilength;
822 dest[0] = dest[1] = dest[2] = 0;
828 void _VectorInverse (vec3_t v)
835 void _VectorScale (vec3_t in, vec_t scale, vec3_t out)
837 out[0] = in[0]*scale;
838 out[1] = in[1]*scale;
839 out[2] = in[2]*scale;
857 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
859 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
860 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
861 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
862 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
863 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
864 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
865 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
866 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
867 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
876 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
878 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
879 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
880 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
881 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
882 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
883 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
884 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
885 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
886 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
887 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
888 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
889 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
897 Returns mathematically correct (floor-based) quotient and remainder for
898 numer and denom, both of which should contain no fractional part. The
899 quotient must fit in 32 bits.
903 void FloorDivMod (double numer, double denom, int *quotient,
911 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
913 // if ((floor(numer) != numer) || (floor(denom) != denom))
914 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
921 x = floor(numer / denom);
923 r = (int)floor(numer - (x * denom));
928 // perform operations with positive values, and fix mod to make floor-based
930 x = floor(-numer / denom);
932 r = (int)floor(-numer - (x * denom));
947 GreatestCommonDivisor
950 int GreatestCommonDivisor (int i1, int i2)
956 return GreatestCommonDivisor (i2, i1 % i2);
962 return GreatestCommonDivisor (i1, i2 % i1);
967 void Mathlib_Init(void)
971 // LordHavoc: setup 1.0f / N table for quick recipricols of integers
973 for (a = 1;a < 4096;a++)
974 ixtable[a] = 1.0f / a;