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
693 // LordHavoc: fixme: do more research on gcc assembly so that qftol_minushalf and result will not be considered unused
694 static double qftol_minushalf = -0.5;
706 #else // gcc hopefully
707 asm("fldl v\n\tfaddl qftol_minushalf\n\tfistpl result");
713 // LordHavoc: renamed these to Length, and made the normal ones #define
714 float VectorNormalizeLength (vec3_t v)
716 float length, ilength;
718 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
719 length = sqrt (length); // FIXME
733 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
735 float length, ilength;
737 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
738 length = sqrt (length); // FIXME
743 dest[0] = v[0] * ilength;
744 dest[1] = v[1] * ilength;
745 dest[2] = v[2] * ilength;
748 dest[0] = dest[1] = dest[2] = 0;
754 void _VectorInverse (vec3_t v)
761 void _VectorScale (vec3_t in, vec_t scale, vec3_t out)
763 out[0] = in[0]*scale;
764 out[1] = in[1]*scale;
765 out[2] = in[2]*scale;
783 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
785 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
786 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
787 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
788 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
789 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
790 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
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];
802 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
804 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
805 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
806 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
807 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
808 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
809 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
810 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
811 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
812 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
813 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
814 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
815 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
823 Returns mathematically correct (floor-based) quotient and remainder for
824 numer and denom, both of which should contain no fractional part. The
825 quotient must fit in 32 bits.
829 void FloorDivMod (double numer, double denom, int *quotient,
837 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
839 // if ((floor(numer) != numer) || (floor(denom) != denom))
840 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
847 x = floor(numer / denom);
849 r = (int)floor(numer - (x * denom));
854 // perform operations with positive values, and fix mod to make floor-based
856 x = floor(-numer / denom);
858 r = (int)floor(-numer - (x * denom));
873 GreatestCommonDivisor
876 int GreatestCommonDivisor (int i1, int i2)
882 return GreatestCommonDivisor (i2, i1 % i2);
888 return GreatestCommonDivisor (i1, i2 % i1);