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 VectorNormalize(right);
305 CrossProduct(right, forward, up);
308 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
311 // LordHavoc: the old way, cryptic brute force...
324 PerpendicularVector( vr, dir );
325 CrossProduct( vr, vf, vup );
339 memcpy( im, m, sizeof( im ) );
348 memset( zrot, 0, sizeof( zrot ) );
349 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
351 zrot[0][0] = cos( DEG2RAD( degrees ) );
352 zrot[0][1] = sin( DEG2RAD( degrees ) );
353 zrot[1][0] = -sin( DEG2RAD( degrees ) );
354 zrot[1][1] = cos( DEG2RAD( degrees ) );
356 R_ConcatRotations( m, zrot, tmpmat );
357 R_ConcatRotations( tmpmat, im, rot );
359 for ( i = 0; i < 3; i++ )
360 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
362 // LordHavoc: on the path to unintelligible code...
372 angle = DEG2RAD(degrees);
381 PerpendicularVector(vr, dir);
382 CrossProduct(vr, vf, vu);
384 // m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0];
385 // m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1];
386 // m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2];
387 // im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2];
388 // im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2];
389 // im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2];
390 // zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0;
391 // zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0;
392 // zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1;
394 // tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
395 // tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
396 // tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
397 // tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
398 // tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
399 // tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
400 // tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
401 // tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
402 // tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
404 tmpmat[0][0] = vr[0] * c + vu[0] * -s;
405 tmpmat[0][1] = vr[0] * s + vu[0] * c;
406 // tmpmat[0][2] = vf[0];
407 tmpmat[1][0] = vr[1] * c + vu[1] * -s;
408 tmpmat[1][1] = vr[1] * s + vu[1] * c;
409 // tmpmat[1][2] = vf[1];
410 tmpmat[2][0] = vr[2] * c + vu[2] * -s;
411 tmpmat[2][1] = vr[2] * s + vu[2] * c;
412 // tmpmat[2][2] = vf[2];
414 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
415 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
416 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
417 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
418 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
419 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
420 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
421 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
422 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
424 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
425 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
426 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
427 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
428 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
429 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
430 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
431 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
432 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
434 // dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
435 // dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
436 // dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
438 dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
439 + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
440 + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
441 dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
442 + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
443 + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
444 dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
445 + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
446 + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
448 // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
453 angle = DEG2RAD(degrees);
462 // PerpendicularVector(vr, dir);
463 // CrossProduct(vr, vf, vu);
464 VectorVectors(vf, vr, vu);
466 t0 = vr[0] * c + vu[0] * -s;
467 t1 = vr[0] * s + vu[0] * c;
468 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
469 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
470 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
472 t0 = vr[1] * c + vu[1] * -s;
473 t1 = vr[1] * s + vu[1] * c;
474 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
475 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
476 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
478 t0 = vr[2] * c + vu[2] * -s;
479 t1 = vr[2] * s + vu[2] * c;
480 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
481 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
482 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
487 #pragma optimize( "", on )
490 /*-----------------------------------------------------------------*/
494 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
495 // assembly in an attempt to accelerate it further, very inefficient
496 // considering that signbits of the frustum planes only changed each
497 // frame, and the world planes changed only at load time.
498 // So, to optimize it further I took the obvious route of storing a function
499 // pointer in the plane struct itself, and shrunk each of the individual
500 // cases to a single return statement.
502 // realized axial cases would be a nice speedup for world geometry, although
503 // never useful for the frustum planes.
504 int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
505 int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
506 int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
507 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));}
508 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));}
509 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));}
510 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));}
511 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));}
512 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));}
513 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));}
514 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));}
516 void BoxOnPlaneSideClassify(mplane_t *p)
521 p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
524 p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
527 p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
530 if (p->normal[2] < 0) // 4
532 if (p->normal[1] < 0) // 2
534 if (p->normal[0] < 0) // 1
535 p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
537 p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
541 if (p->normal[0] < 0) // 1
542 p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
544 p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
549 if (p->normal[1] < 0) // 2
551 if (p->normal[0] < 0) // 1
552 p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
554 p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
558 if (p->normal[0] < 0) // 1
559 p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
561 p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
568 void PlaneClassify(mplane_t *p)
570 if (p->normal[0] == 1)
572 else if (p->normal[1] == 1)
574 else if (p->normal[2] == 1)
578 BoxOnPlaneSideClassify(p);
581 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
584 float sr, sp, sy, cr, cp, cy;
586 angle = angles[YAW] * (M_PI*2 / 360);
589 angle = angles[PITCH] * (M_PI*2 / 360);
592 // LordHavoc: this is only to hush up gcc complaining about 'might be used uninitialized' variables
593 // (they are NOT used uninitialized, but oh well)
598 angle = angles[ROLL] * (M_PI*2 / 360);
611 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
612 right[1] = (-1*sr*sp*sy+-1*cr*cy);
617 up[0] = (cr*sp*cy+-sr*-sy);
618 up[1] = (cr*sp*sy+-sr*cy);
623 int VectorCompare (vec3_t v1, vec3_t v2)
627 for (i=0 ; i<3 ; i++)
634 void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
636 vecc[0] = veca[0] + scale*vecb[0];
637 vecc[1] = veca[1] + scale*vecb[1];
638 vecc[2] = veca[2] + scale*vecb[2];
642 vec_t _DotProduct (vec3_t v1, vec3_t v2)
644 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
647 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
649 out[0] = veca[0]-vecb[0];
650 out[1] = veca[1]-vecb[1];
651 out[2] = veca[2]-vecb[2];
654 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
656 out[0] = veca[0]+vecb[0];
657 out[1] = veca[1]+vecb[1];
658 out[2] = veca[2]+vecb[2];
661 void _VectorCopy (vec3_t in, vec3_t out)
668 // LordHavoc: changed CrossProduct to a #define
670 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
672 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
673 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
674 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
678 double sqrt(double x);
680 vec_t Length(vec3_t v)
686 for (i=0 ; i< 3 ; i++)
688 length = sqrt (length); // FIXME
694 // LordHavoc: fixme: do more research on gcc assembly so that qftol_minushalf and result will not be considered unused
695 static double qftol_minushalf = -0.5;
707 #else // gcc hopefully
708 asm("fldl v\n\tfaddl qftol_minushalf\n\tfistpl result");
714 // LordHavoc: renamed these to Length, and made the normal ones #define
715 float VectorNormalizeLength (vec3_t v)
717 float length, ilength;
719 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
720 length = sqrt (length); // FIXME
734 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
736 float length, ilength;
738 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
739 length = sqrt (length); // FIXME
744 dest[0] = v[0] * ilength;
745 dest[1] = v[1] * ilength;
746 dest[2] = v[2] * ilength;
749 dest[0] = dest[1] = dest[2] = 0;
755 void _VectorInverse (vec3_t v)
762 void _VectorScale (vec3_t in, vec_t scale, vec3_t out)
764 out[0] = in[0]*scale;
765 out[1] = in[1]*scale;
766 out[2] = in[2]*scale;
784 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
786 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
787 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
788 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
789 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
790 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
791 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
792 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
793 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
794 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
803 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
805 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
806 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
807 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
808 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
809 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
810 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
811 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
812 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
813 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
814 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
815 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
816 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
824 Returns mathematically correct (floor-based) quotient and remainder for
825 numer and denom, both of which should contain no fractional part. The
826 quotient must fit in 32 bits.
830 void FloorDivMod (double numer, double denom, int *quotient,
838 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
840 // if ((floor(numer) != numer) || (floor(denom) != denom))
841 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
848 x = floor(numer / denom);
850 r = (int)floor(numer - (x * denom));
855 // perform operations with positive values, and fix mod to make floor-based
857 x = floor(-numer / denom);
859 r = (int)floor(-numer - (x * denom));
874 GreatestCommonDivisor
877 int GreatestCommonDivisor (int i1, int i2)
883 return GreatestCommonDivisor (i2, i1 % i2);
889 return GreatestCommonDivisor (i1, i2 % i1);
894 void Mathlib_Init(void)
898 // LordHavoc: setup 1.0f / N table for quick recipricols of integers
900 for (a = 1;a < 4096;a++)
901 ixtable[a] = 1.0f / a;