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