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};
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);
285 // LordHavoc: like AngleVectors, but taking a forward vector instead of angles, useful!
286 void VectorVectors(const vec3_t forward, vec3_t right, vec3_t up)
290 right[0] = forward[2];
291 right[1] = -forward[0];
292 right[2] = forward[1];
294 d = DotProduct(forward, right);
295 right[0] -= d * forward[0];
296 right[1] -= d * forward[1];
297 right[2] -= d * forward[2];
298 VectorNormalizeFast(right);
299 CrossProduct(right, forward, up);
302 void VectorVectorsDouble(const double *forward, double *right, double *up)
306 right[0] = forward[2];
307 right[1] = -forward[0];
308 right[2] = forward[1];
310 d = DotProduct(forward, right);
311 right[0] -= d * forward[0];
312 right[1] -= d * forward[1];
313 right[2] -= d * forward[2];
314 VectorNormalize(right);
315 CrossProduct(right, forward, up);
318 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
321 // LordHavoc: the old way, cryptic brute force...
334 PerpendicularVector( vr, dir );
335 CrossProduct( vr, vf, vup );
349 memcpy( im, m, sizeof( im ) );
358 memset( zrot, 0, sizeof( zrot ) );
359 zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
361 zrot[0][0] = cos( DEG2RAD( degrees ) );
362 zrot[0][1] = sin( DEG2RAD( degrees ) );
363 zrot[1][0] = -sin( DEG2RAD( degrees ) );
364 zrot[1][1] = cos( DEG2RAD( degrees ) );
366 R_ConcatRotations( m, zrot, tmpmat );
367 R_ConcatRotations( tmpmat, im, rot );
369 for ( i = 0; i < 3; i++ )
370 dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
372 // LordHavoc: on the path to unintelligible code...
382 angle = DEG2RAD(degrees);
391 PerpendicularVector(vr, dir);
392 CrossProduct(vr, vf, vu);
394 // m [0][0] = vr[0];m [0][1] = vu[0];m [0][2] = vf[0];
395 // m [1][0] = vr[1];m [1][1] = vu[1];m [1][2] = vf[1];
396 // m [2][0] = vr[2];m [2][1] = vu[2];m [2][2] = vf[2];
397 // im [0][0] = vr[0];im [0][1] = vr[1];im [0][2] = vr[2];
398 // im [1][0] = vu[0];im [1][1] = vu[1];im [1][2] = vu[2];
399 // im [2][0] = vf[0];im [2][1] = vf[1];im [2][2] = vf[2];
400 // zrot[0][0] = c;zrot[0][1] = s;zrot[0][2] = 0;
401 // zrot[1][0] = -s;zrot[1][1] = c;zrot[1][2] = 0;
402 // zrot[2][0] = 0;zrot[2][1] = 0;zrot[2][2] = 1;
404 // tmpmat[0][0] = m[0][0] * zrot[0][0] + m[0][1] * zrot[1][0] + m[0][2] * zrot[2][0];
405 // tmpmat[0][1] = m[0][0] * zrot[0][1] + m[0][1] * zrot[1][1] + m[0][2] * zrot[2][1];
406 // tmpmat[0][2] = m[0][0] * zrot[0][2] + m[0][1] * zrot[1][2] + m[0][2] * zrot[2][2];
407 // tmpmat[1][0] = m[1][0] * zrot[0][0] + m[1][1] * zrot[1][0] + m[1][2] * zrot[2][0];
408 // tmpmat[1][1] = m[1][0] * zrot[0][1] + m[1][1] * zrot[1][1] + m[1][2] * zrot[2][1];
409 // tmpmat[1][2] = m[1][0] * zrot[0][2] + m[1][1] * zrot[1][2] + m[1][2] * zrot[2][2];
410 // tmpmat[2][0] = m[2][0] * zrot[0][0] + m[2][1] * zrot[1][0] + m[2][2] * zrot[2][0];
411 // tmpmat[2][1] = m[2][0] * zrot[0][1] + m[2][1] * zrot[1][1] + m[2][2] * zrot[2][1];
412 // tmpmat[2][2] = m[2][0] * zrot[0][2] + m[2][1] * zrot[1][2] + m[2][2] * zrot[2][2];
414 tmpmat[0][0] = vr[0] * c + vu[0] * -s;
415 tmpmat[0][1] = vr[0] * s + vu[0] * c;
416 // tmpmat[0][2] = vf[0];
417 tmpmat[1][0] = vr[1] * c + vu[1] * -s;
418 tmpmat[1][1] = vr[1] * s + vu[1] * c;
419 // tmpmat[1][2] = vf[1];
420 tmpmat[2][0] = vr[2] * c + vu[2] * -s;
421 tmpmat[2][1] = vr[2] * s + vu[2] * c;
422 // tmpmat[2][2] = vf[2];
424 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + tmpmat[0][2] * vf[0];
425 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + tmpmat[0][2] * vf[1];
426 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + tmpmat[0][2] * vf[2];
427 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + tmpmat[1][2] * vf[0];
428 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + tmpmat[1][2] * vf[1];
429 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + tmpmat[1][2] * vf[2];
430 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + tmpmat[2][2] * vf[0];
431 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + tmpmat[2][2] * vf[1];
432 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + tmpmat[2][2] * vf[2];
434 // rot[0][0] = tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0];
435 // rot[0][1] = tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1];
436 // rot[0][2] = tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2];
437 // rot[1][0] = tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0];
438 // rot[1][1] = tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1];
439 // rot[1][2] = tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2];
440 // rot[2][0] = tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0];
441 // rot[2][1] = tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1];
442 // rot[2][2] = tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2];
444 // dst[0] = rot[0][0] * point[0] + rot[0][1] * point[1] + rot[0][2] * point[2];
445 // dst[1] = rot[1][0] * point[0] + rot[1][1] * point[1] + rot[1][2] * point[2];
446 // dst[2] = rot[2][0] * point[0] + rot[2][1] * point[1] + rot[2][2] * point[2];
448 dst[0] = (tmpmat[0][0] * vr[0] + tmpmat[0][1] * vu[0] + vf[0] * vf[0]) * point[0]
449 + (tmpmat[0][0] * vr[1] + tmpmat[0][1] * vu[1] + vf[0] * vf[1]) * point[1]
450 + (tmpmat[0][0] * vr[2] + tmpmat[0][1] * vu[2] + vf[0] * vf[2]) * point[2];
451 dst[1] = (tmpmat[1][0] * vr[0] + tmpmat[1][1] * vu[0] + vf[1] * vf[0]) * point[0]
452 + (tmpmat[1][0] * vr[1] + tmpmat[1][1] * vu[1] + vf[1] * vf[1]) * point[1]
453 + (tmpmat[1][0] * vr[2] + tmpmat[1][1] * vu[2] + vf[1] * vf[2]) * point[2];
454 dst[2] = (tmpmat[2][0] * vr[0] + tmpmat[2][1] * vu[0] + vf[2] * vf[0]) * point[0]
455 + (tmpmat[2][0] * vr[1] + tmpmat[2][1] * vu[1] + vf[2] * vf[1]) * point[1]
456 + (tmpmat[2][0] * vr[2] + tmpmat[2][1] * vu[2] + vf[2] * vf[2]) * point[2];
458 // LordHavoc: optimized to death and beyond, cryptic in an entirely new way
463 angle = DEG2RAD(degrees);
472 // PerpendicularVector(vr, dir);
473 // CrossProduct(vr, vf, vu);
474 VectorVectors(vf, vr, vu);
476 t0 = vr[0] * c + vu[0] * -s;
477 t1 = vr[0] * s + vu[0] * c;
478 dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
479 + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
480 + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
482 t0 = vr[1] * c + vu[1] * -s;
483 t1 = vr[1] * s + vu[1] * c;
484 dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
485 + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
486 + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
488 t0 = vr[2] * c + vu[2] * -s;
489 t1 = vr[2] * s + vu[2] * c;
490 dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
491 + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
492 + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
496 /*-----------------------------------------------------------------*/
500 // BoxOnPlaneSide did a switch on a 'signbits' value and had optimized
501 // assembly in an attempt to accelerate it further, very inefficient
502 // considering that signbits of the frustum planes only changed each
503 // frame, and the world planes changed only at load time.
504 // So, to optimize it further I took the obvious route of storing a function
505 // pointer in the plane struct itself, and shrunk each of the individual
506 // cases to a single return statement.
508 // realized axial cases would be a nice speedup for world geometry, although
509 // never useful for the frustum planes.
510 int BoxOnPlaneSideX (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[0] ? 1 : (p->dist >= emaxs[0] ? 2 : 3);}
511 int BoxOnPlaneSideY (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[1] ? 1 : (p->dist >= emaxs[1] ? 2 : 3);}
512 int BoxOnPlaneSideZ (vec3_t emins, vec3_t emaxs, mplane_t *p) {return p->dist <= emins[2] ? 1 : (p->dist >= emaxs[2] ? 2 : 3);}
513 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));}
514 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));}
515 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));}
516 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));}
517 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));}
518 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));}
519 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));}
520 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));}
522 void BoxOnPlaneSideClassify(mplane_t *p)
527 p->BoxOnPlaneSideFunc = BoxOnPlaneSideX;
530 p->BoxOnPlaneSideFunc = BoxOnPlaneSideY;
533 p->BoxOnPlaneSideFunc = BoxOnPlaneSideZ;
536 if (p->normal[2] < 0) // 4
538 if (p->normal[1] < 0) // 2
540 if (p->normal[0] < 0) // 1
541 p->BoxOnPlaneSideFunc = BoxOnPlaneSide7;
543 p->BoxOnPlaneSideFunc = BoxOnPlaneSide6;
547 if (p->normal[0] < 0) // 1
548 p->BoxOnPlaneSideFunc = BoxOnPlaneSide5;
550 p->BoxOnPlaneSideFunc = BoxOnPlaneSide4;
555 if (p->normal[1] < 0) // 2
557 if (p->normal[0] < 0) // 1
558 p->BoxOnPlaneSideFunc = BoxOnPlaneSide3;
560 p->BoxOnPlaneSideFunc = BoxOnPlaneSide2;
564 if (p->normal[0] < 0) // 1
565 p->BoxOnPlaneSideFunc = BoxOnPlaneSide1;
567 p->BoxOnPlaneSideFunc = BoxOnPlaneSide0;
574 void PlaneClassify(mplane_t *p)
576 if (p->normal[0] == 1)
578 else if (p->normal[1] == 1)
580 else if (p->normal[2] == 1)
584 BoxOnPlaneSideClassify(p);
587 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
589 double angle, sr, sp, sy, cr, cp, cy;
591 angle = angles[YAW] * (M_PI*2 / 360);
594 angle = angles[PITCH] * (M_PI*2 / 360);
605 angle = angles[ROLL] * (M_PI*2 / 360);
610 right[0] = -1*(sr*sp*cy+cr*-sy);
611 right[1] = -1*(sr*sp*sy+cr*cy);
612 right[2] = -1*(sr*cp);
616 up[0] = (cr*sp*cy+-sr*-sy);
617 up[1] = (cr*sp*sy+-sr*cy);
623 void AngleVectorsFLU (vec3_t angles, vec3_t forward, vec3_t left, vec3_t up)
625 double angle, sr, sp, sy, cr, cp, cy;
627 angle = angles[YAW] * (M_PI*2 / 360);
630 angle = angles[PITCH] * (M_PI*2 / 360);
641 angle = angles[ROLL] * (M_PI*2 / 360);
646 left[0] = sr*sp*cy+cr*-sy;
647 left[1] = sr*sp*sy+cr*cy;
652 up[0] = cr*sp*cy+-sr*-sy;
653 up[1] = cr*sp*sy+-sr*cy;
659 void AngleMatrix (vec3_t angles, vec3_t translate, vec_t matrix[][4])
661 double angle, sr, sp, sy, cr, cp, cy;
663 angle = angles[YAW] * (M_PI*2 / 360);
666 angle = angles[PITCH] * (M_PI*2 / 360);
669 angle = angles[ROLL] * (M_PI*2 / 360);
672 matrix[0][0] = cp*cy;
673 matrix[0][1] = sr*sp*cy+cr*-sy;
674 matrix[0][2] = cr*sp*cy+-sr*-sy;
675 matrix[0][3] = translate[0];
676 matrix[1][0] = cp*sy;
677 matrix[1][1] = sr*sp*sy+cr*cy;
678 matrix[1][2] = cr*sp*sy+-sr*cy;
679 matrix[1][3] = translate[1];
681 matrix[2][1] = sr*cp;
682 matrix[2][2] = cr*cp;
683 matrix[2][3] = translate[2];
686 void VectorMASlow (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
688 vecc[0] = veca[0] + scale*vecb[0];
689 vecc[1] = veca[1] + scale*vecb[1];
690 vecc[2] = veca[2] + scale*vecb[2];
694 vec_t _DotProduct (vec3_t v1, vec3_t v2)
696 return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
699 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
701 out[0] = veca[0]-vecb[0];
702 out[1] = veca[1]-vecb[1];
703 out[2] = veca[2]-vecb[2];
706 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
708 out[0] = veca[0]+vecb[0];
709 out[1] = veca[1]+vecb[1];
710 out[2] = veca[2]+vecb[2];
713 void _VectorCopy (vec3_t in, vec3_t out)
720 // LordHavoc: changed CrossProduct to a #define
722 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
724 cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
725 cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
726 cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
730 double sqrt(double x);
732 vec_t Length(vec3_t v)
738 for (i=0 ; i< 3 ; i++)
740 length = sqrt (length); // FIXME
746 // LordHavoc: fixme: do more research on gcc assembly so that qftol_minushalf and result will not be considered unused
747 static double qftol_minushalf = -0.5;
759 #else // gcc hopefully
760 asm("fldl v\n\tfaddl qftol_minushalf\n\tfistpl result");
766 // LordHavoc: renamed these to Length, and made the normal ones #define
767 float VectorNormalizeLength (vec3_t v)
769 float length, ilength;
771 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
772 length = sqrt (length); // FIXME
786 float VectorNormalizeLength2 (vec3_t v, vec3_t dest) // LordHavoc: added to allow copying while doing the calculation...
788 float length, ilength;
790 length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
791 length = sqrt (length); // FIXME
796 dest[0] = v[0] * ilength;
797 dest[1] = v[1] * ilength;
798 dest[2] = v[2] * ilength;
801 dest[0] = dest[1] = dest[2] = 0;
807 void _VectorInverse (vec3_t v)
814 void _VectorScale (vec3_t in, vec_t scale, vec3_t out)
816 out[0] = in[0]*scale;
817 out[1] = in[1]*scale;
818 out[2] = in[2]*scale;
836 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
838 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
839 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
840 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
841 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
842 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
843 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
844 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
845 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
846 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
855 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
857 out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0];
858 out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1];
859 out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2];
860 out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3];
861 out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0];
862 out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1];
863 out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2];
864 out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3];
865 out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0];
866 out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1];
867 out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2];
868 out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3];
876 Returns mathematically correct (floor-based) quotient and remainder for
877 numer and denom, both of which should contain no fractional part. The
878 quotient must fit in 32 bits.
882 void FloorDivMod (double numer, double denom, int *quotient,
890 Sys_Error ("FloorDivMod: bad denominator %d\n", denom);
892 // if ((floor(numer) != numer) || (floor(denom) != denom))
893 // Sys_Error ("FloorDivMod: non-integer numer or denom %f %f\n",
900 x = floor(numer / denom);
902 r = (int)floor(numer - (x * denom));
907 // perform operations with positive values, and fix mod to make floor-based
909 x = floor(-numer / denom);
911 r = (int)floor(-numer - (x * denom));
926 GreatestCommonDivisor
929 int GreatestCommonDivisor (int i1, int i2)
935 return GreatestCommonDivisor (i2, i1 % i2);
941 return GreatestCommonDivisor (i1, i2 % i1);
946 void Mathlib_Init(void)
950 // LordHavoc: setup 1.0f / N table for quick recipricols of integers
952 for (a = 1;a < 4096;a++)
953 ixtable[a] = 1.0f / a;