|
|
1.1.1.2 ! root 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: */ 1.1 root 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: 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: 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: 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: */ 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: */ 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: */ 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: 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) 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: */ 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: 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 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__ 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 775: void VectorInverse (vec3_t v) 776: { 777: v[0] = -v[0]; 778: v[1] = -v[1]; 779: v[2] = -v[2]; 780: } 781: 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: 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: */ 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: */ 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: */ 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: */ 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: */ 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: */ 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: 945: short BigShort(short l){return _BigShort(l);} 946: short LittleShort(short l) {return _LittleShort(l);} 947: int BigLong (int l) {return _BigLong(l);} 948: int LittleLong (int l) {return _LittleLong(l);} 949: float BigFloat (float l) {return _BigFloat(l);} 950: float LittleFloat (float l) {return _LittleFloat(l);} 951: 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: 962: short ShortNoSwap (short l) 963: { 964: return l; 965: } 966: 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: 979: int LongNoSwap (int l) 980: { 981: return l; 982: } 983: 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: 1001: float FloatNoSwap (float f) 1002: { 1003: return f; 1004: } 1005: 1006: /* 1007: ================ 1008: Swap_Init 1009: ================ 1010: */ 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: */ 1050: char *va(char *format, ...) 1051: { 1052: va_list argptr; 1053: static char string[1024]; 1054: 1055: va_start (argptr, format); 1056: vsprintf (string, 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: */ 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: 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: // FIXME: replace all Q_stricmp with Q_strcasecmp 1180: int Q_stricmp (char *s1, char *s2) 1181: { 1182: #if defined(WIN32) 1183: return _stricmp (s1, s2); 1184: #else 1185: return strcasecmp (s1, s2); 1186: #endif 1187: } 1188: 1189: 1190: int Q_strncasecmp (char *s1, char *s2, int n) 1191: { 1192: int c1, c2; 1193: 1194: do 1195: { 1196: c1 = *s1++; 1197: c2 = *s2++; 1198: 1199: if (!n--) 1200: return 0; // strings are equal until end point 1201: 1202: if (c1 != c2) 1203: { 1204: if (c1 >= 'a' && c1 <= 'z') 1205: c1 -= ('a' - 'A'); 1206: if (c2 >= 'a' && c2 <= 'z') 1207: c2 -= ('a' - 'A'); 1208: if (c1 != c2) 1209: return -1; // strings not equal 1210: } 1211: } while (c1); 1212: 1213: return 0; // strings are equal 1214: } 1215: 1216: int Q_strcasecmp (char *s1, char *s2) 1217: { 1218: return Q_strncasecmp (s1, s2, 99999); 1219: } 1220: 1221: 1222: 1223: void Com_sprintf (char *dest, int size, char *fmt, ...) 1224: { 1225: int len; 1226: va_list argptr; 1227: char bigbuffer[0x10000]; 1228: 1229: va_start (argptr,fmt); 1230: len = vsprintf (bigbuffer,fmt,argptr); 1231: va_end (argptr); 1232: if (len >= size) 1233: Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size); 1234: strncpy (dest, bigbuffer, size-1); 1235: } 1236: 1237: /* 1238: ===================================================================== 1239: 1240: INFO STRINGS 1241: 1242: ===================================================================== 1243: */ 1244: 1245: /* 1246: =============== 1247: Info_ValueForKey 1248: 1249: Searches the string for the given 1250: key and returns the associated value, or an empty string. 1251: =============== 1252: */ 1253: char *Info_ValueForKey (char *s, char *key) 1254: { 1255: char pkey[512]; 1256: static char value[2][512]; // use two buffers so compares 1257: // work without stomping on each other 1258: static int valueindex; 1259: char *o; 1260: 1261: valueindex ^= 1; 1262: if (*s == '\\') 1263: s++; 1264: while (1) 1265: { 1266: o = pkey; 1267: while (*s != '\\') 1268: { 1269: if (!*s) 1270: return ""; 1271: *o++ = *s++; 1272: } 1273: *o = 0; 1274: s++; 1275: 1276: o = value[valueindex]; 1277: 1278: while (*s != '\\' && *s) 1279: { 1280: if (!*s) 1281: return ""; 1282: *o++ = *s++; 1283: } 1284: *o = 0; 1285: 1286: if (!strcmp (key, pkey) ) 1287: return value[valueindex]; 1288: 1289: if (!*s) 1290: return ""; 1291: s++; 1292: } 1293: } 1294: 1295: void Info_RemoveKey (char *s, char *key) 1296: { 1297: char *start; 1298: char pkey[512]; 1299: char value[512]; 1300: char *o; 1301: 1302: if (strstr (key, "\\")) 1303: { 1304: // Com_Printf ("Can't use a key with a \\\n"); 1305: return; 1306: } 1307: 1308: while (1) 1309: { 1310: start = s; 1311: if (*s == '\\') 1312: s++; 1313: o = pkey; 1314: while (*s != '\\') 1315: { 1316: if (!*s) 1317: return; 1318: *o++ = *s++; 1319: } 1320: *o = 0; 1321: s++; 1322: 1323: o = value; 1324: while (*s != '\\' && *s) 1325: { 1326: if (!*s) 1327: return; 1328: *o++ = *s++; 1329: } 1330: *o = 0; 1331: 1332: if (!strcmp (key, pkey) ) 1333: { 1334: strcpy (start, s); // remove this part 1335: return; 1336: } 1337: 1338: if (!*s) 1339: return; 1340: } 1341: 1342: } 1343: 1344: 1345: /* 1346: ================== 1347: Info_Validate 1348: 1349: Some characters are illegal in info strings because they 1350: can mess up the server's parsing 1351: ================== 1352: */ 1353: qboolean Info_Validate (char *s) 1354: { 1355: if (strstr (s, "\"")) 1356: return false; 1357: if (strstr (s, ";")) 1358: return false; 1359: return true; 1360: } 1361: 1362: void Info_SetValueForKey (char *s, char *key, char *value) 1363: { 1364: char newi[MAX_INFO_STRING], *v; 1365: int c; 1366: int maxsize = MAX_INFO_STRING; 1367: 1368: if (strstr (key, "\\") || strstr (value, "\\") ) 1369: { 1370: Com_Printf ("Can't use keys or values with a \\\n"); 1371: return; 1372: } 1373: 1374: if (strstr (key, ";") ) 1375: { 1376: Com_Printf ("Can't use keys or values with a semicolon\n"); 1377: return; 1378: } 1379: 1380: if (strstr (key, "\"") || strstr (value, "\"") ) 1381: { 1382: Com_Printf ("Can't use keys or values with a \"\n"); 1383: return; 1384: } 1385: 1386: if (strlen(key) > MAX_INFO_KEY-1 || strlen(value) > MAX_INFO_KEY-1) 1387: { 1388: Com_Printf ("Keys and values must be < 64 characters.\n"); 1389: return; 1390: } 1391: Info_RemoveKey (s, key); 1392: if (!value || !strlen(value)) 1393: return; 1394: 1395: Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value); 1396: 1397: if (strlen(newi) + strlen(s) > maxsize) 1398: { 1399: Com_Printf ("Info string length exceeded\n"); 1400: return; 1401: } 1402: 1403: // only copy ascii values 1404: s += strlen(s); 1405: v = newi; 1406: while (*v) 1407: { 1408: c = *v++; 1409: c &= 127; // strip high bits 1410: if (c >= 32 && c < 127) 1411: *s++ = c; 1412: } 1413: *s = 0; 1414: } 1415: 1416: //==================================================================== 1417: 1418:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.