|
|
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: // ROGUE VERSIONING
7: int rogueid = ROGUE_VERSION_ID;
8: // ROGUE
9:
10: //============================================================================
11:
12: #ifdef _WIN32
13: #pragma optimize( "", off )
14: #endif
15:
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:
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:
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: */
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: */
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: */
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:
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)
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: */
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:
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
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 __linux__
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
759: void VectorInverse (vec3_t v)
760: {
761: v[0] = -v[0];
762: v[1] = -v[1];
763: v[2] = -v[2];
764: }
765:
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:
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: */
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: */
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: */
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: */
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: */
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: */
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:
929: short BigShort(short l){return _BigShort(l);}
930: short LittleShort(short l) {return _LittleShort(l);}
931: int BigLong (int l) {return _BigLong(l);}
932: int LittleLong (int l) {return _LittleLong(l);}
933: float BigFloat (float l) {return _BigFloat(l);}
934: float LittleFloat (float l) {return _LittleFloat(l);}
935:
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:
946: short ShortNoSwap (short l)
947: {
948: return l;
949: }
950:
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:
963: int LongNoSwap (int l)
964: {
965: return l;
966: }
967:
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:
985: float FloatNoSwap (float f)
986: {
987: return f;
988: }
989:
990: /*
991: ================
992: Swap_Init
993: ================
994: */
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: */
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: */
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:
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
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:
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:
1200: int Q_strcasecmp (char *s1, char *s2)
1201: {
1202: return Q_strncasecmp (s1, s2, 99999);
1203: }
1204:
1205:
1206:
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: */
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:
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: */
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:
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.