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