2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // mathlib.c -- math primitives
25 void Sys_Error (char *error, ...);
27 vec3_t vec3_origin = {0,0,0};
28 int nanmask = 255<<23;
31 /*-----------------------------------------------------------------*/
33 float m_bytenormals[NUMVERTEXNORMALS][3] =
35 {-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188},
36 {-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017},
37 {-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000},
38 {0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718},
39 {0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651},
40 {0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651},
41 {0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188},
42 {0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567},
43 {-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191},
44 {-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856},
45 {-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325},
46 {-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863},
47 {-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621},
48 {-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000},
49 {0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863},
50 {0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460},
51 {0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242},
52 {-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863},
53 {0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017},
54 {0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460},
55 {0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000},
56 {0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621},
57 {0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785},
58 {0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325},
59 {0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567},
60 {0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000},
61 {1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866},
62 {0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000},
63 {0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866},
64 {0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567},
65 {0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856},
66 {0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866},
67 {0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567},
68 {0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731},
69 {0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856},
70 {0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718},
71 {0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785},
72 {0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191},
73 {0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718},
74 {-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651},
75 {-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188},
76 {-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056},
77 {0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423},
78 {0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188},
79 {-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056},
80 {0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718},
81 {0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651},
82 {0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188},
83 {0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863},
84 {0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785},
85 {0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325},
86 {0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242},
87 {0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460},
88 {0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242},
89 {0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460},
90 {0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621},
91 {0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863},
92 {-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460},
93 {-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621},
94 {-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000},
95 {-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863},
96 {-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856},
97 {-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325},
98 {-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188},
99 {-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017},
100 {-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785},
101 {-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188},
102 {0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017},
103 {0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651},
104 {0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191},
105 {0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000},
106 {-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000},
107 {-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000},
108 {-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856},
109 {-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000},
110 {-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866},
111 {-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567},
112 {-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731},
113 {-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191},
114 {-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785},
115 {-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325},
118 byte NormalToByte(vec3_t n)
121 float bestdistance, distance;
124 bestdistance = DotProduct (n, m_bytenormals[0]);
125 for (i = 1;i < NUMVERTEXNORMALS;i++)
127 distance = DotProduct (n, m_bytenormals[i]);
128 if (distance > bestdistance)
130 bestdistance = distance;
137 // note: uses byte partly to force unsigned for the validity check
138 void ByteToNormal(byte num, vec3_t n)
140 if (num < NUMVERTEXNORMALS)
141 VectorCopy(m_bytenormals[num], n);
143 VectorClear(n); // FIXME: complain?
146 float Q_RSqrt(float number)
153 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
154 return y * (1.5f - (number * 0.5f * y * y));
157 void _VectorNormalizeFast(vec3_t v)
161 number = DotProduct(v, v);
165 *((long *)&y) = 0x5f3759df - ((* (long *) &number) >> 1);
166 y = y * (1.5f - (number * 0.5f * y * y));
168 VectorScale(v, y, v);
173 // LordHavoc: no longer used at all
174 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
177 // LordHavoc: the old way...
182 inv_denom = 1.0F / DotProduct( normal, normal );
184 d = DotProduct( normal, p ) * inv_denom;
186 n[0] = normal[0] * inv_denom;
187 n[1] = normal[1] * inv_denom;
188 n[2] = normal[2] * inv_denom;
190 dst[0] = p[0] - d * n[0];
191 dst[1] = p[1] - d * n[1];
192 dst[2] = p[2] - d * n[2];
194 // LordHavoc: optimized to death and beyond
197 // LordHavoc: the normal is a unit vector by definition,
198 // therefore inv_denom was pointless.
199 d = DotProduct(normal, p);
200 dst[0] = p[0] - d * normal[0];
201 dst[1] = p[1] - d * normal[1];
202 dst[2] = p[2] - d * normal[2];
207 // assumes "src" is normalized
208 void PerpendicularVector( vec3_t dst, const vec3_t src )
211 // LordHavoc: the old way...
217 // find the smallest magnitude axially aligned vector
219 for ( pos = 0, i = 0; i < 3; i++ )
221 if ( fabs( src[i] ) < minelem )
224 minelem = fabs( src[i] );
227 VectorClear(tempvec);
230 // project the point onto the plane defined by src
231 ProjectPointOnPlane( dst, tempvec, src );
233 // normalize the result
234 VectorNormalize(dst);
236 // LordHavoc: optimized to death and beyond
250 minelem = fabs(src[0]);
251 if (fabs(src[1]) < minelem)
254 minelem = fabs(src[1]);
256 if (fabs(src[2]) < minelem)
260 dst[0] -= src[pos] * src[0];
261 dst[1] -= src[pos] * src[1];
262 dst[2] -= src[pos] * src[2];
264 // normalize the result
265 VectorNormalize(dst);
287 #pragma optimize( "", off )
291 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
292 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
296 right[0] = forward[2];
297 right[1] = -forward[0];
298 right[2] = forward[1];
300 d = DotProduct(forward, right);
301 right[0] -= d * forward[0];
302 right[1] -= d * forward[1];
303 right[2] -= d * forward[2];
304 VectorNormalizeFast(right);
305 CrossProduct(right, forward, up);
308 void VectorVectorsDouble(const double *forward, double *right, double *up)
312 right[0] = forward[2];
313 right[1] = -forward[0];
314 right[2] = forward[1];
316 d = DotProduct(forward, right);
317 right[0] -= d * forward[0];
318 right[1] -= d * forward[1];
319 right[2] -= d * forward[2];
320 VectorNormalize(right);
321 CrossProduct(right, forward, up);
324 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
327 // LordHavoc: the old way, cryptic brute force...
340 PerpendicularVector( vr, dir );
341 CrossProduct( vr, vf, vup );
355 memcpy( im, m, sizeof( im ) );
364 memset( zrot, 0, sizeof( zrot ) );
365 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
367 zrot[0][0] = cos( DEG2RAD( degrees ) );
368 zrot[0][1] = sin( DEG2RAD( degrees ) );
369 zrot[1][0] = -sin( DEG2RAD( degrees ) );
370 zrot[1][1] = cos( DEG2RAD( degrees ) );
372 R_ConcatRotations( m, zrot, tmpmat );
373 R_ConcatRotations( tmpmat, im, rot );
375 for ( i = 0; i < 3; i++ )
376 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
378 // LordHavoc: on the path to unintelligible code...
388 angle = DEG2RAD(degrees);
397 PerpendicularVector(vr, dir);
398 CrossProduct(vr, vf, vu);
400 // m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0];
401 // m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1];
402 // m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2];
403 // im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2];
404 // im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2];
405 // im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2];
406 // zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0;
407 // zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0;
408 // zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1;
410 // tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
411 // tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
412 // tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
413 // tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
414 // tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
415 // tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
416 // tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
417 // tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
418 // tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
420 tmpmat[0][0] = vr[0] * c + vu[0] * -s;
421 tmpmat[0][1] = vr[0] * s + vu[0] * c;
422 // tmpmat[0][2] = vf[0];
423 tmpmat[1][0] = vr[1] * c + vu[1] * -s;
424 tmpmat[1][1] = vr[1] * s + vu[1] * c;
425 // tmpmat[1][2] = vf[1];
426 tmpmat[2][0] = vr[2] * c + vu[2] * -s;
427 tmpmat[2][1] = vr[2] * s + vu[2] * c;
428 // tmpmat[2][2] = vf[2];
430 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
431 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
432 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
433 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
434 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
435 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
436 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
437 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
438 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
440 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
441 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
442 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
443 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
444 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
445 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
446 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
447 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
448 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
450 // dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
451 // dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
452 // dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
454 dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
455 + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
456 + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
457 dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
458 + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
459 + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
460 dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
461 + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
462 + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
464 // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
469 angle = DEG2RAD(degrees);
478 // PerpendicularVector(vr, dir);
479 // CrossProduct(vr, vf, vu);
480 VectorVectors(vf, vr, vu);
482 t0 = vr[0] * c + vu[0] * -s;
483 t1 = vr[0] * s + vu[0] * c;
484 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
485 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
486 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
488 t0 = vr[1] * c + vu[1] * -s;
489 t1 = vr[1] * s + vu[1] * c;
490 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
491 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
492 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
494 t0 = vr[2] * c + vu[2] * -s;
495 t1 = vr[2] * s + vu[2] * c;
496 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
497 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
498 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
503 #pragma optimize( "", on )
506 /*-----------------------------------------------------------------*/
510 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
511 // assembly in an attempt to accelerate it further, very inefficient
512 // considering that signbits of the frustum planes only changed each
513 // frame, and the world planes changed only at load time.
514 // So, to optimize it further I took the obvious route of storing a function
515 // pointer in the plane struct itself, and shrunk each of the individual
516 // cases to a single return statement.
518 // realized axial cases would be a nice speedup for world geometry, although
519 // never useful for the frustum planes.
520 int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
521 int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
522 int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
523 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));}
524 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));}
525 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));}
526 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));}
527 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));}
528 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));}
529 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));}
530 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));}
532 void BoxOnPlaneSideClassify(mplane_t *p)
537 p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
540 p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
543 p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
546 if (p->normal[2] < 0) // 4
548 if (p->normal[1] < 0) // 2
550 if (p->normal[0] < 0) // 1
551 p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
553 p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
557 if (p->normal[0] < 0) // 1
558 p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
560 p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
565 if (p->normal[1] < 0) // 2
567 if (p->normal[0] < 0) // 1
568 p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
570 p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
574 if (p->normal[0] < 0) // 1
575 p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
577 p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
584 void PlaneClassify(mplane_t *p)
586 if (p->normal[0] == 1)
588 else if (p->normal[1] == 1)
590 else if (p->normal[2] == 1)
594 BoxOnPlaneSideClassify(p);
597 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
599 double angle, sr, sp, sy, cr, cp, cy;
601 angle = angles[YAW] * (M_PI*2 / 360);
604 angle = angles[PITCH] * (M_PI*2 / 360);
615 angle = angles[ROLL] * (M_PI*2 / 360);
620 right[0] = -1*(sr*sp*cy+cr*-sy);
621 right[1] = -1*(sr*sp*sy+cr*cy);
622 right[2] = -1*(sr*cp);
626 up[0] = (cr*sp*cy+-sr*-sy);
627 up[1] = (cr*sp*sy+-sr*cy);
633 void AngleVectorsFLU (vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
635 double angle, sr, sp, sy, cr, cp, cy;
637 angle = angles[YAW] * (M_PI*2 / 360);
640 angle = angles[PITCH] * (M_PI*2 / 360);
651 angle = angles[ROLL] * (M_PI*2 / 360);
656 left[0] = sr*sp*cy+cr*-sy;
657 left[1] = sr*sp*sy+cr*cy;
662 up[0] = cr*sp*cy+-sr*-sy;
663 up[1] = cr*sp*sy+-sr*cy;
669 void AngleMatrix (vec3_t angles, vec3_t translate, vec_t matrix[][4])
671 double angle, sr, sp, sy, cr, cp, cy;
673 angle = angles[YAW] * (M_PI*2 / 360);
676 angle = angles[PITCH] * (M_PI*2 / 360);
679 angle = angles[ROLL] * (M_PI*2 / 360);
682 matrix[0][0] = cp*cy;
683 matrix[0][1] = sr*sp*cy+cr*-sy;
684 matrix[0][2] = cr*sp*cy+-sr*-sy;
685 matrix[0][3] = translate[0];
686 matrix[1][0] = cp*sy;
687 matrix[1][1] = sr*sp*sy+cr*cy;
688 matrix[1][2] = cr*sp*sy+-sr*cy;
689 matrix[1][3] = translate[1];
691 matrix[2][1] = sr*cp;
692 matrix[2][2] = cr*cp;
693 matrix[2][3] = translate[2];
696 void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
698 vecc[0] = veca[0] + scale*vecb[0];
699 vecc[1] = veca[1] + scale*vecb[1];
700 vecc[2] = veca[2] + scale*vecb[2];
704 vec_t _DotProduct (vec3_t v1, vec3_t v2)
706 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
709 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
711 out[0] = veca[0]-vecb[0];
712 out[1] = veca[1]-vecb[1];
713 out[2] = veca[2]-vecb[2];
716 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
718 out[0] = veca[0]+vecb[0];
719 out[1] = veca[1]+vecb[1];
720 out[2] = veca[2]+vecb[2];
723 void _VectorCopy (vec3_t in, vec3_t out)
730 // LordHavoc: changed CrossProduct to a #define
732 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
734 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
735 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
736 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
740 double sqrt(double x);
742 vec_t Length(vec3_t v)
748 for (i=0 ; i< 3 ; i++)
750 length = sqrt (length); // FIXME
756 // LordHavoc: fixme: do more research on gcc assembly so that qftol_minushalf and result will not be considered unused
757 static double qftol_minushalf = -0.5;
769 #else // gcc hopefully
770 asm("fldl v\n\tfaddl qftol_minushalf\n\tfistpl result");
776 // LordHavoc: renamed these to Length, and made the normal ones #define
777 float VectorNormalizeLength (vec3_t v)
779 float length, ilength;
781 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
782 length = sqrt (length); // FIXME
796 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
798 float length, ilength;
800 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
801 length = sqrt (length); // FIXME
806 dest[0] = v[0] * ilength;
807 dest[1] = v[1] * ilength;
808 dest[2] = v[2] * ilength;
811 dest[0] = dest[1] = dest[2] = 0;
817 void _VectorInverse (vec3_t v)
824 void _VectorScale (vec3_t in, vec_t scale, vec3_t out)
826 out[0] = in[0]*scale;
827 out[1] = in[1]*scale;
828 out[2] = in[2]*scale;
846 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
848 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
849 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
850 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
851 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
852 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
853 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
854 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
855 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
856 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
865 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
867 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
868 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
869 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
870 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
871 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
872 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
873 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
874 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
875 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
876 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
877 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
878 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
886 Returns mathematically correct (floor-based) quotient and remainder for
887 numer and denom, both of which should contain no fractional part. The
888 quotient must fit in 32 bits.
892 void FloorDivMod (double numer, double denom, int *quotient,
900 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
902 // if ((floor(numer) != numer) || (floor(denom) != denom))
903 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
910 x = floor(numer / denom);
912 r = (int)floor(numer - (x * denom));
917 // perform operations with positive values, and fix mod to make floor-based
919 x = floor(-numer / denom);
921 r = (int)floor(-numer - (x * denom));
936 GreatestCommonDivisor
939 int GreatestCommonDivisor (int i1, int i2)
945 return GreatestCommonDivisor (i2, i1 % i2);
951 return GreatestCommonDivisor (i1, i2 % i1);
956 void Mathlib_Init(void)
960 // LordHavoc: setup 1.0f / N table for quick recipricols of integers
962 for (a = 1;a < 4096;a++)
963 ixtable[a] = 1.0f / a;