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