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