1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 //
23 // q_math.c -- stateless support routines that are included in each code module
24 
25 // Some of the vector functions are static inline in q_shared.h. q3asm
26 // doesn't understand static functions though, so we only want them in
27 // one file. That's what this is about.
28 #ifdef Q3_VM
29 #define __Q3_VM_MATH
30 #endif
31 
32 #include "q_shared.h"
33 
34 vec3_t	vec3_origin = {0,0,0};
35 vec3_t	axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
36 
37 
38 vec4_t		colorBlack	= {0, 0, 0, 1};
39 vec4_t		colorRed	= {1, 0, 0, 1};
40 vec4_t		colorGreen	= {0, 1, 0, 1};
41 vec4_t		colorBlue	= {0, 0, 1, 1};
42 vec4_t		colorYellow	= {1, 1, 0, 1};
43 vec4_t		colorMagenta= {1, 0, 1, 1};
44 vec4_t		colorCyan	= {0, 1, 1, 1};
45 vec4_t		colorWhite	= {1, 1, 1, 1};
46 vec4_t		colorLtGrey	= {0.75, 0.75, 0.75, 1};
47 vec4_t		colorMdGrey	= {0.5, 0.5, 0.5, 1};
48 vec4_t		colorDkGrey	= {0.25, 0.25, 0.25, 1};
49 
50 vec4_t	g_color_table[8] =
51 	{
52 	{0.0, 0.0, 0.0, 1.0},
53 	{1.0, 0.0, 0.0, 1.0},
54 	{0.0, 0.8f, 0.0, 1.0},//{0.0, 1.0, 0.0, 1.0},
55 	{1.0, 1.0, 0.0, 1.0},
56 	{0.0, 0.0, 1.0, 1.0},
57 	{0.0, 0.8f, 0.8f, 1.0},//{0.0, 1.0, 1.0, 1.0},
58 	{1.0, 0.0, 1.0, 1.0},
59 	{1.0, 1.0, 1.0, 1.0},
60 	};
61 
62 
63 vec3_t	bytedirs[NUMVERTEXNORMALS] =
64 {
65 {-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f},
66 {-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f},
67 {-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f},
68 {0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f},
69 {0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f},
70 {0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f},
71 {0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f},
72 {0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f},
73 {-0.809017f, 0.309017f, 0.500000f},{-0.587785f, 0.425325f, 0.688191f},
74 {-0.850651f, 0.525731f, 0.000000f},{-0.864188f, 0.442863f, 0.238856f},
75 {-0.716567f, 0.681718f, 0.147621f},{-0.688191f, 0.587785f, 0.425325f},
76 {-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f},
77 {-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f},
78 {-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f},
79 {0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f},
80 {0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f},
81 {0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f},
82 {-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f},
83 {0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f},
84 {0.238856f, 0.864188f, -0.442863f},{0.262866f, 0.951056f, -0.162460f},
85 {0.500000f, 0.809017f, -0.309017f},{0.850651f, 0.525731f, 0.000000f},
86 {0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f},
87 {0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f},
88 {0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f},
89 {0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f},
90 {0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f},
91 {1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f},
92 {0.850651f, -0.525731f, 0.000000f},{0.955423f, -0.295242f, 0.000000f},
93 {0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f},
94 {0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f},
95 {0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f},
96 {0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f},
97 {0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f},
98 {0.681718f, -0.147621f, -0.716567f},{0.850651f, 0.000000f, -0.525731f},
99 {0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f},
100 {0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f},
101 {0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f},
102 {0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f},
103 {0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f},
104 {-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f},
105 {-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f},
106 {-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f},
107 {0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f},
108 {0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f},
109 {-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f},
110 {0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f},
111 {0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f},
112 {0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f},
113 {0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f},
114 {0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f},
115 {0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f},
116 {0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f},
117 {0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f},
118 {0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f},
119 {0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f},
120 {0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f},
121 {0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f},
122 {-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f},
123 {-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f},
124 {-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f},
125 {-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f},
126 {-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f},
127 {-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f},
128 {-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f},
129 {-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f},
130 {-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f},
131 {-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f},
132 {0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f},
133 {0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f},
134 {0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f},
135 {0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f},
136 {-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f},
137 {-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f},
138 {-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f},
139 {-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f},
140 {-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f},
141 {-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f},
142 {-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f},
143 {-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f},
144 {-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f},
145 {-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f}
146 };
147 
148 //==============================================================
149 
Q_rand(int * seed)150 int		Q_rand( int *seed ) {
151 	*seed = (69069 * *seed + 1);
152 	return *seed;
153 }
154 
Q_random(int * seed)155 float	Q_random( int *seed ) {
156 	return ( Q_rand( seed ) & 0xffff ) / (float)0x10000;
157 }
158 
Q_crandom(int * seed)159 float	Q_crandom( int *seed ) {
160 	return 2.0 * ( Q_random( seed ) - 0.5 );
161 }
162 
163 //=======================================================
164 
ClampChar(int i)165 signed char ClampChar( int i ) {
166 	if ( i < -128 ) {
167 		return -128;
168 	}
169 	if ( i > 127 ) {
170 		return 127;
171 	}
172 	return i;
173 }
174 
ClampShort(int i)175 signed short ClampShort( int i ) {
176 	if ( i < -32768 ) {
177 		return -32768;
178 	}
179 	if ( i > 0x7fff ) {
180 		return 0x7fff;
181 	}
182 	return i;
183 }
184 
185 
186 // this isn't a real cheap function to call!
DirToByte(vec3_t dir)187 int DirToByte( vec3_t dir ) {
188 	int		i, best;
189 	float	d, bestd;
190 
191 	if ( !dir ) {
192 		return 0;
193 	}
194 
195 	bestd = 0;
196 	best = 0;
197 	for (i=0 ; i<NUMVERTEXNORMALS ; i++)
198 	{
199 		d = DotProduct (dir, bytedirs[i]);
200 		if (d > bestd)
201 		{
202 			bestd = d;
203 			best = i;
204 		}
205 	}
206 
207 	return best;
208 }
209 
ByteToDir(int b,vec3_t dir)210 void ByteToDir( int b, vec3_t dir ) {
211 	if ( b < 0 || b >= NUMVERTEXNORMALS ) {
212 		VectorCopy( vec3_origin, dir );
213 		return;
214 	}
215 	VectorCopy (bytedirs[b], dir);
216 }
217 
218 
ColorBytes3(float r,float g,float b)219 unsigned ColorBytes3 (float r, float g, float b) {
220 	unsigned	i;
221 
222 	( (byte *)&i )[0] = r * 255;
223 	( (byte *)&i )[1] = g * 255;
224 	( (byte *)&i )[2] = b * 255;
225 
226 	return i;
227 }
228 
ColorBytes4(float r,float g,float b,float a)229 unsigned ColorBytes4 (float r, float g, float b, float a) {
230 	unsigned	i;
231 
232 	( (byte *)&i )[0] = r * 255;
233 	( (byte *)&i )[1] = g * 255;
234 	( (byte *)&i )[2] = b * 255;
235 	( (byte *)&i )[3] = a * 255;
236 
237 	return i;
238 }
239 
NormalizeColor(const vec3_t in,vec3_t out)240 float NormalizeColor( const vec3_t in, vec3_t out ) {
241 	float	max;
242 
243 	max = in[0];
244 	if ( in[1] > max ) {
245 		max = in[1];
246 	}
247 	if ( in[2] > max ) {
248 		max = in[2];
249 	}
250 
251 	if ( !max ) {
252 		VectorClear( out );
253 	} else {
254 		out[0] = in[0] / max;
255 		out[1] = in[1] / max;
256 		out[2] = in[2] / max;
257 	}
258 	return max;
259 }
260 
261 
262 /*
263 =====================
264 PlaneFromPoints
265 
266 Returns false if the triangle is degenrate.
267 The normal will point out of the clock for clockwise ordered points
268 =====================
269 */
PlaneFromPoints(vec4_t plane,const vec3_t a,const vec3_t b,const vec3_t c)270 qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
271 	vec3_t	d1, d2;
272 
273 	VectorSubtract( b, a, d1 );
274 	VectorSubtract( c, a, d2 );
275 	CrossProduct( d2, d1, plane );
276 	if ( VectorNormalize( plane ) == 0 ) {
277 		return qfalse;
278 	}
279 
280 	plane[3] = DotProduct( a, plane );
281 	return qtrue;
282 }
283 
284 /*
285 ===============
286 RotatePointAroundVector
287 
288 This is not implemented very well...
289 ===============
290 */
RotatePointAroundVector(vec3_t dst,const vec3_t dir,const vec3_t point,float degrees)291 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
292 							 float degrees ) {
293 	float	m[3][3];
294 	float	im[3][3];
295 	float	zrot[3][3];
296 	float	tmpmat[3][3];
297 	float	rot[3][3];
298 	int	i;
299 	vec3_t vr, vup, vf;
300 	float	rad;
301 
302 	vf[0] = dir[0];
303 	vf[1] = dir[1];
304 	vf[2] = dir[2];
305 
306 	PerpendicularVector( vr, dir );
307 	CrossProduct( vr, vf, vup );
308 
309 	m[0][0] = vr[0];
310 	m[1][0] = vr[1];
311 	m[2][0] = vr[2];
312 
313 	m[0][1] = vup[0];
314 	m[1][1] = vup[1];
315 	m[2][1] = vup[2];
316 
317 	m[0][2] = vf[0];
318 	m[1][2] = vf[1];
319 	m[2][2] = vf[2];
320 
321 	memcpy( im, m, sizeof( im ) );
322 
323 	im[0][1] = m[1][0];
324 	im[0][2] = m[2][0];
325 	im[1][0] = m[0][1];
326 	im[1][2] = m[2][1];
327 	im[2][0] = m[0][2];
328 	im[2][1] = m[1][2];
329 
330 	memset( zrot, 0, sizeof( zrot ) );
331 	zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
332 
333 	rad = DEG2RAD( degrees );
334 	zrot[0][0] = cos( rad );
335 	zrot[0][1] = sin( rad );
336 	zrot[1][0] = -sin( rad );
337 	zrot[1][1] = cos( rad );
338 
339 	MatrixMultiply( m, zrot, tmpmat );
340 	MatrixMultiply( tmpmat, im, rot );
341 
342 	for ( i = 0; i < 3; i++ ) {
343 		dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
344 	}
345 }
346 
347 /*
348 ===============
349 RotateAroundDirection
350 ===============
351 */
RotateAroundDirection(vec3_t axis[3],float yaw)352 void RotateAroundDirection( vec3_t axis[3], float yaw ) {
353 
354 	// create an arbitrary axis[1]
355 	PerpendicularVector( axis[1], axis[0] );
356 
357 	// rotate it around axis[0] by yaw
358 	if ( yaw ) {
359 		vec3_t	temp;
360 
361 		VectorCopy( axis[1], temp );
362 		RotatePointAroundVector( axis[1], axis[0], temp, yaw );
363 	}
364 
365 	// cross to get axis[2]
366 	CrossProduct( axis[0], axis[1], axis[2] );
367 }
368 
369 
370 
vectoangles(const vec3_t value1,vec3_t angles)371 void vectoangles( const vec3_t value1, vec3_t angles ) {
372 	float	forward;
373 	float	yaw, pitch;
374 
375 	if ( value1[1] == 0 && value1[0] == 0 ) {
376 		yaw = 0;
377 		if ( value1[2] > 0 ) {
378 			pitch = 90;
379 		}
380 		else {
381 			pitch = 270;
382 		}
383 	}
384 	else {
385 		if ( value1[0] ) {
386 			yaw = ( atan2 ( value1[1], value1[0] ) * 180 / M_PI );
387 		}
388 		else if ( value1[1] > 0 ) {
389 			yaw = 90;
390 		}
391 		else {
392 			yaw = 270;
393 		}
394 		if ( yaw < 0 ) {
395 			yaw += 360;
396 		}
397 
398 		forward = sqrt ( value1[0]*value1[0] + value1[1]*value1[1] );
399 		pitch = ( atan2(value1[2], forward) * 180 / M_PI );
400 		if ( pitch < 0 ) {
401 			pitch += 360;
402 		}
403 	}
404 
405 	angles[PITCH] = -pitch;
406 	angles[YAW] = yaw;
407 	angles[ROLL] = 0;
408 }
409 
410 
411 /*
412 =================
413 AnglesToAxis
414 =================
415 */
AnglesToAxis(const vec3_t angles,vec3_t axis[3])416 void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) {
417 	vec3_t	right;
418 
419 	// angle vectors returns "right" instead of "y axis"
420 	AngleVectors( angles, axis[0], right, axis[2] );
421 	VectorSubtract( vec3_origin, right, axis[1] );
422 }
423 
AxisClear(vec3_t axis[3])424 void AxisClear( vec3_t axis[3] ) {
425 	axis[0][0] = 1;
426 	axis[0][1] = 0;
427 	axis[0][2] = 0;
428 	axis[1][0] = 0;
429 	axis[1][1] = 1;
430 	axis[1][2] = 0;
431 	axis[2][0] = 0;
432 	axis[2][1] = 0;
433 	axis[2][2] = 1;
434 }
435 
AxisCopy(vec3_t in[3],vec3_t out[3])436 void AxisCopy( vec3_t in[3], vec3_t out[3] ) {
437 	VectorCopy( in[0], out[0] );
438 	VectorCopy( in[1], out[1] );
439 	VectorCopy( in[2], out[2] );
440 }
441 
ProjectPointOnPlane(vec3_t dst,const vec3_t p,const vec3_t normal)442 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
443 {
444 	float d;
445 	vec3_t n;
446 	float inv_denom;
447 
448 	inv_denom =  DotProduct( normal, normal );
449 #ifndef Q3_VM
450 	assert( Q_fabs(inv_denom) != 0.0f ); // zero vectors get here
451 #endif
452 	inv_denom = 1.0f / inv_denom;
453 
454 	d = DotProduct( normal, p ) * inv_denom;
455 
456 	n[0] = normal[0] * inv_denom;
457 	n[1] = normal[1] * inv_denom;
458 	n[2] = normal[2] * inv_denom;
459 
460 	dst[0] = p[0] - d * n[0];
461 	dst[1] = p[1] - d * n[1];
462 	dst[2] = p[2] - d * n[2];
463 }
464 
465 /*
466 ================
467 MakeNormalVectors
468 
469 Given a normalized forward vector, create two
470 other perpendicular vectors
471 ================
472 */
MakeNormalVectors(const vec3_t forward,vec3_t right,vec3_t up)473 void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up) {
474 	float		d;
475 
476 	// this rotate and negate guarantees a vector
477 	// not colinear with the original
478 	right[1] = -forward[0];
479 	right[2] = forward[1];
480 	right[0] = forward[2];
481 
482 	d = DotProduct (right, forward);
483 	VectorMA (right, -d, forward, right);
484 	VectorNormalize (right);
485 	CrossProduct (right, forward, up);
486 }
487 
488 
VectorRotate(vec3_t in,vec3_t matrix[3],vec3_t out)489 void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out )
490 {
491 	out[0] = DotProduct( in, matrix[0] );
492 	out[1] = DotProduct( in, matrix[1] );
493 	out[2] = DotProduct( in, matrix[2] );
494 }
495 
496 //============================================================================
497 
498 #if !idppc
499 /*
500 ** float q_rsqrt( float number )
501 */
Q_rsqrt(float number)502 float Q_rsqrt( float number )
503 {
504 	union {
505 		float f;
506 		int i;
507 	} t;
508 	float x2, y;
509 	const float threehalfs = 1.5F;
510 
511 	x2 = number * 0.5F;
512 	t.f  = number;
513 	t.i  = 0x5f3759df - ( t.i >> 1 );               // what the fuck?
514 	y  = t.f;
515 	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
516 //	y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
517 
518 	return y;
519 }
520 
Q_fabs(float f)521 float Q_fabs( float f ) {
522 	int tmp = * ( int * ) &f;
523 	tmp &= 0x7FFFFFFF;
524 	return * ( float * ) &tmp;
525 }
526 #endif
527 
528 //============================================================
529 
530 /*
531 ===============
532 LerpAngle
533 
534 ===============
535 */
LerpAngle(float from,float to,float frac)536 float LerpAngle (float from, float to, float frac) {
537 	float	a;
538 
539 	if ( to - from > 180 ) {
540 		to -= 360;
541 	}
542 	if ( to - from < -180 ) {
543 		to += 360;
544 	}
545 	a = from + frac * (to - from);
546 
547 	return a;
548 }
549 
550 
551 /*
552 =================
553 AngleSubtract
554 
555 Always returns a value from -180 to 180
556 =================
557 */
AngleSubtract(float a1,float a2)558 float	AngleSubtract( float a1, float a2 ) {
559 	float	a;
560 
561 	a = a1 - a2;
562 	while ( a > 180 ) {
563 		a -= 360;
564 	}
565 	while ( a < -180 ) {
566 		a += 360;
567 	}
568 	return a;
569 }
570 
571 
AnglesSubtract(vec3_t v1,vec3_t v2,vec3_t v3)572 void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ) {
573 	v3[0] = AngleSubtract( v1[0], v2[0] );
574 	v3[1] = AngleSubtract( v1[1], v2[1] );
575 	v3[2] = AngleSubtract( v1[2], v2[2] );
576 }
577 
578 
AngleMod(float a)579 float	AngleMod(float a) {
580 	a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
581 	return a;
582 }
583 
584 
585 /*
586 =================
587 AngleNormalize360
588 
589 returns angle normalized to the range [0 <= angle < 360]
590 =================
591 */
AngleNormalize360(float angle)592 float AngleNormalize360 ( float angle ) {
593 	return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535);
594 }
595 
596 
597 /*
598 =================
599 AngleNormalize180
600 
601 returns angle normalized to the range [-180 < angle <= 180]
602 =================
603 */
AngleNormalize180(float angle)604 float AngleNormalize180 ( float angle ) {
605 	angle = AngleNormalize360( angle );
606 	if ( angle > 180.0 ) {
607 		angle -= 360.0;
608 	}
609 	return angle;
610 }
611 
612 
613 /*
614 =================
615 AngleDelta
616 
617 returns the normalized delta from angle1 to angle2
618 =================
619 */
AngleDelta(float angle1,float angle2)620 float AngleDelta ( float angle1, float angle2 ) {
621 	return AngleNormalize180( angle1 - angle2 );
622 }
623 
624 
625 //============================================================
626 
627 
628 /*
629 =================
630 SetPlaneSignbits
631 =================
632 */
SetPlaneSignbits(cplane_t * out)633 void SetPlaneSignbits (cplane_t *out) {
634 	int	bits, j;
635 
636 	// for fast box on planeside test
637 	bits = 0;
638 	for (j=0 ; j<3 ; j++) {
639 		if (out->normal[j] < 0) {
640 			bits |= 1<<j;
641 		}
642 	}
643 	out->signbits = bits;
644 }
645 
646 
647 /*
648 ==================
649 BoxOnPlaneSide
650 
651 Returns 1, 2, or 1 + 2
652 
653 // this is the slow, general version
654 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
655 {
656 	int		i;
657 	float	dist1, dist2;
658 	int		sides;
659 	vec3_t	corners[2];
660 
661 	for (i=0 ; i<3 ; i++)
662 	{
663 		if (p->normal[i] < 0)
664 		{
665 			corners[0][i] = emins[i];
666 			corners[1][i] = emaxs[i];
667 		}
668 		else
669 		{
670 			corners[1][i] = emins[i];
671 			corners[0][i] = emaxs[i];
672 		}
673 	}
674 	dist1 = DotProduct (p->normal, corners[0]) - p->dist;
675 	dist2 = DotProduct (p->normal, corners[1]) - p->dist;
676 	sides = 0;
677 	if (dist1 >= 0)
678 		sides = 1;
679 	if (dist2 < 0)
680 		sides |= 2;
681 
682 	return sides;
683 }
684 
685 ==================
686 */
687 
688 #if !id386
689 
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)690 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
691 {
692 	float	dist1, dist2;
693 	int		sides;
694 
695 // fast axial cases
696 	if (p->type < 3)
697 	{
698 		if (p->dist <= emins[p->type])
699 			return 1;
700 		if (p->dist >= emaxs[p->type])
701 			return 2;
702 		return 3;
703 	}
704 
705 // general case
706 	switch (p->signbits)
707 	{
708 	case 0:
709 		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
710 		dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
711 		break;
712 	case 1:
713 		dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
714 		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
715 		break;
716 	case 2:
717 		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
718 		dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
719 		break;
720 	case 3:
721 		dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
722 		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
723 		break;
724 	case 4:
725 		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
726 		dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
727 		break;
728 	case 5:
729 		dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
730 		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
731 		break;
732 	case 6:
733 		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
734 		dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
735 		break;
736 	case 7:
737 		dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
738 		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
739 		break;
740 	default:
741 		dist1 = dist2 = 0;		// shut up compiler
742 		break;
743 	}
744 
745 	sides = 0;
746 	if (dist1 >= p->dist)
747 		sides = 1;
748 	if (dist2 < p->dist)
749 		sides |= 2;
750 
751 	return sides;
752 }
753 #elif __GNUC__
754 // use matha.s
755 #else
756 #pragma warning( disable: 4035 )
757 
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)758 __declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
759 {
760 	static int bops_initialized;
761 	static int Ljmptab[8];
762 
763 	__asm {
764 
765 		push ebx
766 
767 		cmp bops_initialized, 1
768 		je  initialized
769 		mov bops_initialized, 1
770 
771 		mov Ljmptab[0*4], offset Lcase0
772 		mov Ljmptab[1*4], offset Lcase1
773 		mov Ljmptab[2*4], offset Lcase2
774 		mov Ljmptab[3*4], offset Lcase3
775 		mov Ljmptab[4*4], offset Lcase4
776 		mov Ljmptab[5*4], offset Lcase5
777 		mov Ljmptab[6*4], offset Lcase6
778 		mov Ljmptab[7*4], offset Lcase7
779 
780 initialized:
781 
782 		mov edx,dword ptr[4+12+esp]
783 		mov ecx,dword ptr[4+4+esp]
784 		xor eax,eax
785 		mov ebx,dword ptr[4+8+esp]
786 		mov al,byte ptr[17+edx]
787 		cmp al,8
788 		jge Lerror
789 		fld dword ptr[0+edx]
790 		fld st(0)
791 		jmp dword ptr[Ljmptab+eax*4]
792 Lcase0:
793 		fmul dword ptr[ebx]
794 		fld dword ptr[0+4+edx]
795 		fxch st(2)
796 		fmul dword ptr[ecx]
797 		fxch st(2)
798 		fld st(0)
799 		fmul dword ptr[4+ebx]
800 		fld dword ptr[0+8+edx]
801 		fxch st(2)
802 		fmul dword ptr[4+ecx]
803 		fxch st(2)
804 		fld st(0)
805 		fmul dword ptr[8+ebx]
806 		fxch st(5)
807 		faddp st(3),st(0)
808 		fmul dword ptr[8+ecx]
809 		fxch st(1)
810 		faddp st(3),st(0)
811 		fxch st(3)
812 		faddp st(2),st(0)
813 		jmp LSetSides
814 Lcase1:
815 		fmul dword ptr[ecx]
816 		fld dword ptr[0+4+edx]
817 		fxch st(2)
818 		fmul dword ptr[ebx]
819 		fxch st(2)
820 		fld st(0)
821 		fmul dword ptr[4+ebx]
822 		fld dword ptr[0+8+edx]
823 		fxch st(2)
824 		fmul dword ptr[4+ecx]
825 		fxch st(2)
826 		fld st(0)
827 		fmul dword ptr[8+ebx]
828 		fxch st(5)
829 		faddp st(3),st(0)
830 		fmul dword ptr[8+ecx]
831 		fxch st(1)
832 		faddp st(3),st(0)
833 		fxch st(3)
834 		faddp st(2),st(0)
835 		jmp LSetSides
836 Lcase2:
837 		fmul dword ptr[ebx]
838 		fld dword ptr[0+4+edx]
839 		fxch st(2)
840 		fmul dword ptr[ecx]
841 		fxch st(2)
842 		fld st(0)
843 		fmul dword ptr[4+ecx]
844 		fld dword ptr[0+8+edx]
845 		fxch st(2)
846 		fmul dword ptr[4+ebx]
847 		fxch st(2)
848 		fld st(0)
849 		fmul dword ptr[8+ebx]
850 		fxch st(5)
851 		faddp st(3),st(0)
852 		fmul dword ptr[8+ecx]
853 		fxch st(1)
854 		faddp st(3),st(0)
855 		fxch st(3)
856 		faddp st(2),st(0)
857 		jmp LSetSides
858 Lcase3:
859 		fmul dword ptr[ecx]
860 		fld dword ptr[0+4+edx]
861 		fxch st(2)
862 		fmul dword ptr[ebx]
863 		fxch st(2)
864 		fld st(0)
865 		fmul dword ptr[4+ecx]
866 		fld dword ptr[0+8+edx]
867 		fxch st(2)
868 		fmul dword ptr[4+ebx]
869 		fxch st(2)
870 		fld st(0)
871 		fmul dword ptr[8+ebx]
872 		fxch st(5)
873 		faddp st(3),st(0)
874 		fmul dword ptr[8+ecx]
875 		fxch st(1)
876 		faddp st(3),st(0)
877 		fxch st(3)
878 		faddp st(2),st(0)
879 		jmp LSetSides
880 Lcase4:
881 		fmul dword ptr[ebx]
882 		fld dword ptr[0+4+edx]
883 		fxch st(2)
884 		fmul dword ptr[ecx]
885 		fxch st(2)
886 		fld st(0)
887 		fmul dword ptr[4+ebx]
888 		fld dword ptr[0+8+edx]
889 		fxch st(2)
890 		fmul dword ptr[4+ecx]
891 		fxch st(2)
892 		fld st(0)
893 		fmul dword ptr[8+ecx]
894 		fxch st(5)
895 		faddp st(3),st(0)
896 		fmul dword ptr[8+ebx]
897 		fxch st(1)
898 		faddp st(3),st(0)
899 		fxch st(3)
900 		faddp st(2),st(0)
901 		jmp LSetSides
902 Lcase5:
903 		fmul dword ptr[ecx]
904 		fld dword ptr[0+4+edx]
905 		fxch st(2)
906 		fmul dword ptr[ebx]
907 		fxch st(2)
908 		fld st(0)
909 		fmul dword ptr[4+ebx]
910 		fld dword ptr[0+8+edx]
911 		fxch st(2)
912 		fmul dword ptr[4+ecx]
913 		fxch st(2)
914 		fld st(0)
915 		fmul dword ptr[8+ecx]
916 		fxch st(5)
917 		faddp st(3),st(0)
918 		fmul dword ptr[8+ebx]
919 		fxch st(1)
920 		faddp st(3),st(0)
921 		fxch st(3)
922 		faddp st(2),st(0)
923 		jmp LSetSides
924 Lcase6:
925 		fmul dword ptr[ebx]
926 		fld dword ptr[0+4+edx]
927 		fxch st(2)
928 		fmul dword ptr[ecx]
929 		fxch st(2)
930 		fld st(0)
931 		fmul dword ptr[4+ecx]
932 		fld dword ptr[0+8+edx]
933 		fxch st(2)
934 		fmul dword ptr[4+ebx]
935 		fxch st(2)
936 		fld st(0)
937 		fmul dword ptr[8+ecx]
938 		fxch st(5)
939 		faddp st(3),st(0)
940 		fmul dword ptr[8+ebx]
941 		fxch st(1)
942 		faddp st(3),st(0)
943 		fxch st(3)
944 		faddp st(2),st(0)
945 		jmp LSetSides
946 Lcase7:
947 		fmul dword ptr[ecx]
948 		fld dword ptr[0+4+edx]
949 		fxch st(2)
950 		fmul dword ptr[ebx]
951 		fxch st(2)
952 		fld st(0)
953 		fmul dword ptr[4+ecx]
954 		fld dword ptr[0+8+edx]
955 		fxch st(2)
956 		fmul dword ptr[4+ebx]
957 		fxch st(2)
958 		fld st(0)
959 		fmul dword ptr[8+ecx]
960 		fxch st(5)
961 		faddp st(3),st(0)
962 		fmul dword ptr[8+ebx]
963 		fxch st(1)
964 		faddp st(3),st(0)
965 		fxch st(3)
966 		faddp st(2),st(0)
967 LSetSides:
968 		faddp st(2),st(0)
969 		fcomp dword ptr[12+edx]
970 		xor ecx,ecx
971 		fnstsw ax
972 		fcomp dword ptr[12+edx]
973 		and ah,1
974 		xor ah,1
975 		add cl,ah
976 		fnstsw ax
977 		and ah,1
978 		add ah,ah
979 		add cl,ah
980 		pop ebx
981 		mov eax,ecx
982 		ret
983 Lerror:
984 		int 3
985 	}
986 }
987 #pragma warning( default: 4035 )
988 
989 #endif
990 
991 /*
992 =================
993 RadiusFromBounds
994 =================
995 */
RadiusFromBounds(const vec3_t mins,const vec3_t maxs)996 float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) {
997 	int		i;
998 	vec3_t	corner;
999 	float	a, b;
1000 
1001 	for (i=0 ; i<3 ; i++) {
1002 		a = fabs( mins[i] );
1003 		b = fabs( maxs[i] );
1004 		corner[i] = a > b ? a : b;
1005 	}
1006 
1007 	return VectorLength (corner);
1008 }
1009 
1010 
ClearBounds(vec3_t mins,vec3_t maxs)1011 void ClearBounds( vec3_t mins, vec3_t maxs ) {
1012 	mins[0] = mins[1] = mins[2] = 99999;
1013 	maxs[0] = maxs[1] = maxs[2] = -99999;
1014 }
1015 
AddPointToBounds(const vec3_t v,vec3_t mins,vec3_t maxs)1016 void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) {
1017 	if ( v[0] < mins[0] ) {
1018 		mins[0] = v[0];
1019 	}
1020 	if ( v[0] > maxs[0]) {
1021 		maxs[0] = v[0];
1022 	}
1023 
1024 	if ( v[1] < mins[1] ) {
1025 		mins[1] = v[1];
1026 	}
1027 	if ( v[1] > maxs[1]) {
1028 		maxs[1] = v[1];
1029 	}
1030 
1031 	if ( v[2] < mins[2] ) {
1032 		mins[2] = v[2];
1033 	}
1034 	if ( v[2] > maxs[2]) {
1035 		maxs[2] = v[2];
1036 	}
1037 }
1038 
BoundsIntersect(const vec3_t mins,const vec3_t maxs,const vec3_t mins2,const vec3_t maxs2)1039 qboolean BoundsIntersect(const vec3_t mins, const vec3_t maxs,
1040 		const vec3_t mins2, const vec3_t maxs2)
1041 {
1042 	if ( maxs[0] < mins2[0] ||
1043 		maxs[1] < mins2[1] ||
1044 		maxs[2] < mins2[2] ||
1045 		mins[0] > maxs2[0] ||
1046 		mins[1] > maxs2[1] ||
1047 		mins[2] > maxs2[2])
1048 	{
1049 		return qfalse;
1050 	}
1051 
1052 	return qtrue;
1053 }
1054 
BoundsIntersectSphere(const vec3_t mins,const vec3_t maxs,const vec3_t origin,vec_t radius)1055 qboolean BoundsIntersectSphere(const vec3_t mins, const vec3_t maxs,
1056 		const vec3_t origin, vec_t radius)
1057 {
1058 	if ( origin[0] - radius > maxs[0] ||
1059 		origin[0] + radius < mins[0] ||
1060 		origin[1] - radius > maxs[1] ||
1061 		origin[1] + radius < mins[1] ||
1062 		origin[2] - radius > maxs[2] ||
1063 		origin[2] + radius < mins[2])
1064 	{
1065 		return qfalse;
1066 	}
1067 
1068 	return qtrue;
1069 }
1070 
BoundsIntersectPoint(const vec3_t mins,const vec3_t maxs,const vec3_t origin)1071 qboolean BoundsIntersectPoint(const vec3_t mins, const vec3_t maxs,
1072 		const vec3_t origin)
1073 {
1074 	if ( origin[0] > maxs[0] ||
1075 		origin[0] < mins[0] ||
1076 		origin[1] > maxs[1] ||
1077 		origin[1] < mins[1] ||
1078 		origin[2] > maxs[2] ||
1079 		origin[2] < mins[2])
1080 	{
1081 		return qfalse;
1082 	}
1083 
1084 	return qtrue;
1085 }
1086 
VectorNormalize(vec3_t v)1087 vec_t VectorNormalize( vec3_t v ) {
1088 	// NOTE: TTimo - Apple G4 altivec source uses double?
1089 	float	length, ilength;
1090 
1091 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
1092 	length = sqrt (length);
1093 
1094 	if ( length ) {
1095 		ilength = 1/length;
1096 		v[0] *= ilength;
1097 		v[1] *= ilength;
1098 		v[2] *= ilength;
1099 	}
1100 
1101 	return length;
1102 }
1103 
VectorNormalize2(const vec3_t v,vec3_t out)1104 vec_t VectorNormalize2( const vec3_t v, vec3_t out) {
1105 	float	length, ilength;
1106 
1107 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
1108 	length = sqrt (length);
1109 
1110 	if (length)
1111 	{
1112 		ilength = 1/length;
1113 		out[0] = v[0]*ilength;
1114 		out[1] = v[1]*ilength;
1115 		out[2] = v[2]*ilength;
1116 	} else {
1117 		VectorClear( out );
1118 	}
1119 
1120 	return length;
1121 
1122 }
1123 
_VectorMA(const vec3_t veca,float scale,const vec3_t vecb,vec3_t vecc)1124 void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) {
1125 	vecc[0] = veca[0] + scale*vecb[0];
1126 	vecc[1] = veca[1] + scale*vecb[1];
1127 	vecc[2] = veca[2] + scale*vecb[2];
1128 }
1129 
1130 
_DotProduct(const vec3_t v1,const vec3_t v2)1131 vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ) {
1132 	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
1133 }
1134 
_VectorSubtract(const vec3_t veca,const vec3_t vecb,vec3_t out)1135 void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
1136 	out[0] = veca[0]-vecb[0];
1137 	out[1] = veca[1]-vecb[1];
1138 	out[2] = veca[2]-vecb[2];
1139 }
1140 
_VectorAdd(const vec3_t veca,const vec3_t vecb,vec3_t out)1141 void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ) {
1142 	out[0] = veca[0]+vecb[0];
1143 	out[1] = veca[1]+vecb[1];
1144 	out[2] = veca[2]+vecb[2];
1145 }
1146 
_VectorCopy(const vec3_t in,vec3_t out)1147 void _VectorCopy( const vec3_t in, vec3_t out ) {
1148 	out[0] = in[0];
1149 	out[1] = in[1];
1150 	out[2] = in[2];
1151 }
1152 
_VectorScale(const vec3_t in,vec_t scale,vec3_t out)1153 void _VectorScale( const vec3_t in, vec_t scale, vec3_t out ) {
1154 	out[0] = in[0]*scale;
1155 	out[1] = in[1]*scale;
1156 	out[2] = in[2]*scale;
1157 }
1158 
Vector4Scale(const vec4_t in,vec_t scale,vec4_t out)1159 void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ) {
1160 	out[0] = in[0]*scale;
1161 	out[1] = in[1]*scale;
1162 	out[2] = in[2]*scale;
1163 	out[3] = in[3]*scale;
1164 }
1165 
1166 
Q_log2(int val)1167 int Q_log2( int val ) {
1168 	int answer;
1169 
1170 	answer = 0;
1171 	while ( ( val>>=1 ) != 0 ) {
1172 		answer++;
1173 	}
1174 	return answer;
1175 }
1176 
1177 
1178 
1179 /*
1180 =================
1181 PlaneTypeForNormal
1182 =================
1183 */
1184 /*
1185 int	PlaneTypeForNormal (vec3_t normal) {
1186 	if ( normal[0] == 1.0 )
1187 		return PLANE_X;
1188 	if ( normal[1] == 1.0 )
1189 		return PLANE_Y;
1190 	if ( normal[2] == 1.0 )
1191 		return PLANE_Z;
1192 
1193 	return PLANE_NON_AXIAL;
1194 }
1195 */
1196 
1197 
1198 /*
1199 ================
1200 MatrixMultiply
1201 ================
1202 */
MatrixMultiply(float in1[3][3],float in2[3][3],float out[3][3])1203 void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
1204 	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
1205 				in1[0][2] * in2[2][0];
1206 	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
1207 				in1[0][2] * in2[2][1];
1208 	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
1209 				in1[0][2] * in2[2][2];
1210 	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
1211 				in1[1][2] * in2[2][0];
1212 	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
1213 				in1[1][2] * in2[2][1];
1214 	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
1215 				in1[1][2] * in2[2][2];
1216 	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
1217 				in1[2][2] * in2[2][0];
1218 	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
1219 				in1[2][2] * in2[2][1];
1220 	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
1221 				in1[2][2] * in2[2][2];
1222 }
1223 
1224 
AngleVectors(const vec3_t angles,vec3_t forward,vec3_t right,vec3_t up)1225 void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) {
1226 	float		angle;
1227 	static float		sr, sp, sy, cr, cp, cy;
1228 	// static to help MS compiler fp bugs
1229 
1230 	angle = angles[YAW] * (M_PI*2 / 360);
1231 	sy = sin(angle);
1232 	cy = cos(angle);
1233 	angle = angles[PITCH] * (M_PI*2 / 360);
1234 	sp = sin(angle);
1235 	cp = cos(angle);
1236 	angle = angles[ROLL] * (M_PI*2 / 360);
1237 	sr = sin(angle);
1238 	cr = cos(angle);
1239 
1240 	if (forward)
1241 	{
1242 		forward[0] = cp*cy;
1243 		forward[1] = cp*sy;
1244 		forward[2] = -sp;
1245 	}
1246 	if (right)
1247 	{
1248 		right[0] = (-1*sr*sp*cy+-1*cr*-sy);
1249 		right[1] = (-1*sr*sp*sy+-1*cr*cy);
1250 		right[2] = -1*sr*cp;
1251 	}
1252 	if (up)
1253 	{
1254 		up[0] = (cr*sp*cy+-sr*-sy);
1255 		up[1] = (cr*sp*sy+-sr*cy);
1256 		up[2] = cr*cp;
1257 	}
1258 }
1259 
1260 /*
1261 ** assumes "src" is normalized
1262 */
PerpendicularVector(vec3_t dst,const vec3_t src)1263 void PerpendicularVector( vec3_t dst, const vec3_t src )
1264 {
1265 	int	pos;
1266 	int i;
1267 	float minelem = 1.0F;
1268 	vec3_t tempvec;
1269 
1270 	/*
1271 	** find the smallest magnitude axially aligned vector
1272 	*/
1273 	for ( pos = 0, i = 0; i < 3; i++ )
1274 	{
1275 		if ( fabs( src[i] ) < minelem )
1276 		{
1277 			pos = i;
1278 			minelem = fabs( src[i] );
1279 		}
1280 	}
1281 	tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
1282 	tempvec[pos] = 1.0F;
1283 
1284 	/*
1285 	** project the point onto the plane defined by src
1286 	*/
1287 	ProjectPointOnPlane( dst, tempvec, src );
1288 
1289 	/*
1290 	** normalize the result
1291 	*/
1292 	VectorNormalize( dst );
1293 }
1294 
1295 /*
1296 ================
1297 Q_isnan
1298 
1299 Don't pass doubles to this
1300 ================
1301 */
Q_isnan(float x)1302 int Q_isnan( float x )
1303 {
1304 	union
1305 	{
1306 		float f;
1307 		unsigned int i;
1308 	} t;
1309 
1310 	t.f = x;
1311 	t.i &= 0x7FFFFFFF;
1312 	t.i = 0x7F800000 - t.i;
1313 
1314 	return (int)( (unsigned int)t.i >> 31 );
1315 }
1316