1 // this file is not distributed under the GNU General Public License
2 // refer to id_license.txt for the id source license
3 
4 #include <assert.h>
5 #include <math.h>
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <time.h>
11 
12 #include "shared.h"
13 #include "q2utils.h"
14 
15 #ifdef WIN32
16 #pragma warning(disable: 4244)	// double to float conversion
17 #pragma warning(disable: 4018)	// signed/unsigned mismatch
18 #endif
19 
20 #define DEG2RAD( a ) ( a * M_PI ) / 180.0F
21 
22 vec3_t vec3_origin = {0,0,0};
23 
24 //============================================================================
25 
26 #ifdef _WIN32
27 #pragma optimize( "", off )
28 #endif
29 
RotatePointAroundVector(vec3_t dst,const vec3_t dir,const vec3_t point,float degrees)30 void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
31 {
32 	float	m[3][3];
33 	float	im[3][3];
34 	float	zrot[3][3];
35 	float	tmpmat[3][3];
36 	float	rot[3][3];
37 	int i;
38 	vec3_t vr, vup, vf;
39 
40 	vf[0] = dir[0];
41 	vf[1] = dir[1];
42 	vf[2] = dir[2];
43 
44 	PerpendicularVector( vr, dir );
45 	CrossProduct( vr, vf, vup );
46 
47 	m[0][0] = vr[0];
48 	m[1][0] = vr[1];
49 	m[2][0] = vr[2];
50 
51 	m[0][1] = vup[0];
52 	m[1][1] = vup[1];
53 	m[2][1] = vup[2];
54 
55 	m[0][2] = vf[0];
56 	m[1][2] = vf[1];
57 	m[2][2] = vf[2];
58 
59 	memcpy( im, m, sizeof( im ) );
60 
61 	im[0][1] = m[1][0];
62 	im[0][2] = m[2][0];
63 	im[1][0] = m[0][1];
64 	im[1][2] = m[2][1];
65 	im[2][0] = m[0][2];
66 	im[2][1] = m[1][2];
67 
68 	memset( zrot, 0, sizeof( zrot ) );
69 	zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
70 
71 	zrot[0][0] = cos( DEG2RAD( degrees ) );
72 	zrot[0][1] = sin( DEG2RAD( degrees ) );
73 	zrot[1][0] = -sin( DEG2RAD( degrees ) );
74 	zrot[1][1] = cos( DEG2RAD( degrees ) );
75 
76 	R_ConcatRotations( m, zrot, tmpmat );
77 	R_ConcatRotations( tmpmat, im, rot );
78 
79 	for ( i = 0; i < 3; i++ )
80 	{
81 		dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
82 	}
83 }
84 
85 #ifdef _WIN32
86 #pragma optimize( "", on )
87 #endif
88 
89 
90 
AngleVectors(vec3_t angles,vec3_t forward,vec3_t right,vec3_t up)91 void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
92 {
93 	float		angle;
94 	static float		sr, sp, sy, cr, cp, cy;
95 	// static to help MS compiler fp bugs
96 
97 	angle = angles[YAW] * (M_PI*2 / 360);
98 	sy = sin(angle);
99 	cy = cos(angle);
100 	angle = angles[PITCH] * (M_PI*2 / 360);
101 	sp = sin(angle);
102 	cp = cos(angle);
103 	angle = angles[ROLL] * (M_PI*2 / 360);
104 	sr = sin(angle);
105 	cr = cos(angle);
106 
107 	if (forward)
108 	{
109 		forward[0] = cp*cy;
110 		forward[1] = cp*sy;
111 		forward[2] = -sp;
112 	}
113 	if (right)
114 	{
115 		right[0] = (-1*sr*sp*cy+-1*cr*-sy);
116 		right[1] = (-1*sr*sp*sy+-1*cr*cy);
117 		right[2] = -1*sr*cp;
118 	}
119 	if (up)
120 	{
121 		up[0] = (cr*sp*cy+-sr*-sy);
122 		up[1] = (cr*sp*sy+-sr*cy);
123 		up[2] = cr*cp;
124 	}
125 }
126 
ProjectPointOnPlane(vec3_t dst,const vec3_t p,const vec3_t normal)127 void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
128 {
129 	float d;
130 	vec3_t n;
131 	float inv_denom;
132 
133 	inv_denom = 1.0F / DotProduct( normal, normal );
134 
135 	d = DotProduct( normal, p ) * inv_denom;
136 
137 	n[0] = normal[0] * inv_denom;
138 	n[1] = normal[1] * inv_denom;
139 	n[2] = normal[2] * inv_denom;
140 
141 	dst[0] = p[0] - d * n[0];
142 	dst[1] = p[1] - d * n[1];
143 	dst[2] = p[2] - d * n[2];
144 }
145 
146 /*
147 ** assumes "src" is normalized
148 */
PerpendicularVector(vec3_t dst,const vec3_t src)149 void PerpendicularVector( vec3_t dst, const vec3_t src )
150 {
151 	int pos;
152 	int i;
153 	float minelem = 1.0F;
154 	vec3_t tempvec;
155 
156 	/*
157 	** find the smallest magnitude axially aligned vector
158 	*/
159 	for ( pos = 0, i = 0; i < 3; i++ )
160 	{
161 		if ( fabs( src[i] ) < minelem )
162 		{
163 			pos = i;
164 			minelem = fabs( src[i] );
165 		}
166 	}
167 	tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
168 	tempvec[pos] = 1.0F;
169 
170 	/*
171 	** project the point onto the plane defined by src
172 	*/
173 	ProjectPointOnPlane( dst, tempvec, src );
174 
175 	/*
176 	** normalize the result
177 	*/
178 	VectorNormalize( dst );
179 }
180 
181 
182 
183 /*
184 ================
185 R_ConcatRotations
186 ================
187 */
R_ConcatRotations(float in1[3][3],float in2[3][3],float out[3][3])188 void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3])
189 {
190 	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
191 				in1[0][2] * in2[2][0];
192 	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
193 				in1[0][2] * in2[2][1];
194 	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
195 				in1[0][2] * in2[2][2];
196 	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
197 				in1[1][2] * in2[2][0];
198 	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
199 				in1[1][2] * in2[2][1];
200 	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
201 				in1[1][2] * in2[2][2];
202 	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
203 				in1[2][2] * in2[2][0];
204 	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
205 				in1[2][2] * in2[2][1];
206 	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
207 				in1[2][2] * in2[2][2];
208 }
209 
210 
211 /*
212 ================
213 R_ConcatTransforms
214 ================
215 */
R_ConcatTransforms(float in1[3][4],float in2[3][4],float out[3][4])216 void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4])
217 {
218 	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
219 				in1[0][2] * in2[2][0];
220 	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
221 				in1[0][2] * in2[2][1];
222 	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
223 				in1[0][2] * in2[2][2];
224 	out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] +
225 				in1[0][2] * in2[2][3] + in1[0][3];
226 	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
227 				in1[1][2] * in2[2][0];
228 	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
229 				in1[1][2] * in2[2][1];
230 	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
231 				in1[1][2] * in2[2][2];
232 	out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] +
233 				in1[1][2] * in2[2][3] + in1[1][3];
234 	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
235 				in1[2][2] * in2[2][0];
236 	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
237 				in1[2][2] * in2[2][1];
238 	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
239 				in1[2][2] * in2[2][2];
240 	out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] +
241 				in1[2][2] * in2[2][3] + in1[2][3];
242 }
243 
244 
245 //============================================================================
246 
247 
Q_fabs(float f)248 float Q_fabs (float f)
249 {
250 #if 0
251 	if (f >= 0)
252 		return f;
253 	return -f;
254 #else
255 	int tmp = * ( int * ) &f;
256 	tmp &= 0x7FFFFFFF;
257 	return * ( float * ) &tmp;
258 #endif
259 }
260 
261 #if defined _M_IX86 && !defined C_ONLY
262 #pragma warning (disable:4035)
Q_ftol(float f)263 __declspec( naked ) long Q_ftol( float f )
264 {
265 	static int tmp;
266 	__asm fld dword ptr [esp+4]
267 	__asm fistp tmp
268 	__asm mov eax, tmp
269 	__asm ret
270 }
271 #pragma warning (default:4035)
272 #endif
273 
274 /*
275 ===============
276 LerpAngle
277 
278 ===============
279 */
LerpAngle(float a2,float a1,float frac)280 float LerpAngle (float a2, float a1, float frac)
281 {
282 	if (a1 - a2 > 180)
283 		a1 -= 360;
284 	if (a1 - a2 < -180)
285 		a1 += 360;
286 	return a2 + frac * (a1 - a2);
287 }
288 
289 
anglemod(float a)290 float	anglemod(float a)
291 {
292 #if 0
293 	if (a >= 0)
294 		a -= 360*(int)(a/360);
295 	else
296 		a += 360*( 1 + (int)(-a/360) );
297 #endif
298 	a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535);
299 	return a;
300 }
301 
302 	int 	i;
303 	vec3_t	corners[2];
304 
305 
306 // this is the slow, general version
BoxOnPlaneSide2(vec3_t emins,vec3_t emaxs,struct cplane_s * p)307 int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
308 {
309 	int 	i;
310 	float	dist1, dist2;
311 	int 	sides;
312 	vec3_t	corners[2];
313 
314 	for (i=0 ; i<3 ; i++)
315 	{
316 		if (p->normal[i] < 0)
317 		{
318 			corners[0][i] = emins[i];
319 			corners[1][i] = emaxs[i];
320 		}
321 		else
322 		{
323 			corners[1][i] = emins[i];
324 			corners[0][i] = emaxs[i];
325 		}
326 	}
327 	dist1 = DotProduct (p->normal, corners[0]) - p->dist;
328 	dist2 = DotProduct (p->normal, corners[1]) - p->dist;
329 	sides = 0;
330 	if (dist1 >= 0)
331 		sides = 1;
332 	if (dist2 < 0)
333 		sides |= 2;
334 
335 	return sides;
336 }
337 
338 /*
339 ==================
340 BoxOnPlaneSide
341 
342 Returns 1, 2, or 1 + 2
343 ==================
344 */
345 #if !id386 || defined __linux__
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)346 int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
347 {
348 	float	dist1, dist2;
349 	int 	sides;
350 
351 // fast axial cases
352 	if (p->type < 3)
353 	{
354 		if (p->dist <= emins[p->type])
355 			return 1;
356 		if (p->dist >= emaxs[p->type])
357 			return 2;
358 		return 3;
359 	}
360 
361 // general case
362 	switch (p->signbits)
363 	{
364 	case 0:
365 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
366 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
367 		break;
368 	case 1:
369 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
370 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
371 		break;
372 	case 2:
373 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
374 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
375 		break;
376 	case 3:
377 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
378 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
379 		break;
380 	case 4:
381 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
382 dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
383 		break;
384 	case 5:
385 dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
386 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
387 		break;
388 	case 6:
389 dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
390 dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
391 		break;
392 	case 7:
393 dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
394 dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
395 		break;
396 	default:
397 		dist1 = dist2 = 0;		// shut up compiler
398 		assert( 0 );
399 		break;
400 	}
401 
402 	sides = 0;
403 	if (dist1 >= p->dist)
404 		sides = 1;
405 	if (dist2 < p->dist)
406 		sides |= 2;
407 
408 	assert( sides != 0 );
409 
410 	return sides;
411 }
412 #else
413 #pragma warning( disable: 4035 )
414 
BoxOnPlaneSide(vec3_t emins,vec3_t emaxs,struct cplane_s * p)415 __declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p)
416 {
417 	static int bops_initialized;
418 	static int Ljmptab[8];
419 
420 	__asm {
421 
422 		push ebx
423 
424 		cmp bops_initialized, 1
425 		je	initialized
426 		mov bops_initialized, 1
427 
428 		mov Ljmptab[0*4], offset Lcase0
429 		mov Ljmptab[1*4], offset Lcase1
430 		mov Ljmptab[2*4], offset Lcase2
431 		mov Ljmptab[3*4], offset Lcase3
432 		mov Ljmptab[4*4], offset Lcase4
433 		mov Ljmptab[5*4], offset Lcase5
434 		mov Ljmptab[6*4], offset Lcase6
435 		mov Ljmptab[7*4], offset Lcase7
436 
437 initialized:
438 
439 		mov edx,ds:dword ptr[4+12+esp]
440 		mov ecx,ds:dword ptr[4+4+esp]
441 		xor eax,eax
442 		mov ebx,ds:dword ptr[4+8+esp]
443 		mov al,ds:byte ptr[17+edx]
444 		cmp al,8
445 		jge Lerror
446 		fld ds:dword ptr[0+edx]
447 		fld st(0)
448 		jmp dword ptr[Ljmptab+eax*4]
449 Lcase0:
450 		fmul ds:dword ptr[ebx]
451 		fld ds:dword ptr[0+4+edx]
452 		fxch st(2)
453 		fmul ds:dword ptr[ecx]
454 		fxch st(2)
455 		fld st(0)
456 		fmul ds:dword ptr[4+ebx]
457 		fld ds:dword ptr[0+8+edx]
458 		fxch st(2)
459 		fmul ds:dword ptr[4+ecx]
460 		fxch st(2)
461 		fld st(0)
462 		fmul ds:dword ptr[8+ebx]
463 		fxch st(5)
464 		faddp st(3),st(0)
465 		fmul ds:dword ptr[8+ecx]
466 		fxch st(1)
467 		faddp st(3),st(0)
468 		fxch st(3)
469 		faddp st(2),st(0)
470 		jmp LSetSides
471 Lcase1:
472 		fmul ds:dword ptr[ecx]
473 		fld ds:dword ptr[0+4+edx]
474 		fxch st(2)
475 		fmul ds:dword ptr[ebx]
476 		fxch st(2)
477 		fld st(0)
478 		fmul ds:dword ptr[4+ebx]
479 		fld ds:dword ptr[0+8+edx]
480 		fxch st(2)
481 		fmul ds:dword ptr[4+ecx]
482 		fxch st(2)
483 		fld st(0)
484 		fmul ds:dword ptr[8+ebx]
485 		fxch st(5)
486 		faddp st(3),st(0)
487 		fmul ds:dword ptr[8+ecx]
488 		fxch st(1)
489 		faddp st(3),st(0)
490 		fxch st(3)
491 		faddp st(2),st(0)
492 		jmp LSetSides
493 Lcase2:
494 		fmul ds:dword ptr[ebx]
495 		fld ds:dword ptr[0+4+edx]
496 		fxch st(2)
497 		fmul ds:dword ptr[ecx]
498 		fxch st(2)
499 		fld st(0)
500 		fmul ds:dword ptr[4+ecx]
501 		fld ds:dword ptr[0+8+edx]
502 		fxch st(2)
503 		fmul ds:dword ptr[4+ebx]
504 		fxch st(2)
505 		fld st(0)
506 		fmul ds:dword ptr[8+ebx]
507 		fxch st(5)
508 		faddp st(3),st(0)
509 		fmul ds:dword ptr[8+ecx]
510 		fxch st(1)
511 		faddp st(3),st(0)
512 		fxch st(3)
513 		faddp st(2),st(0)
514 		jmp LSetSides
515 Lcase3:
516 		fmul ds:dword ptr[ecx]
517 		fld ds:dword ptr[0+4+edx]
518 		fxch st(2)
519 		fmul ds:dword ptr[ebx]
520 		fxch st(2)
521 		fld st(0)
522 		fmul ds:dword ptr[4+ecx]
523 		fld ds:dword ptr[0+8+edx]
524 		fxch st(2)
525 		fmul ds:dword ptr[4+ebx]
526 		fxch st(2)
527 		fld st(0)
528 		fmul ds:dword ptr[8+ebx]
529 		fxch st(5)
530 		faddp st(3),st(0)
531 		fmul ds:dword ptr[8+ecx]
532 		fxch st(1)
533 		faddp st(3),st(0)
534 		fxch st(3)
535 		faddp st(2),st(0)
536 		jmp LSetSides
537 Lcase4:
538 		fmul ds:dword ptr[ebx]
539 		fld ds:dword ptr[0+4+edx]
540 		fxch st(2)
541 		fmul ds:dword ptr[ecx]
542 		fxch st(2)
543 		fld st(0)
544 		fmul ds:dword ptr[4+ebx]
545 		fld ds:dword ptr[0+8+edx]
546 		fxch st(2)
547 		fmul ds:dword ptr[4+ecx]
548 		fxch st(2)
549 		fld st(0)
550 		fmul ds:dword ptr[8+ecx]
551 		fxch st(5)
552 		faddp st(3),st(0)
553 		fmul ds:dword ptr[8+ebx]
554 		fxch st(1)
555 		faddp st(3),st(0)
556 		fxch st(3)
557 		faddp st(2),st(0)
558 		jmp LSetSides
559 Lcase5:
560 		fmul ds:dword ptr[ecx]
561 		fld ds:dword ptr[0+4+edx]
562 		fxch st(2)
563 		fmul ds:dword ptr[ebx]
564 		fxch st(2)
565 		fld st(0)
566 		fmul ds:dword ptr[4+ebx]
567 		fld ds:dword ptr[0+8+edx]
568 		fxch st(2)
569 		fmul ds:dword ptr[4+ecx]
570 		fxch st(2)
571 		fld st(0)
572 		fmul ds:dword ptr[8+ecx]
573 		fxch st(5)
574 		faddp st(3),st(0)
575 		fmul ds:dword ptr[8+ebx]
576 		fxch st(1)
577 		faddp st(3),st(0)
578 		fxch st(3)
579 		faddp st(2),st(0)
580 		jmp LSetSides
581 Lcase6:
582 		fmul ds:dword ptr[ebx]
583 		fld ds:dword ptr[0+4+edx]
584 		fxch st(2)
585 		fmul ds:dword ptr[ecx]
586 		fxch st(2)
587 		fld st(0)
588 		fmul ds:dword ptr[4+ecx]
589 		fld ds:dword ptr[0+8+edx]
590 		fxch st(2)
591 		fmul ds:dword ptr[4+ebx]
592 		fxch st(2)
593 		fld st(0)
594 		fmul ds:dword ptr[8+ecx]
595 		fxch st(5)
596 		faddp st(3),st(0)
597 		fmul ds:dword ptr[8+ebx]
598 		fxch st(1)
599 		faddp st(3),st(0)
600 		fxch st(3)
601 		faddp st(2),st(0)
602 		jmp LSetSides
603 Lcase7:
604 		fmul ds:dword ptr[ecx]
605 		fld ds:dword ptr[0+4+edx]
606 		fxch st(2)
607 		fmul ds:dword ptr[ebx]
608 		fxch st(2)
609 		fld st(0)
610 		fmul ds:dword ptr[4+ecx]
611 		fld ds:dword ptr[0+8+edx]
612 		fxch st(2)
613 		fmul ds:dword ptr[4+ebx]
614 		fxch st(2)
615 		fld st(0)
616 		fmul ds:dword ptr[8+ecx]
617 		fxch st(5)
618 		faddp st(3),st(0)
619 		fmul ds:dword ptr[8+ebx]
620 		fxch st(1)
621 		faddp st(3),st(0)
622 		fxch st(3)
623 		faddp st(2),st(0)
624 LSetSides:
625 		faddp st(2),st(0)
626 		fcomp ds:dword ptr[12+edx]
627 		xor ecx,ecx
628 		fnstsw ax
629 		fcomp ds:dword ptr[12+edx]
630 		and ah,1
631 		xor ah,1
632 		add cl,ah
633 		fnstsw ax
634 		and ah,1
635 		add ah,ah
636 		add cl,ah
637 		pop ebx
638 		mov eax,ecx
639 		ret
640 Lerror:
641 		int 3
642 	}
643 }
644 #pragma warning( default: 4035 )
645 #endif
646 
ClearBounds(vec3_t mins,vec3_t maxs)647 void ClearBounds (vec3_t mins, vec3_t maxs)
648 {
649 	mins[0] = mins[1] = mins[2] = 99999;
650 	maxs[0] = maxs[1] = maxs[2] = -99999;
651 }
652 
AddPointToBounds(vec3_t v,vec3_t mins,vec3_t maxs)653 void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
654 {
655 	int 	i;
656 	vec_t	val;
657 
658 	for (i=0 ; i<3 ; i++)
659 	{
660 		val = v[i];
661 		if (val < mins[i])
662 			mins[i] = val;
663 		if (val > maxs[i])
664 			maxs[i] = val;
665 	}
666 }
667 
668 /*
669 int VectorCompare (vec3_t v1, vec3_t v2)
670 {
671 	if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2])
672 			return 0;
673 
674 	return 1;
675 }
676 */
677 
VectorNormalize(vec3_t v)678 vec_t VectorNormalize (vec3_t v)
679 {
680 	float	length, ilength;
681 
682 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
683 	length = sqrt (length); 	// FIXME
684 
685 	if (length)
686 	{
687 		ilength = 1/length;
688 		v[0] *= ilength;
689 		v[1] *= ilength;
690 		v[2] *= ilength;
691 	}
692 
693 	return length;
694 
695 }
696 
VectorNormalize2(vec3_t v,vec3_t out)697 vec_t VectorNormalize2 (vec3_t v, vec3_t out)
698 {
699 	float	length, ilength;
700 
701 	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
702 	length = sqrt (length); 	// FIXME
703 
704 	if (length)
705 	{
706 		ilength = 1/length;
707 		out[0] = v[0]*ilength;
708 		out[1] = v[1]*ilength;
709 		out[2] = v[2]*ilength;
710 	}
711 
712 	return length;
713 
714 }
715 
VectorMA(vec3_t veca,float scale,vec3_t vecb,vec3_t vecc)716 void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc)
717 {
718 	vecc[0] = veca[0] + scale*vecb[0];
719 	vecc[1] = veca[1] + scale*vecb[1];
720 	vecc[2] = veca[2] + scale*vecb[2];
721 }
722 
723 
_DotProduct(vec3_t v1,vec3_t v2)724 vec_t _DotProduct (vec3_t v1, vec3_t v2)
725 {
726 	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
727 }
728 
_VectorSubtract(vec3_t veca,vec3_t vecb,vec3_t out)729 void _VectorSubtract (vec3_t veca, vec3_t vecb, vec3_t out)
730 {
731 	out[0] = veca[0]-vecb[0];
732 	out[1] = veca[1]-vecb[1];
733 	out[2] = veca[2]-vecb[2];
734 }
735 
_VectorAdd(vec3_t veca,vec3_t vecb,vec3_t out)736 void _VectorAdd (vec3_t veca, vec3_t vecb, vec3_t out)
737 {
738 	out[0] = veca[0]+vecb[0];
739 	out[1] = veca[1]+vecb[1];
740 	out[2] = veca[2]+vecb[2];
741 }
742 
_VectorCopy(vec3_t in,vec3_t out)743 void _VectorCopy (vec3_t in, vec3_t out)
744 {
745 	out[0] = in[0];
746 	out[1] = in[1];
747 	out[2] = in[2];
748 }
749 
CrossProduct(vec3_t v1,vec3_t v2,vec3_t cross)750 void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
751 {
752 	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
753 	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
754 	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
755 }
756 
757 double sqrt(double x);
758 
VectorLength(vec3_t v)759 vec_t VectorLength(vec3_t v)
760 {
761 	int 	i;
762 	float	length;
763 
764 	length = 0;
765 	for (i=0 ; i< 3 ; i++)
766 		length += v[i]*v[i];
767 	length = sqrt (length); 	// FIXME
768 
769 	return length;
770 }
771 
VectorInverse(vec3_t v)772 void VectorInverse (vec3_t v)
773 {
774 	v[0] = -v[0];
775 	v[1] = -v[1];
776 	v[2] = -v[2];
777 }
778 
VectorScale(vec3_t in,vec_t scale,vec3_t out)779 void VectorScale (vec3_t in, vec_t scale, vec3_t out)
780 {
781 	out[0] = in[0]*scale;
782 	out[1] = in[1]*scale;
783 	out[2] = in[2]*scale;
784 }
785 
786 
Q_log2(int val)787 int Q_log2(int val)
788 {
789 	int answer=0;
790 	while (val>>=1)
791 		answer++;
792 	return answer;
793 }
794 
795 
796 
797 //====================================================================================
798 
799 /*
800 ============
801 COM_SkipPath
802 ============
803 */
COM_SkipPath(char * pathname)804 char *COM_SkipPath (char *pathname)
805 {
806 	char  *last;
807 
808 	last = pathname;
809 	while (*pathname)
810 	{
811 		if (*pathname=='/')
812 			last = pathname+1;
813 		pathname++;
814 	}
815 	return last;
816 }
817 
818 /*
819 ============
820 COM_StripExtension
821 ============
822 */
COM_StripExtension(const char * in,char * out)823 void COM_StripExtension (const char *in, char *out)
824 {
825 	while (*in && *in != '.')
826 		*out++ = *in++;
827 	*out = 0;
828 }
829 
830 /*
831 ============
832 COM_FileExtension
833 ============
834 */
COM_FileExtension(const char * in)835 char *COM_FileExtension (const char *in)
836 {
837 	static char exten[8];
838 	int 	i;
839 
840 	while (*in && *in != '.')
841 		in++;
842 	if (!*in)
843 		return "";
844 	in++;
845 	for (i=0 ; i<7 && *in ; i++,in++)
846 		exten[i] = *in;
847 	exten[i] = 0;
848 	return exten;
849 }
850 
851 /*
852 ============
853 COM_FileBase
854 ============
855 */
COM_FileBase(const char * in,char * out)856 void COM_FileBase (const char *in, char *out)
857 {
858 	const char *s, *s2;
859 
860 	s = in + strlen(in) - 1;
861 
862 	while (s != in && *s != '.')
863 		s--;
864 
865 	for (s2 = s ; s2 != in && *s2 != '/' ; s2--)
866 	;
867 
868 	if (s-s2 < 2)
869 		out[0] = 0;
870 	else
871 	{
872 		s--;
873 		strncpy (out,s2+1, s-s2);
874 		out[s-s2] = 0;
875 	}
876 }
877 
878 /*
879 ============
880 COM_FilePath
881 
882 Returns the path up to, but not including the last /
883 ============
884 */
COM_FilePath(const char * in,char * out)885 void COM_FilePath (const char *in, char *out)
886 {
887 	const char *s;
888 
889 	s = in + strlen(in) - 1;
890 
891 	while (s != in && *s != '/')
892 		s--;
893 
894 	strncpy (out,in, s-in);
895 	out[s-in] = 0;
896 }
897 
898 
899 /*
900 ==================
901 COM_DefaultExtension
902 ==================
903 */
COM_DefaultExtension(char * path,const char * extension)904 void COM_DefaultExtension (char *path, const char *extension)
905 {
906 	char	*src;
907 //
908 // if path doesn't have a .EXT, append extension
909 // (extension should include the .)
910 //
911 	src = path + strlen(path) - 1;
912 
913 	while (*src != '/' && src != path)
914 	{
915 		if (*src == '.')
916 			return; 				// it has an extension
917 		src--;
918 	}
919 
920 	strcat(path, extension);
921 }
922 
923 /*
924 ============
925 va
926 
927 does a varargs printf into a temp buffer, so I don't need to have
928 varargs versions of all text functions.
929 FIXME: make this buffer size safe someday
930 ============
931 */
va(const char * format,...)932 char	*va(const char *format, ...)
933 {
934 	va_list 	argptr;
935 	static char string[1024];
936 
937 	va_start(argptr, format);
938 	vsprintf(string, format, argptr);
939 	va_end(argptr);
940 
941 	return string;
942 }
943 
944 
945 char	com_token[MAX_TOKEN_CHARS];
946 
947 /*
948 ==============
949 COM_Parse
950 
951 Parse a token out of a string
952 ==============
953 */
COM_Parse(char ** data_p)954 char *COM_Parse (char **data_p)
955 {
956 	int 	c;
957 	int 	len;
958 	char	*data;
959 
960 	data = *data_p;
961 	len = 0;
962 	com_token[0] = 0;
963 
964 	if (!data)
965 	{
966 		*data_p = NULL;
967 		return "";
968 	}
969 
970 // skip whitespace
971 skipwhite:
972 	while ( (c = *data) <= ' ')
973 	{
974 		if (c == 0)
975 		{
976 			*data_p = NULL;
977 			return "";
978 		}
979 		data++;
980 	}
981 
982 // skip // comments
983 	if (c=='/' && data[1] == '/')
984 	{
985 		while (*data && *data != '\n')
986 			data++;
987 		goto skipwhite;
988 	}
989 
990 // handle quoted strings specially
991 	if (c == '\"')
992 	{
993 		data++;
994 		while (1)
995 		{
996 			c = *data++;
997 			if (c=='\"' || !c)
998 			{
999 				com_token[len] = 0;
1000 				*data_p = data;
1001 				return com_token;
1002 			}
1003 			if (len < MAX_TOKEN_CHARS)
1004 			{
1005 				com_token[len] = c;
1006 				len++;
1007 			}
1008 		}
1009 	}
1010 
1011 // parse a regular word
1012 	do
1013 	{
1014 		if (len < MAX_TOKEN_CHARS)
1015 		{
1016 			com_token[len] = c;
1017 			len++;
1018 		}
1019 		data++;
1020 		c = *data;
1021 	} while (c>32);
1022 
1023 	if (len == MAX_TOKEN_CHARS)
1024 	{
1025 		Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
1026 		len = 0;
1027 	}
1028 	com_token[len] = 0;
1029 
1030 	*data_p = data;
1031 	return com_token;
1032 }
1033 
1034 
1035 /*
1036 ===============
1037 Com_PageInMemory
1038 
1039 ===============
1040 */
1041 int paged_total;
1042 
Com_PageInMemory(byte * buffer,int size)1043 void Com_PageInMemory (byte *buffer, int size)
1044 {
1045 	int 	i;
1046 
1047 	for (i=size-1 ; i>0 ; i-=4096)
1048 		paged_total += buffer[i];
1049 }
1050 
1051 
1052 
1053 /*
1054 ============================================================================
1055 
1056 					LIBRARY REPLACEMENT FUNCTIONS
1057 
1058 ============================================================================
1059 */
1060 
1061 // FIXME: replace all Q_stricmp with Q_strcasecmp
Q_stricmp(const char * s1,const char * s2)1062 int Q_stricmp (const char *s1, const char *s2)
1063 {
1064 #if defined(WIN32)
1065 	return _stricmp (s1, s2);
1066 #else
1067 	return strcasecmp (s1, s2);
1068 #endif
1069 }
1070 
1071 
Q_strncasecmp(const char * s1,const char * s2,int n)1072 int Q_strncasecmp (const char *s1, const char *s2, int n)
1073 {
1074 	int 	c1, c2;
1075 
1076 	do
1077 	{
1078 		c1 = *s1++;
1079 		c2 = *s2++;
1080 
1081 		if (!n--)
1082 			return 0;		// strings are equal until end point
1083 
1084 		if (c1 != c2)
1085 		{
1086 			if (c1 >= 'a' && c1 <= 'z')
1087 				c1 -= ('a' - 'A');
1088 			if (c2 >= 'a' && c2 <= 'z')
1089 				c2 -= ('a' - 'A');
1090 			if (c1 != c2)
1091 				return -1;		// strings not equal
1092 		}
1093 	} while (c1);
1094 
1095 	return 0;		// strings are equal
1096 }
1097 
Q_strcasecmp(const char * s1,const char * s2)1098 int Q_strcasecmp (const char *s1, const char *s2)
1099 {
1100 	return Q_strncasecmp (s1, s2, 99999);
1101 }
1102 
1103 
1104 
Com_sprintf(char * dest,int size,const char * fmt,...)1105 void Com_sprintf (char *dest, int size, const char *fmt, ...)
1106 {
1107 	int 	len;
1108 	va_list 	argptr;
1109 	char	bigbuffer[0x10000];
1110 
1111 	va_start (argptr,fmt);
1112 	len = vsprintf (bigbuffer,fmt,argptr);
1113 	va_end (argptr);
1114 	if (len >= size)
1115 		Com_Printf("Com_sprintf: overflow of %i in %i\n", len, size);
1116 	strncpy (dest, bigbuffer, size-1);
1117 }
1118 
1119 /*
1120 =====================================================================
1121 
1122   INFO STRINGS
1123 
1124 =====================================================================
1125 */
1126 
1127 /*
1128 ===============
1129 Info_ValueForKey
1130 
1131 Searches the string for the given
1132 key and returns the associated value, or an empty string.
1133 ===============
1134 */
Info_ValueForKey(const char * s,const char * key)1135 char *Info_ValueForKey (const char *s, const char *key)
1136 {
1137 	char	pkey[512];
1138 	static	char value[2][512]; // use two buffers so compares
1139 								// work without stomping on each other
1140 	static	int valueindex;
1141 	char	*o;
1142 
1143 	valueindex ^= 1;
1144 	if (*s == '\\')
1145 		s++;
1146 	while (1)
1147 	{
1148 		o = pkey;
1149 		while (*s != '\\')
1150 		{
1151 			if (!*s)
1152 				return "";
1153 			*o++ = *s++;
1154 		}
1155 		*o = 0;
1156 		s++;
1157 
1158 		o = value[valueindex];
1159 
1160 		while (*s != '\\' && *s)
1161 		{
1162 			if (!*s)
1163 				return "";
1164 			*o++ = *s++;
1165 		}
1166 		*o = 0;
1167 
1168 		if (!strcmp (key, pkey) )
1169 			return value[valueindex];
1170 
1171 		if (!*s)
1172 			return "";
1173 		s++;
1174 	}
1175 }
1176 
Info_RemoveKey(char * s,const char * key)1177 void Info_RemoveKey (char *s, const char *key)
1178 {
1179 	char	*start;
1180 	char	pkey[512];
1181 	char	value[512];
1182 	char	*o;
1183 
1184 	if (strstr (key, "\\"))
1185 	{
1186 		Com_Printf ("Can't use a key with a \\\n");
1187 		return;
1188 	}
1189 
1190 	while (1)
1191 	{
1192 		start = s;
1193 		if (*s == '\\')
1194 			s++;
1195 		o = pkey;
1196 		while (*s != '\\')
1197 		{
1198 			if (!*s)
1199 				return;
1200 			*o++ = *s++;
1201 		}
1202 		*o = 0;
1203 		s++;
1204 
1205 		o = value;
1206 		while (*s != '\\' && *s)
1207 		{
1208 			if (!*s)
1209 				return;
1210 			*o++ = *s++;
1211 		}
1212 		*o = 0;
1213 
1214 		if (!strcmp (key, pkey) )
1215 		{
1216 			strcpy (start, s);	// remove this part
1217 			return;
1218 		}
1219 
1220 		if (!*s)
1221 			return;
1222 	}
1223 
1224 }
1225 
1226 
1227 /*
1228 ==================
1229 Info_Validate
1230 
1231 Some characters are illegal in info strings because they
1232 can mess up the server's parsing
1233 ==================
1234 */
Info_Validate(const char * s)1235 qboolean Info_Validate (const char *s)
1236 {
1237 	if (strstr (s, "\""))
1238 		return false;
1239 	if (strstr (s, ";"))
1240 		return false;
1241 	return true;
1242 }
1243 
Info_SetValueForKey(char * s,const char * key,const char * value)1244 void Info_SetValueForKey (char *s, const char *key, const char *value)
1245 {
1246 	char	newi[MAX_INFO_STRING], *v;
1247 	int 	c;
1248 	int 	maxsize = MAX_INFO_STRING;
1249 
1250 	if (strstr (key, "\\") || strstr (value, "\\") )
1251 	{
1252 		Com_Printf ("Can't use keys or values with a \\\n");
1253 		return;
1254 	}
1255 
1256 	if (strstr (key, ";") )
1257 	{
1258 		Com_Printf ("Can't use keys or values with a semicolon\n");
1259 		return;
1260 	}
1261 
1262 	if (strstr (key, "\"") || strstr (value, "\"") )
1263 	{
1264 		Com_Printf ("Can't use keys or values with a \"\n");
1265 		return;
1266 	}
1267 
1268 	if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1)
1269 	{
1270 		Com_Printf ("Keys and values must be < 64 characters.\n");
1271 		return;
1272 	}
1273 	Info_RemoveKey (s, key);
1274 	if (!value || !strlen(value))
1275 		return;
1276 
1277 	Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
1278 
1279 	if (strlen(newi) + strlen(s) > maxsize)
1280 	{
1281 		Com_Printf ("Info string length exceeded\n");
1282 		return;
1283 	}
1284 
1285 	// only copy ascii values
1286 	s += strlen(s);
1287 	v = newi;
1288 	while (*v)
1289 	{
1290 		c = *v++;
1291 		c &= 127;		// strip high bits
1292 		if (c >= 32 && c < 127)
1293 			*s++ = c;
1294 	}
1295 	*s = 0;
1296 }
1297 
1298 //====================================================================
1299 
1300 // from g_utils.c
G_ProjectSource(vec3_t point,vec3_t distance,vec3_t forward,vec3_t right,vec3_t result)1301 void G_ProjectSource (vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
1302 {
1303 	result[0] = point[0] + forward[0] * distance[0] + right[0] * distance[1];
1304 	result[1] = point[1] + forward[1] * distance[0] + right[1] * distance[1];
1305 	result[2] = point[2] + forward[2] * distance[0] + right[2] * distance[1] + distance[2];
1306 }
1307 
1308 /*
1309 =============
1310 TempVector
1311 
1312 This is just a convenience function
1313 for making temporary vectors for function calls
1314 =============
1315 */
tv(float x,float y,float z)1316 float	*tv (float x, float y, float z)
1317 {
1318 	static	int 	index;
1319 	static	vec3_t	vecs[8];
1320 	float	*v;
1321 
1322 	// use an array so that multiple tempvectors won't collide
1323 	// for a while
1324 	v = vecs[index];
1325 	index = (index + 1)&7;
1326 
1327 	v[0] = x;
1328 	v[1] = y;
1329 	v[2] = z;
1330 
1331 	return v;
1332 }
1333 
1334 /*
1335 =============
1336 VectorToString
1337 
1338 This is just a convenience function
1339 for printing vectors
1340 =============
1341 */
vtos(vec3_t v)1342 char	*vtos (vec3_t v)
1343 {
1344 	static	int 	index;
1345 	static	char	str[8][32];
1346 	char	*s;
1347 
1348 	// use an array so that multiple vtos won't collide
1349 	s = str[index];
1350 	index = (index + 1)&7;
1351 
1352 	Com_sprintf (s, 32, "(%i %i %i)", (int)v[0], (int)v[1], (int)v[2]);
1353 
1354 	return s;
1355 }
1356 
vectoyaw(vec3_t vec)1357 float vectoyaw (vec3_t vec)
1358 {
1359 	float	yaw;
1360 
1361 	if (/*vec[YAW] == 0 &&*/ vec[PITCH] == 0)
1362 	{
1363 		yaw = 0;
1364 		if (vec[YAW] > 0)
1365 			yaw = 90;
1366 		else if (vec[YAW] < 0)
1367 			yaw = -90;
1368 	}
1369 	else
1370 	{
1371 		yaw = (int) (atan2(vec[YAW], vec[PITCH]) * 180 / M_PI);
1372 		if (yaw < 0)
1373 			yaw += 360;
1374 	}
1375 
1376 	return yaw;
1377 }
1378 
vectoangles(vec3_t value1,vec3_t angles)1379 void vectoangles (vec3_t value1, vec3_t angles)
1380 {
1381 	float	forward;
1382 	float	yaw, pitch;
1383 
1384 	if (value1[1] == 0 && value1[0] == 0)
1385 	{
1386 		yaw = 0;
1387 		if (value1[2] > 0)
1388 			pitch = 90;
1389 		else
1390 			pitch = 270;
1391 	}
1392 	else
1393 	{
1394 		if (value1[0])
1395 			yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI);
1396 		else if (value1[1] > 0)
1397 			yaw = 90;
1398 		else
1399 			yaw = -90;
1400 		if (yaw < 0)
1401 			yaw += 360;
1402 
1403 		forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
1404 		pitch = (int) (atan2(value1[2], forward) * 180 / M_PI);
1405 		if (pitch < 0)
1406 			pitch += 360;
1407 	}
1408 
1409 	angles[PITCH] = -pitch;
1410 	angles[YAW] = yaw;
1411 	angles[ROLL] = 0;
1412 }
1413