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__
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 // handle quoted strings specially
1090 if (c == '\"')
1091 {
1092 data++;
1093 while (1)
1094 {
1095 c = *data++;
1096 if (c=='\"' || !c)
1097 {
1098 com_token[len] = 0;
1099 *data_p = data;
1100 return com_token;
1101 }
1102 if (len < MAX_TOKEN_CHARS)
1103 {
1104 com_token[len] = c;
1105 len++;
1106 }
1107 }
1108 }
1109
1110 // parse a regular word
1111 do
1112 {
1113 if (len < MAX_TOKEN_CHARS)
1114 {
1115 com_token[len] = c;
1116 len++;
1117 }
1118 data++;
1119 c = *data;
1120 } while (c>32);
1121
1122 if (len == MAX_TOKEN_CHARS)
1123 {
1124 // Com_Printf ("Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS);
1125 len = 0;
1126 }
1127 com_token[len] = 0;
1128
1129 *data_p = data;
1130 return com_token;
1131 }
1132
1133
1134 /*
1135 ===============
1136 Com_PageInMemory
1137
1138 ===============
1139 */
1140 int paged_total;
1141
Com_PageInMemory(byte * buffer,int size)1142 void Com_PageInMemory (byte *buffer, int size)
1143 {
1144 int i;
1145
1146 for (i=size-1 ; i>0 ; i-=4096)
1147 paged_total += buffer[i];
1148 }
1149
1150
1151
1152 /*
1153 ============================================================================
1154
1155 LIBRARY REPLACEMENT FUNCTIONS
1156
1157 ============================================================================
1158 */
1159
1160 // FIXME: replace all Q_stricmp with Q_strcasecmp
Q_stricmp(char * s1,char * s2)1161 int Q_stricmp (char *s1, char *s2)
1162 {
1163 #if defined(WIN32)
1164 return _stricmp (s1, s2);
1165 #else
1166 return strcasecmp (s1, s2);
1167 #endif
1168 }
1169
1170
Q_strncasecmp(char * s1,char * s2,int n)1171 int Q_strncasecmp (char *s1, char *s2, int n)
1172 {
1173 int c1, c2;
1174
1175 do
1176 {
1177 c1 = *s1++;
1178 c2 = *s2++;
1179
1180 if (!n--)
1181 return 0; // strings are equal until end point
1182
1183 if (c1 != c2)
1184 {
1185 if (c1 >= 'a' && c1 <= 'z')
1186 c1 -= ('a' - 'A');
1187 if (c2 >= 'a' && c2 <= 'z')
1188 c2 -= ('a' - 'A');
1189 if (c1 != c2)
1190 return -1; // strings not equal
1191 }
1192 } while (c1);
1193
1194 return 0; // strings are equal
1195 }
1196
Q_strcasecmp(char * s1,char * s2)1197 int Q_strcasecmp (char *s1, char *s2)
1198 {
1199 return Q_strncasecmp (s1, s2, 99999);
1200 }
1201
1202
1203
Com_sprintf(char * dest,int size,char * fmt,...)1204 void Com_sprintf (char *dest, int size, char *fmt, ...)
1205 {
1206 int len;
1207 va_list argptr;
1208 char bigbuffer[0x10000];
1209
1210 va_start (argptr,fmt);
1211 len = vsprintf (bigbuffer,fmt,argptr);
1212 va_end (argptr);
1213 if (len >= size)
1214 Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size);
1215 strncpy (dest, bigbuffer, size-1);
1216 }
1217
1218 /*
1219 =====================================================================
1220
1221 INFO STRINGS
1222
1223 =====================================================================
1224 */
1225
1226 /*
1227 ===============
1228 Info_ValueForKey
1229
1230 Searches the string for the given
1231 key and returns the associated value, or an empty string.
1232 ===============
1233 */
Info_ValueForKey(char * s,char * key)1234 char *Info_ValueForKey (char *s, char *key)
1235 {
1236 char pkey[512];
1237 static char value[2][512]; // use two buffers so compares
1238 // work without stomping on each other
1239 static int valueindex;
1240 char *o;
1241
1242 valueindex ^= 1;
1243 if (*s == '\\')
1244 s++;
1245 while (1)
1246 {
1247 o = pkey;
1248 while (*s != '\\')
1249 {
1250 if (!*s)
1251 return "";
1252 *o++ = *s++;
1253 }
1254 *o = 0;
1255 s++;
1256
1257 o = value[valueindex];
1258
1259 while (*s != '\\' && *s)
1260 {
1261 if (!*s)
1262 return "";
1263 *o++ = *s++;
1264 }
1265 *o = 0;
1266
1267 if (!strcmp (key, pkey) )
1268 return value[valueindex];
1269
1270 if (!*s)
1271 return "";
1272 s++;
1273 }
1274 }
1275
Info_RemoveKey(char * s,char * key)1276 void Info_RemoveKey (char *s, char *key)
1277 {
1278 char *start;
1279 char pkey[512];
1280 char value[512];
1281 char *o;
1282
1283 if (strstr (key, "\\"))
1284 {
1285 // Com_Printf ("Can't use a key with a \\\n");
1286 return;
1287 }
1288
1289 while (1)
1290 {
1291 start = s;
1292 if (*s == '\\')
1293 s++;
1294 o = pkey;
1295 while (*s != '\\')
1296 {
1297 if (!*s)
1298 return;
1299 *o++ = *s++;
1300 }
1301 *o = 0;
1302 s++;
1303
1304 o = value;
1305 while (*s != '\\' && *s)
1306 {
1307 if (!*s)
1308 return;
1309 *o++ = *s++;
1310 }
1311 *o = 0;
1312
1313 if (!strcmp (key, pkey) )
1314 {
1315 strcpy (start, s); // remove this part
1316 return;
1317 }
1318
1319 if (!*s)
1320 return;
1321 }
1322
1323 }
1324
1325
1326 /*
1327 ==================
1328 Info_Validate
1329
1330 Some characters are illegal in info strings because they
1331 can mess up the server's parsing
1332 ==================
1333 */
Info_Validate(char * s)1334 qboolean Info_Validate (char *s)
1335 {
1336 if (strstr (s, "\""))
1337 return false;
1338 if (strstr (s, ";"))
1339 return false;
1340 return true;
1341 }
1342
Info_SetValueForKey(char * s,char * key,char * value)1343 void Info_SetValueForKey (char *s, char *key, char *value)
1344 {
1345 char newi[MAX_INFO_STRING], *v;
1346 int c;
1347 int maxsize = MAX_INFO_STRING;
1348
1349 if (strstr (key, "\\") || strstr (value, "\\") )
1350 {
1351 Com_Printf ("Can't use keys or values with a \\\n");
1352 return;
1353 }
1354
1355 if (strstr (key, ";") )
1356 {
1357 Com_Printf ("Can't use keys or values with a semicolon\n");
1358 return;
1359 }
1360
1361 if (strstr (key, "\"") || strstr (value, "\"") )
1362 {
1363 Com_Printf ("Can't use keys or values with a \"\n");
1364 return;
1365 }
1366
1367 if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1)
1368 {
1369 Com_Printf ("Keys and values must be < 64 characters.\n");
1370 return;
1371 }
1372 Info_RemoveKey (s, key);
1373 if (!value || !strlen(value))
1374 return;
1375
1376 Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value);
1377
1378 if (strlen(newi) + strlen(s) > maxsize)
1379 {
1380 Com_Printf ("Info string length exceeded\n");
1381 return;
1382 }
1383
1384 // only copy ascii values
1385 s += strlen(s);
1386 v = newi;
1387 while (*v)
1388 {
1389 c = *v++;
1390 c &= 127; // strip high bits
1391 if (c >= 32 && c < 127)
1392 *s++ = c;
1393 }
1394 *s = 0;
1395 }
1396
1397 //====================================================================
1398
1399
1400