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