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