q_shared.c (25613B)
1 /* 2 Copyright (C) 1997-2001 Id Software, Inc. 3 4 This program is free software; you can redistribute it and/or 5 modify it under the terms of the GNU General Public License 6 as published by the Free Software Foundation; either version 2 7 of the License, or (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13 See the GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 */ 20 #include "q_shared.h" 21 22 #define DEG2RAD( a ) ( a * M_PI ) / 180.0F 23 24 vec3_t vec3_origin = {0,0,0}; 25 26 //============================================================================ 27 28 #ifdef _WIN32 29 #pragma optimize( "", off ) 30 #endif 31 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