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?
146 // LordHavoc: no longer used at all
147 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
150 // LordHavoc: the old way...
155 inv_denom = 1.0F / DotProduct( normal, normal );
157 d = DotProduct( normal, p ) * inv_denom;
159 n[0] = normal[0] * inv_denom;
160 n[1] = normal[1] * inv_denom;
161 n[2] = normal[2] * inv_denom;
163 dst[0] = p[0] - d * n[0];
164 dst[1] = p[1] - d * n[1];
165 dst[2] = p[2] - d * n[2];
167 // LordHavoc: optimized to death and beyond
170 // LordHavoc: the normal is a unit vector by definition,
171 // therefore inv_denom was pointless.
172 d = DotProduct(normal, p);
173 dst[0] = p[0] - d * normal[0];
174 dst[1] = p[1] - d * normal[1];
175 dst[2] = p[2] - d * normal[2];
180 // assumes "src" is normalized
181 void PerpendicularVector( vec3_t dst, const vec3_t src )
184 // LordHavoc: the old way...
190 // find the smallest magnitude axially aligned vector
192 for ( pos = 0, i = 0; i < 3; i++ )
194 if ( fabs( src[i] ) < minelem )
197 minelem = fabs( src[i] );
200 VectorClear(tempvec);
203 // project the point onto the plane defined by src
204 ProjectPointOnPlane( dst, tempvec, src );
206 // normalize the result
207 VectorNormalize(dst);
209 // LordHavoc: optimized to death and beyond
223 minelem = fabs(src[0]);
224 if (fabs(src[1]) < minelem)
227 minelem = fabs(src[1]);
229 if (fabs(src[2]) < minelem)
233 dst[0] -= src[pos] * src[0];
234 dst[1] -= src[pos] * src[1];
235 dst[2] -= src[pos] * src[2];
237 // normalize the result
238 VectorNormalize(dst);
260 #pragma optimize( "", off )
264 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
265 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
269 right[0] = forward[2];
270 right[1] = -forward[0];
271 right[2] = forward[1];
273 d = DotProduct(forward, right);
274 right[0] -= d * forward[0];
275 right[1] -= d * forward[1];
276 right[2] -= d * forward[2];
277 VectorNormalize(right);
278 CrossProduct(right, forward, up);
281 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
284 // LordHavoc: the old way, cryptic brute force...
297 PerpendicularVector( vr, dir );
298 CrossProduct( vr, vf, vup );
312 memcpy( im, m, sizeof( im ) );
321 memset( zrot, 0, sizeof( zrot ) );
322 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
324 zrot[0][0] = cos( DEG2RAD( degrees ) );
325 zrot[0][1] = sin( DEG2RAD( degrees ) );
326 zrot[1][0] = -sin( DEG2RAD( degrees ) );
327 zrot[1][1] = cos( DEG2RAD( degrees ) );
329 R_ConcatRotations( m, zrot, tmpmat );
330 R_ConcatRotations( tmpmat, im, rot );
332 for ( i = 0; i < 3; i++ )
333 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
335 // LordHavoc: on the path to unintelligible code...
345 angle = DEG2RAD(degrees);
354 PerpendicularVector(vr, dir);
355 CrossProduct(vr, vf, vu);
357 // m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0];
358 // m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1];
359 // m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2];
360 // im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2];
361 // im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2];
362 // im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2];
363 // zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0;
364 // zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0;
365 // zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1;
367 // tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
368 // tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
369 // tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
370 // tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
371 // tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
372 // tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
373 // tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
374 // tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
375 // tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
377 tmpmat[0][0] = vr[0] * c + vu[0] * -s;
378 tmpmat[0][1] = vr[0] * s + vu[0] * c;
379 // tmpmat[0][2] = vf[0];
380 tmpmat[1][0] = vr[1] * c + vu[1] * -s;
381 tmpmat[1][1] = vr[1] * s + vu[1] * c;
382 // tmpmat[1][2] = vf[1];
383 tmpmat[2][0] = vr[2] * c + vu[2] * -s;
384 tmpmat[2][1] = vr[2] * s + vu[2] * c;
385 // tmpmat[2][2] = vf[2];
387 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
388 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
389 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
390 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
391 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
392 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
393 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
394 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
395 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
397 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
398 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
399 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
400 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
401 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
402 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
403 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
404 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
405 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
407 // dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
408 // dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
409 // dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
411 dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
412 + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
413 + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
414 dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
415 + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
416 + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
417 dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
418 + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
419 + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
421 // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
426 angle = DEG2RAD(degrees);
435 // PerpendicularVector(vr, dir);
436 // CrossProduct(vr, vf, vu);
437 VectorVectors(vf, vr, vu);
439 t0 = vr[0] * c + vu[0] * -s;
440 t1 = vr[0] * s + vu[0] * c;
441 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
442 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
443 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
445 t0 = vr[1] * c + vu[1] * -s;
446 t1 = vr[1] * s + vu[1] * c;
447 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
448 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
449 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
451 t0 = vr[2] * c + vu[2] * -s;
452 t1 = vr[2] * s + vu[2] * c;
453 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
454 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
455 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
460 #pragma optimize( "", on )
463 /*-----------------------------------------------------------------*/
467 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
468 // assembly in an attempt to accelerate it further, very inefficient
469 // considering that signbits of the frustum planes only changed each
470 // frame, and the world planes changed only at load time.
471 // So, to optimize it further I took the obvious route of storing a function
472 // pointer in the plane struct itself, and shrunk each of the individual
473 // cases to a single return statement.
475 // realized axial cases would be a nice speedup for world geometry, although
476 // never useful for the frustum planes.
477 int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
478 int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
479 int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
480 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));}
481 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));}
482 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));}
483 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));}
484 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));}
485 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));}
486 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));}
487 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));}
489 void BoxOnPlaneSideClassify(mplane_t *p)
494 p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
497 p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
500 p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
503 if (p->normal[2] < 0) // 4
505 if (p->normal[1] < 0) // 2
507 if (p->normal[0] < 0) // 1
508 p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
510 p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
514 if (p->normal[0] < 0) // 1
515 p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
517 p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
522 if (p->normal[1] < 0) // 2
524 if (p->normal[0] < 0) // 1
525 p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
527 p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
531 if (p->normal[0] < 0) // 1
532 p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
534 p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
541 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
544 float sr, sp, sy, cr, cp, cy;
546 angle = angles[YAW] * (M_PI*2 / 360);
549 angle = angles[PITCH] * (M_PI*2 / 360);
552 // LordHavoc: this is only to hush up gcc complaining about 'might be used uninitialized' variables
553 // (they are NOT used uninitialized, but oh well)
558 angle = angles[ROLL] * (M_PI*2 / 360);
571 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
572 right[1] = (-1*sr*sp*sy+-1*cr*cy);
577 up[0] = (cr*sp*cy+-sr*-sy);
578 up[1] = (cr*sp*sy+-sr*cy);
583 int VectorCompare (vec3_t v1, vec3_t v2)
587 for (i=0 ; i<3 ; i++)
594 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
596 vecc[0] = veca[0] + scale*vecb[0];
597 vecc[1] = veca[1] + scale*vecb[1];
598 vecc[2] = veca[2] + scale*vecb[2];
602 vec_t _DotProduct (vec3_t v1, vec3_t v2)
604 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
607 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
609 out[0] = veca[0]-vecb[0];
610 out[1] = veca[1]-vecb[1];
611 out[2] = veca[2]-vecb[2];
614 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
616 out[0] = veca[0]+vecb[0];
617 out[1] = veca[1]+vecb[1];
618 out[2] = veca[2]+vecb[2];
621 void _VectorCopy (vec3_t in, vec3_t out)
628 // LordHavoc: changed CrossProduct to a #define
630 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
632 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
633 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
634 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
638 double sqrt(double x);
640 vec_t Length(vec3_t v)
646 for (i=0 ; i< 3 ; i++)
648 length = sqrt (length); // FIXME
653 // LordHavoc: renamed these to Length, and made the normal ones #define
654 float VectorNormalizeLength (vec3_t v)
656 float length, ilength;
658 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
659 length = sqrt (length); // FIXME
673 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
675 float length, ilength;
677 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
678 length = sqrt (length); // FIXME
683 dest[0] = v[0] * ilength;
684 dest[1] = v[1] * ilength;
685 dest[2] = v[2] * ilength;
688 dest[0] = dest[1] = dest[2] = 0;
694 void VectorInverse (vec3_t v)
701 void VectorScale (vec3_t in, vec_t scale, vec3_t out)
703 out[0] = in[0]*scale;
704 out[1] = in[1]*scale;
705 out[2] = in[2]*scale;
723 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
725 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
726 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
727 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
728 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
729 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
730 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
731 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
732 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
733 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
742 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
744 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
745 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
746 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
747 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
748 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
749 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
750 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
751 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
752 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
753 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
754 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
755 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
763 Returns mathematically correct (floor-based) quotient and remainder for
764 numer and denom, both of which should contain no fractional part. The
765 quotient must fit in 32 bits.
769 void FloorDivMod (double numer, double denom, int *quotient,
777 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
779 // if ((floor(numer) != numer) || (floor(denom) != denom))
780 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
787 x = floor(numer / denom);
789 r = (int)floor(numer - (x * denom));
794 // perform operations with positive values, and fix mod to make floor-based
796 x = floor(-numer / denom);
798 r = (int)floor(-numer - (x * denom));
813 GreatestCommonDivisor
816 int GreatestCommonDivisor (int i1, int i2)
822 return GreatestCommonDivisor (i2, i1 % i2);
828 return GreatestCommonDivisor (i1, i2 % i1);