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;
30 /*-----------------------------------------------------------------*/
32 float m_bytenormals[NUMVERTEXNORMALS][3] =
34 {-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188},
35 {-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017},
36 {-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000},
37 {0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718},
38 {0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651},
39 {0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651},
40 {0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188},
41 {0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567},
42 {-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191},
43 {-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856},
44 {-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325},
45 {-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863},
46 {-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621},
47 {-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000},
48 {0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863},
49 {0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460},
50 {0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242},
51 {-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863},
52 {0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017},
53 {0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460},
54 {0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000},
55 {0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621},
56 {0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785},
57 {0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325},
58 {0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567},
59 {0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000},
60 {1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866},
61 {0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000},
62 {0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866},
63 {0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
64 {0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856},
65 {0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866},
66 {0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567},
67 {0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731},
68 {0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856},
69 {0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718},
70 {0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785},
71 {0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191},
72 {0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718},
73 {-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651},
74 {-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188},
75 {-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056},
76 {0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423},
77 {0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188},
78 {-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056},
79 {0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718},
80 {0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651},
81 {0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188},
82 {0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863},
83 {0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785},
84 {0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325},
85 {0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242},
86 {0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460},
87 {0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242},
88 {0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460},
89 {0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621},
90 {0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863},
91 {-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460},
92 {-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621},
93 {-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000},
94 {-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
95 {-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856},
96 {-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325},
97 {-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188},
98 {-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017},
99 {-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785},
100 {-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188},
101 {0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017},
102 {0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651},
103 {0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191},
104 {0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000},
105 {-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000},
106 {-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000},
107 {-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856},
108 {-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000},
109 {-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866},
110 {-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567},
111 {-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731},
112 {-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191},
113 {-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785},
114 {-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325},
117 byte NormalToByte(vec3_t n)
120 float bestdistance, distance;
123 bestdistance = DotProduct (n, m_bytenormals[0]);
124 for (i = 1;i < NUMVERTEXNORMALS;i++)
126 distance = DotProduct (n, m_bytenormals[i]);
127 if (distance > bestdistance)
129 bestdistance = distance;
136 // note: uses byte partly to force unsigned for the validity check
137 void ByteToNormal(byte num, vec3_t n)
139 if (num < NUMVERTEXNORMALS)
140 VectorCopy(m_bytenormals[num], n)
142 VectorClear(n) // FIXME: complain?
145 float Q_RSqrt(float number)
152 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
153 return y * (1.5f - (number * 0.5f * y * y));
156 void _VectorNormalizeFast(vec3_t v)
160 number = DotProduct(v, v);
164 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
165 y = y * (1.5f - (number * 0.5f * y * y));
167 VectorScale(v, y, v);
172 // LordHavoc: no longer used at all
173 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
176 // LordHavoc: the old way...
181 inv_denom = 1.0F / DotProduct( normal, normal );
183 d = DotProduct( normal, p ) * inv_denom;
185 n[0] = normal[0] * inv_denom;
186 n[1] = normal[1] * inv_denom;
187 n[2] = normal[2] * inv_denom;
189 dst[0] = p[0] - d * n[0];
190 dst[1] = p[1] - d * n[1];
191 dst[2] = p[2] - d * n[2];
193 // LordHavoc: optimized to death and beyond
196 // LordHavoc: the normal is a unit vector by definition,
197 // therefore inv_denom was pointless.
198 d = DotProduct(normal, p);
199 dst[0] = p[0] - d * normal[0];
200 dst[1] = p[1] - d * normal[1];
201 dst[2] = p[2] - d * normal[2];
206 // assumes "src" is normalized
207 void PerpendicularVector( vec3_t dst, const vec3_t src )
210 // LordHavoc: the old way...
216 // find the smallest magnitude axially aligned vector
218 for ( pos = 0, i = 0; i < 3; i++ )
220 if ( fabs( src[i] ) < minelem )
223 minelem = fabs( src[i] );
226 VectorClear(tempvec);
229 // project the point onto the plane defined by src
230 ProjectPointOnPlane( dst, tempvec, src );
232 // normalize the result
233 VectorNormalize(dst);
235 // LordHavoc: optimized to death and beyond
249 minelem = fabs(src[0]);
250 if (fabs(src[1]) < minelem)
253 minelem = fabs(src[1]);
255 if (fabs(src[2]) < minelem)
259 dst[0] -= src[pos] * src[0];
260 dst[1] -= src[pos] * src[1];
261 dst[2] -= src[pos] * src[2];
263 // normalize the result
264 VectorNormalize(dst);
286 #pragma optimize( "", off )
290 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
291 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
295 right[0] = forward[2];
296 right[1] = -forward[0];
297 right[2] = forward[1];
299 d = DotProduct(forward, right);
300 right[0] -= d * forward[0];
301 right[1] -= d * forward[1];
302 right[2] -= d * forward[2];
303 VectorNormalize(right);
304 CrossProduct(right, forward, up);
307 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
310 // LordHavoc: the old way, cryptic brute force...
323 PerpendicularVector( vr, dir );
324 CrossProduct( vr, vf, vup );
338 memcpy( im, m, sizeof( im ) );
347 memset( zrot, 0, sizeof( zrot ) );
348 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
350 zrot[0][0] = cos( DEG2RAD( degrees ) );
351 zrot[0][1] = sin( DEG2RAD( degrees ) );
352 zrot[1][0] = -sin( DEG2RAD( degrees ) );
353 zrot[1][1] = cos( DEG2RAD( degrees ) );
355 R_ConcatRotations( m, zrot, tmpmat );
356 R_ConcatRotations( tmpmat, im, rot );
358 for ( i = 0; i < 3; i++ )
359 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
361 // LordHavoc: on the path to unintelligible code...
371 angle = DEG2RAD(degrees);
380 PerpendicularVector(vr, dir);
381 CrossProduct(vr, vf, vu);
383 // m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0];
384 // m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1];
385 // m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2];
386 // im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2];
387 // im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2];
388 // im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2];
389 // zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0;
390 // zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0;
391 // zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1;
393 // tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
394 // tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
395 // tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
396 // tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
397 // tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
398 // tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
399 // tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
400 // tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
401 // tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
403 tmpmat[0][0] = vr[0] * c + vu[0] * -s;
404 tmpmat[0][1] = vr[0] * s + vu[0] * c;
405 // tmpmat[0][2] = vf[0];
406 tmpmat[1][0] = vr[1] * c + vu[1] * -s;
407 tmpmat[1][1] = vr[1] * s + vu[1] * c;
408 // tmpmat[1][2] = vf[1];
409 tmpmat[2][0] = vr[2] * c + vu[2] * -s;
410 tmpmat[2][1] = vr[2] * s + vu[2] * c;
411 // tmpmat[2][2] = vf[2];
413 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
414 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
415 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
416 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
417 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
418 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
419 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
420 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
421 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
423 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
424 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
425 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
426 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
427 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
428 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
429 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
430 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
431 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
433 // dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
434 // dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
435 // dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
437 dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
438 + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
439 + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
440 dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
441 + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
442 + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
443 dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
444 + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
445 + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
447 // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
452 angle = DEG2RAD(degrees);
461 // PerpendicularVector(vr, dir);
462 // CrossProduct(vr, vf, vu);
463 VectorVectors(vf, vr, vu);
465 t0 = vr[0] * c + vu[0] * -s;
466 t1 = vr[0] * s + vu[0] * c;
467 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
468 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
469 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
471 t0 = vr[1] * c + vu[1] * -s;
472 t1 = vr[1] * s + vu[1] * c;
473 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
474 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
475 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
477 t0 = vr[2] * c + vu[2] * -s;
478 t1 = vr[2] * s + vu[2] * c;
479 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
480 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
481 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
486 #pragma optimize( "", on )
489 /*-----------------------------------------------------------------*/
493 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
494 // assembly in an attempt to accelerate it further, very inefficient
495 // considering that signbits of the frustum planes only changed each
496 // frame, and the world planes changed only at load time.
497 // So, to optimize it further I took the obvious route of storing a function
498 // pointer in the plane struct itself, and shrunk each of the individual
499 // cases to a single return statement.
501 // realized axial cases would be a nice speedup for world geometry, although
502 // never useful for the frustum planes.
503 int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
504 int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
505 int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
506 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));}
507 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));}
508 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));}
509 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));}
510 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));}
511 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));}
512 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));}
513 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));}
515 void BoxOnPlaneSideClassify(mplane_t *p)
520 p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
523 p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
526 p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
529 if (p->normal[2] < 0) // 4
531 if (p->normal[1] < 0) // 2
533 if (p->normal[0] < 0) // 1
534 p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
536 p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
540 if (p->normal[0] < 0) // 1
541 p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
543 p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
548 if (p->normal[1] < 0) // 2
550 if (p->normal[0] < 0) // 1
551 p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
553 p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
557 if (p->normal[0] < 0) // 1
558 p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
560 p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
567 void PlaneClassify(mplane_t *p)
569 if (p->normal[0] == 1)
571 else if (p->normal[1] == 1)
573 else if (p->normal[2] == 1)
577 BoxOnPlaneSideClassify(p);
580 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
583 float sr, sp, sy, cr, cp, cy;
585 angle = angles[YAW] * (M_PI*2 / 360);
588 angle = angles[PITCH] * (M_PI*2 / 360);
591 // LordHavoc: this is only to hush up gcc complaining about 'might be used uninitialized' variables
592 // (they are NOT used uninitialized, but oh well)
597 angle = angles[ROLL] * (M_PI*2 / 360);
610 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
611 right[1] = (-1*sr*sp*sy+-1*cr*cy);
616 up[0] = (cr*sp*cy+-sr*-sy);
617 up[1] = (cr*sp*sy+-sr*cy);
622 int VectorCompare (vec3_t v1, vec3_t v2)
626 for (i=0 ; i<3 ; i++)
633 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
635 vecc[0] = veca[0] + scale*vecb[0];
636 vecc[1] = veca[1] + scale*vecb[1];
637 vecc[2] = veca[2] + scale*vecb[2];
641 vec_t _DotProduct (vec3_t v1, vec3_t v2)
643 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
646 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
648 out[0] = veca[0]-vecb[0];
649 out[1] = veca[1]-vecb[1];
650 out[2] = veca[2]-vecb[2];
653 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
655 out[0] = veca[0]+vecb[0];
656 out[1] = veca[1]+vecb[1];
657 out[2] = veca[2]+vecb[2];
660 void _VectorCopy (vec3_t in, vec3_t out)
667 // LordHavoc: changed CrossProduct to a #define
669 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
671 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
672 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
673 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
677 double sqrt(double x);
679 vec_t Length(vec3_t v)
685 for (i=0 ; i< 3 ; i++)
687 length = sqrt (length); // FIXME
692 // LordHavoc: renamed these to Length, and made the normal ones #define
693 float VectorNormalizeLength (vec3_t v)
695 float length, ilength;
697 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
698 length = sqrt (length); // FIXME
712 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
714 float length, ilength;
716 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
717 length = sqrt (length); // FIXME
722 dest[0] = v[0] * ilength;
723 dest[1] = v[1] * ilength;
724 dest[2] = v[2] * ilength;
727 dest[0] = dest[1] = dest[2] = 0;
733 void _VectorInverse (vec3_t v)
740 void _VectorScale (vec3_t in, vec_t scale, vec3_t out)
742 out[0] = in[0]*scale;
743 out[1] = in[1]*scale;
744 out[2] = in[2]*scale;
762 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
764 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
765 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
766 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
767 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
768 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
769 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
770 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
771 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
772 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
781 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
783 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
784 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
785 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
786 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
787 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
788 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
789 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
790 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
791 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
792 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
793 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
794 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
802 Returns mathematically correct (floor-based) quotient and remainder for
803 numer and denom, both of which should contain no fractional part. The
804 quotient must fit in 32 bits.
808 void FloorDivMod (double numer, double denom, int *quotient,
816 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
818 // if ((floor(numer) != numer) || (floor(denom) != denom))
819 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
826 x = floor(numer / denom);
828 r = (int)floor(numer - (x * denom));
833 // perform operations with positive values, and fix mod to make floor-based
835 x = floor(-numer / denom);
837 r = (int)floor(-numer - (x * denom));
852 GreatestCommonDivisor
855 int GreatestCommonDivisor (int i1, int i2)
861 return GreatestCommonDivisor (i2, i1 % i2);
867 return GreatestCommonDivisor (i1, i2 % i1);