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