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