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 #define DEG2RAD( a ) ( a * M_PI ) / 180.0F
34 float m_bytenormals[NUMVERTEXNORMALS][3] =
36 {-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188},
37 {-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017},
38 {-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000},
39 {0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718},
40 {0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651},
41 {0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651},
42 {0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188},
43 {0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567},
44 {-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191},
45 {-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856},
46 {-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325},
47 {-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863},
48 {-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621},
49 {-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000},
50 {0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863},
51 {0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460},
52 {0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242},
53 {-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863},
54 {0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017},
55 {0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460},
56 {0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000},
57 {0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621},
58 {0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785},
59 {0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325},
60 {0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567},
61 {0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000},
62 {1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866},
63 {0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000},
64 {0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866},
65 {0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
66 {0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856},
67 {0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866},
68 {0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567},
69 {0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731},
70 {0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856},
71 {0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718},
72 {0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785},
73 {0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191},
74 {0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718},
75 {-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651},
76 {-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188},
77 {-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056},
78 {0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423},
79 {0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188},
80 {-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056},
81 {0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718},
82 {0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651},
83 {0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188},
84 {0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863},
85 {0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785},
86 {0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325},
87 {0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242},
88 {0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460},
89 {0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242},
90 {0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460},
91 {0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621},
92 {0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863},
93 {-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460},
94 {-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621},
95 {-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000},
96 {-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
97 {-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856},
98 {-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325},
99 {-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188},
100 {-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017},
101 {-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785},
102 {-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188},
103 {0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017},
104 {0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651},
105 {0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191},
106 {0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000},
107 {-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000},
108 {-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000},
109 {-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856},
110 {-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000},
111 {-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866},
112 {-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567},
113 {-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731},
114 {-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191},
115 {-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785},
116 {-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325},
119 byte NormalToByte(vec3_t n)
122 float bestdistance, distance;
125 bestdistance = DotProduct (n, m_bytenormals[0]);
126 for (i = 1;i < NUMVERTEXNORMALS;i++)
128 distance = DotProduct (n, m_bytenormals[i]);
129 if (distance > bestdistance)
131 bestdistance = distance;
138 // note: uses byte partly to force unsigned for the validity check
139 void ByteToNormal(byte num, vec3_t n)
141 if (num < NUMVERTEXNORMALS)
142 VectorCopy(m_bytenormals[num], n)
144 VectorClear(n) // FIXME: complain?
148 // LordHavoc: no longer used at all
149 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
152 // LordHavoc: the old way...
157 inv_denom = 1.0F / DotProduct( normal, normal );
159 d = DotProduct( normal, p ) * inv_denom;
161 n[0] = normal[0] * inv_denom;
162 n[1] = normal[1] * inv_denom;
163 n[2] = normal[2] * inv_denom;
165 dst[0] = p[0] - d * n[0];
166 dst[1] = p[1] - d * n[1];
167 dst[2] = p[2] - d * n[2];
169 // LordHavoc: optimized to death and beyond
172 // LordHavoc: the normal is a unit vector by definition,
173 // therefore inv_denom was pointless.
174 d = DotProduct(normal, p);
175 dst[0] = p[0] - d * normal[0];
176 dst[1] = p[1] - d * normal[1];
177 dst[2] = p[2] - d * normal[2];
182 // assumes "src" is normalized
183 void PerpendicularVector( vec3_t dst, const vec3_t src )
186 // LordHavoc: the old way...
192 // find the smallest magnitude axially aligned vector
194 for ( pos = 0, i = 0; i < 3; i++ )
196 if ( fabs( src[i] ) < minelem )
199 minelem = fabs( src[i] );
202 VectorClear(tempvec);
205 // project the point onto the plane defined by src
206 ProjectPointOnPlane( dst, tempvec, src );
208 // normalize the result
209 VectorNormalize(dst);
211 // LordHavoc: optimized to death and beyond
225 minelem = fabs(src[0]);
226 if (fabs(src[1]) < minelem)
229 minelem = fabs(src[1]);
231 if (fabs(src[2]) < minelem)
235 dst[0] -= src[pos] * src[0];
236 dst[1] -= src[pos] * src[1];
237 dst[2] -= src[pos] * src[2];
239 // normalize the result
240 VectorNormalize(dst);
262 #pragma optimize( "", off )
266 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
267 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
271 right[0] = forward[2];
272 right[1] = -forward[0];
273 right[2] = forward[1];
275 d = DotProduct(forward, right);
276 right[0] -= d * forward[0];
277 right[1] -= d * forward[1];
278 right[2] -= d * forward[2];
279 VectorNormalize(right);
280 CrossProduct(right, forward, up);
283 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
286 // LordHavoc: the old way, cryptic brute force...
299 PerpendicularVector( vr, dir );
300 CrossProduct( vr, vf, vup );
314 memcpy( im, m, sizeof( im ) );
323 memset( zrot, 0, sizeof( zrot ) );
324 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
326 zrot[0][0] = cos( DEG2RAD( degrees ) );
327 zrot[0][1] = sin( DEG2RAD( degrees ) );
328 zrot[1][0] = -sin( DEG2RAD( degrees ) );
329 zrot[1][1] = cos( DEG2RAD( degrees ) );
331 R_ConcatRotations( m, zrot, tmpmat );
332 R_ConcatRotations( tmpmat, im, rot );
334 for ( i = 0; i < 3; i++ )
335 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
337 // LordHavoc: on the path to unintelligible code...
347 angle = DEG2RAD(degrees);
356 PerpendicularVector(vr, dir);
357 CrossProduct(vr, vf, vu);
359 // m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0];
360 // m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1];
361 // m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2];
362 // im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2];
363 // im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2];
364 // im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2];
365 // zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0;
366 // zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0;
367 // zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1;
369 // tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
370 // tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
371 // tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
372 // tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
373 // tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
374 // tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
375 // tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
376 // tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
377 // tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
379 tmpmat[0][0] = vr[0] * c + vu[0] * -s;
380 tmpmat[0][1] = vr[0] * s + vu[0] * c;
381 // tmpmat[0][2] = vf[0];
382 tmpmat[1][0] = vr[1] * c + vu[1] * -s;
383 tmpmat[1][1] = vr[1] * s + vu[1] * c;
384 // tmpmat[1][2] = vf[1];
385 tmpmat[2][0] = vr[2] * c + vu[2] * -s;
386 tmpmat[2][1] = vr[2] * s + vu[2] * c;
387 // tmpmat[2][2] = vf[2];
389 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
390 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
391 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
392 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
393 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
394 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
395 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
396 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
397 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
399 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
400 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
401 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
402 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
403 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
404 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
405 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
406 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
407 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
409 // dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
410 // dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
411 // dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
413 dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
414 + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
415 + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
416 dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
417 + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
418 + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
419 dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
420 + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
421 + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
423 // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
428 angle = DEG2RAD(degrees);
437 // PerpendicularVector(vr, dir);
438 // CrossProduct(vr, vf, vu);
439 VectorVectors(vf, vr, vu);
441 t0 = vr[0] * c + vu[0] * -s;
442 t1 = vr[0] * s + vu[0] * c;
443 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
444 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
445 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
447 t0 = vr[1] * c + vu[1] * -s;
448 t1 = vr[1] * s + vu[1] * c;
449 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
450 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
451 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
453 t0 = vr[2] * c + vu[2] * -s;
454 t1 = vr[2] * s + vu[2] * c;
455 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
456 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
457 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
462 #pragma optimize( "", on )
465 /*-----------------------------------------------------------------*/
468 float anglemod(float a)
472 a -= 360*(int)(a/360);
474 a += 360*( 1 + (int)(-a/360) );
476 a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
481 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
482 // assembly in an attempt to accelerate it further, very inefficient
483 // considering that signbits of the frustum planes only changed each
484 // frame, and the world planes changed only at load time.
485 // So, to optimize it further I took the obvious route of storing a function
486 // pointer in the plane struct itself, and shrunk each of the individual
487 // cases to a single return statement.
489 // realized axial cases would be a nice speedup for world geometry, although
490 // never useful for the frustum planes.
491 int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
492 int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
493 int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
494 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));}
495 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));}
496 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));}
497 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));}
498 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));}
499 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));}
500 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));}
501 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));}
503 void BoxOnPlaneSideClassify(mplane_t *p)
508 p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
511 p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
514 p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
517 if (p->normal[2] < 0) // 4
519 if (p->normal[1] < 0) // 2
521 if (p->normal[0] < 0) // 1
522 p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
524 p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
528 if (p->normal[0] < 0) // 1
529 p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
531 p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
536 if (p->normal[1] < 0) // 2
538 if (p->normal[0] < 0) // 1
539 p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
541 p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
545 if (p->normal[0] < 0) // 1
546 p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
548 p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
555 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
558 float sr, sp, sy, cr, cp, cy;
560 angle = angles[YAW] * (M_PI*2 / 360);
563 angle = angles[PITCH] * (M_PI*2 / 360);
566 // LordHavoc: this is only to hush up gcc complaining about 'might be used uninitialized' variables
567 // (they are NOT used uninitialized, but oh well)
572 angle = angles[ROLL] * (M_PI*2 / 360);
585 right[0] = (-1*sr*sp*cy+-1*cr*-sy);
586 right[1] = (-1*sr*sp*sy+-1*cr*cy);
591 up[0] = (cr*sp*cy+-sr*-sy);
592 up[1] = (cr*sp*sy+-sr*cy);
597 int VectorCompare (vec3_t v1, vec3_t v2)
601 for (i=0 ; i<3 ; i++)
608 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
610 vecc[0] = veca[0] + scale*vecb[0];
611 vecc[1] = veca[1] + scale*vecb[1];
612 vecc[2] = veca[2] + scale*vecb[2];
616 vec_t _DotProduct (vec3_t v1, vec3_t v2)
618 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
621 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
623 out[0] = veca[0]-vecb[0];
624 out[1] = veca[1]-vecb[1];
625 out[2] = veca[2]-vecb[2];
628 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
630 out[0] = veca[0]+vecb[0];
631 out[1] = veca[1]+vecb[1];
632 out[2] = veca[2]+vecb[2];
635 void _VectorCopy (vec3_t in, vec3_t out)
642 // LordHavoc: changed CrossProduct to a #define
644 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
646 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
647 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
648 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
652 double sqrt(double x);
654 vec_t Length(vec3_t v)
660 for (i=0 ; i< 3 ; i++)
662 length = sqrt (length); // FIXME
667 // LordHavoc: renamed these to Length, and made the normal ones #define
668 float VectorNormalizeLength (vec3_t v)
670 float length, ilength;
672 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
673 length = sqrt (length); // FIXME
687 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
689 float length, ilength;
691 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
692 length = sqrt (length); // FIXME
697 dest[0] = v[0] * ilength;
698 dest[1] = v[1] * ilength;
699 dest[2] = v[2] * ilength;
702 dest[0] = dest[1] = dest[2] = 0;
708 void VectorInverse (vec3_t v)
715 void VectorScale (vec3_t in, vec_t scale, vec3_t out)
717 out[0] = in[0]*scale;
718 out[1] = in[1]*scale;
719 out[2] = in[2]*scale;
737 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
739 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
740 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
741 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
742 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
743 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
744 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
745 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
746 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
747 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
756 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
758 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
759 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
760 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
761 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
762 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
763 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
764 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
765 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
766 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
767 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
768 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
769 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
777 Returns mathematically correct (floor-based) quotient and remainder for
778 numer and denom, both of which should contain no fractional part. The
779 quotient must fit in 32 bits.
783 void FloorDivMod (double numer, double denom, int *quotient,
791 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
793 // if ((floor(numer) != numer) || (floor(denom) != denom))
794 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
801 x = floor(numer / denom);
803 r = (int)floor(numer - (x * denom));
808 // perform operations with positive values, and fix mod to make floor-based
810 x = floor(-numer / denom);
812 r = (int)floor(-numer - (x * denom));
827 GreatestCommonDivisor
830 int GreatestCommonDivisor (int i1, int i2)
836 return GreatestCommonDivisor (i2, i1 % i2);
842 return GreatestCommonDivisor (i1, i2 % i1);