1 /* 2 Copyright (C) 1996-1997 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 // models.c -- model loading and caching 21 22 // models are the only shared resource between a client and server running 23 // on the same machine. 24 25 #include "qwsvdef.h" 26 27 model_t *loadmodel; 28 char loadname[32]; // for hunk tags 29 30 void Mod_LoadSpriteModel (model_t *mod, void *buffer); 31 void Mod_LoadBrushModel (model_t *mod, void *buffer); 32 void Mod_LoadAliasModel (model_t *mod, void *buffer); 33 model_t *Mod_LoadModel (model_t *mod, qboolean crash); 34 35 byte mod_novis[MAX_MAP_LEAFS/8]; 36 37 #define MAX_MOD_KNOWN 256 38 model_t mod_known[MAX_MOD_KNOWN]; 39 int mod_numknown; 40 41 texture_t r_notexture_mip; 42 43 unsigned *model_checksum; 44 45 /* 46 =============== 47 Mod_Init 48 =============== 49 */ 50 void Mod_Init (void) 51 { 52 memset (mod_novis, 0xff, sizeof(mod_novis)); 53 } 54 55 /* 56 =============== 57 Mod_PointInLeaf 58 =============== 59 */ 60 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) 61 { 62 mnode_t *node; 63 float d; 64 mplane_t *plane; 65 66 if (!model || !model->nodes) 67 SV_Error ("Mod_PointInLeaf: bad model"); 68 69 node = model->nodes; 70 while (1) 71 { 72 if (node->contents < 0) 73 return (mleaf_t *)node; 74 plane = node->plane; 75 d = DotProduct (p,plane->normal) - plane->dist; 76 if (d > 0) 77 node = node->children[0]; 78 else 79 node = node->children[1]; 80 } 81 82 return NULL; // never reached 83 } 84 85 86 /* 87 =================== 88 Mod_DecompressVis 89 =================== 90 */ 91 byte *Mod_DecompressVis (byte *in, model_t *model) 92 { 93 static byte decompressed[MAX_MAP_LEAFS/8]; 94 int c; 95 byte *out; 96 int row; 97 98 row = (model->numleafs+7)>>3; 99 out = decompressed; 100 101 #if 0 102 memcpy (out, in, row); 103 #else 104 if (!in) 105 { // no vis info, so make all visible 106 while (row) 107 { 108 *out++ = 0xff; 109 row--; 110 } 111 return decompressed; 112 } 113 114 do 115 { 116 if (*in) 117 { 118 *out++ = *in++; 119 continue; 120 } 121 122 c = in[1]; 123 in += 2; 124 while (c) 125 { 126 *out++ = 0; 127 c--; 128 } 129 } while (out - decompressed < row); 130 #endif 131 132 return decompressed; 133 } 134 135 byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) 136 { 137 if (leaf == model->leafs) 138 return mod_novis; 139 return Mod_DecompressVis (leaf->compressed_vis, model); 140 } 141 142 /* 143 =================== 144 Mod_ClearAll 145 =================== 146 */ 147 void Mod_ClearAll (void) 148 { 149 int i; 150 model_t *mod; 151 152 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) 153 if (mod->type != mod_alias) 154 mod->needload = true; 155 } 156 157 /* 158 ================== 159 Mod_FindName 160 161 ================== 162 */ 163 model_t *Mod_FindName (char *name) 164 { 165 int i; 166 model_t *mod; 167 168 if (!name[0]) 169 SV_Error ("Mod_ForName: NULL name"); 170 171 // 172 // search the currently loaded models 173 // 174 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) 175 if (!strcmp (mod->name, name) ) 176 break; 177 178 if (i == mod_numknown) 179 { 180 if (mod_numknown == MAX_MOD_KNOWN) 181 SV_Error ("mod_numknown == MAX_MOD_KNOWN"); 182 strcpy (mod->name, name); 183 mod->needload = true; 184 mod_numknown++; 185 } 186 187 return mod; 188 } 189 190 191 /* 192 ================== 193 Mod_LoadModel 194 195 Loads a model into the cache 196 ================== 197 */ 198 model_t *Mod_LoadModel (model_t *mod, qboolean crash) 199 { 200 void *d; 201 unsigned *buf; 202 byte stackbuf[1024]; // avoid dirtying the cache heap 203 204 if (!mod->needload) 205 { 206 if (mod->type == mod_alias) 207 { 208 d = Cache_Check (&mod->cache); 209 if (d) 210 return mod; 211 } 212 else 213 return mod; // not cached at all 214 } 215 216 // 217 // load the file 218 // 219 buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); 220 if (!buf) 221 { 222 if (crash) 223 SV_Error ("Mod_NumForName: %s not found", mod->name); 224 return NULL; 225 } 226 227 // 228 // allocate a new model 229 // 230 COM_FileBase (mod->name, loadname); 231 232 loadmodel = mod; 233 234 // 235 // fill it in 236 // 237 238 // call the apropriate loader 239 mod->needload = false; 240 241 Mod_LoadBrushModel (mod, buf); 242 243 return mod; 244 } 245 246 /* 247 ================== 248 Mod_ForName 249 250 Loads in a model for the given name 251 ================== 252 */ 253 model_t *Mod_ForName (char *name, qboolean crash) 254 { 255 model_t *mod; 256 257 mod = Mod_FindName (name); 258 259 return Mod_LoadModel (mod, crash); 260 } 261 262 263 /* 264 =============================================================================== 265 266 BRUSHMODEL LOADING 267 268 =============================================================================== 269 */ 270 271 byte *mod_base; 272 273 274 /* 275 ================= 276 Mod_LoadTextures 277 ================= 278 */ 279 void Mod_LoadTextures (lump_t *l) 280 { 281 int i, j, pixels, num, max, altmax; 282 miptex_t *mt; 283 texture_t *tx, *tx2; 284 texture_t *anims[10]; 285 texture_t *altanims[10]; 286 dmiptexlump_t *m; 287 288 if (!l->filelen) 289 { 290 loadmodel->textures = NULL; 291 return; 292 } 293 m = (dmiptexlump_t *)(mod_base + l->fileofs); 294 295 m->nummiptex = LittleLong (m->nummiptex); 296 297 loadmodel->numtextures = m->nummiptex; 298 loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); 299 300 for (i=0 ; i<m->nummiptex ; i++) 301 { 302 m->dataofs[i] = LittleLong(m->dataofs[i]); 303 if (m->dataofs[i] == -1) 304 continue; 305 mt = (miptex_t *)((byte *)m + m->dataofs[i]); 306 mt->width = LittleLong (mt->width); 307 mt->height = LittleLong (mt->height); 308 for (j=0 ; j<MIPLEVELS ; j++) 309 mt->offsets[j] = LittleLong (mt->offsets[j]); 310 311 if ( (mt->width & 15) || (mt->height & 15) ) 312 SV_Error ("Texture %s is not 16 aligned", mt->name); 313 pixels = mt->width*mt->height/64*85; 314 tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); 315 loadmodel->textures[i] = tx; 316 317 memcpy (tx->name, mt->name, sizeof(tx->name)); 318 tx->width = mt->width; 319 tx->height = mt->height; 320 for (j=0 ; j<MIPLEVELS ; j++) 321 tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); 322 // the pixels immediately follow the structures 323 memcpy ( tx+1, mt+1, pixels); 324 } 325 326 // 327 // sequence the animations 328 // 329 for (i=0 ; i<m->nummiptex ; i++) 330 { 331 tx = loadmodel->textures[i]; 332 if (!tx || tx->name[0] != '+') 333 continue; 334 if (tx->anim_next) 335 continue; // allready sequenced 336 337 // find the number of frames in the animation 338 memset (anims, 0, sizeof(anims)); 339 memset (altanims, 0, sizeof(altanims)); 340 341 max = tx->name[1]; 342 altmax = 0; 343 if (max >= 'a' && max <= 'z') 344 max -= 'a' - 'A'; 345 if (max >= '0' && max <= '9') 346 { 347 max -= '0'; 348 altmax = 0; 349 anims[max] = tx; 350 max++; 351 } 352 else if (max >= 'A' && max <= 'J') 353 { 354 altmax = max - 'A'; 355 max = 0; 356 altanims[altmax] = tx; 357 altmax++; 358 } 359 else 360 SV_Error ("Bad animating texture %s", tx->name); 361 362 for (j=i+1 ; j<m->nummiptex ; j++) 363 { 364 tx2 = loadmodel->textures[j]; 365 if (!tx2 || tx2->name[0] != '+') 366 continue; 367 if (strcmp (tx2->name+2, tx->name+2)) 368 continue; 369 370 num = tx2->name[1]; 371 if (num >= 'a' && num <= 'z') 372 num -= 'a' - 'A'; 373 if (num >= '0' && num <= '9') 374 { 375 num -= '0'; 376 anims[num] = tx2; 377 if (num+1 > max) 378 max = num + 1; 379 } 380 else if (num >= 'A' && num <= 'J') 381 { 382 num = num - 'A'; 383 altanims[num] = tx2; 384 if (num+1 > altmax) 385 altmax = num+1; 386 } 387 else 388 SV_Error ("Bad animating texture %s", tx->name); 389 } 390 391 #define ANIM_CYCLE 2 392 // link them all together 393 for (j=0 ; j<max ; j++) 394 { 395 tx2 = anims[j]; 396 if (!tx2) 397 SV_Error ("Missing frame %i of %s",j, tx->name); 398 tx2->anim_total = max * ANIM_CYCLE; 399 tx2->anim_min = j * ANIM_CYCLE; 400 tx2->anim_max = (j+1) * ANIM_CYCLE; 401 tx2->anim_next = anims[ (j+1)%max ]; 402 if (altmax) 403 tx2->alternate_anims = altanims[0]; 404 } 405 for (j=0 ; j<altmax ; j++) 406 { 407 tx2 = altanims[j]; 408 if (!tx2) 409 SV_Error ("Missing frame %i of %s",j, tx->name); 410 tx2->anim_total = altmax * ANIM_CYCLE; 411 tx2->anim_min = j * ANIM_CYCLE; 412 tx2->anim_max = (j+1) * ANIM_CYCLE; 413 tx2->anim_next = altanims[ (j+1)%altmax ]; 414 if (max) 415 tx2->alternate_anims = anims[0]; 416 } 417 } 418 } 419 420 /* 421 ================= 422 Mod_LoadLighting 423 ================= 424 */ 425 void Mod_LoadLighting (lump_t *l) 426 { 427 if (!l->filelen) 428 { 429 loadmodel->lightdata = NULL; 430 return; 431 } 432 loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname); 433 memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); 434 } 435 436 437 /* 438 ================= 439 Mod_LoadVisibility 440 ================= 441 */ 442 void Mod_LoadVisibility (lump_t *l) 443 { 444 if (!l->filelen) 445 { 446 loadmodel->visdata = NULL; 447 return; 448 } 449 loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname); 450 memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen); 451 } 452 453 454 /* 455 ================= 456 Mod_LoadEntities 457 ================= 458 */ 459 void Mod_LoadEntities (lump_t *l) 460 { 461 if (!l->filelen) 462 { 463 loadmodel->entities = NULL; 464 return; 465 } 466 loadmodel->entities = Hunk_AllocName ( l->filelen, loadname); 467 memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); 468 } 469 470 471 /* 472 ================= 473 Mod_LoadVertexes 474 ================= 475 */ 476 void Mod_LoadVertexes (lump_t *l) 477 { 478 dvertex_t *in; 479 mvertex_t *out; 480 int i, count; 481 482 in = (void *)(mod_base + l->fileofs); 483 if (l->filelen % sizeof(*in)) 484 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 485 count = l->filelen / sizeof(*in); 486 out = Hunk_AllocName ( count*sizeof(*out), loadname); 487 488 loadmodel->vertexes = out; 489 loadmodel->numvertexes = count; 490 491 for ( i=0 ; i<count ; i++, in++, out++) 492 { 493 out->position[0] = LittleFloat (in->point[0]); 494 out->position[1] = LittleFloat (in->point[1]); 495 out->position[2] = LittleFloat (in->point[2]); 496 } 497 } 498 499 /* 500 ================= 501 Mod_LoadSubmodels 502 ================= 503 */ 504 void Mod_LoadSubmodels (lump_t *l) 505 { 506 dmodel_t *in; 507 dmodel_t *out; 508 int i, j, count; 509 510 in = (void *)(mod_base + l->fileofs); 511 if (l->filelen % sizeof(*in)) 512 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 513 count = l->filelen / sizeof(*in); 514 out = Hunk_AllocName ( count*sizeof(*out), loadname); 515 516 loadmodel->submodels = out; 517 loadmodel->numsubmodels = count; 518 519 for ( i=0 ; i<count ; i++, in++, out++) 520 { 521 for (j=0 ; j<3 ; j++) 522 { // spread the mins / maxs by a pixel 523 out->mins[j] = LittleFloat (in->mins[j]) - 1; 524 out->maxs[j] = LittleFloat (in->maxs[j]) + 1; 525 out->origin[j] = LittleFloat (in->origin[j]); 526 } 527 for (j=0 ; j<MAX_MAP_HULLS ; j++) 528 out->headnode[j] = LittleLong (in->headnode[j]); 529 out->visleafs = LittleLong (in->visleafs); 530 out->firstface = LittleLong (in->firstface); 531 out->numfaces = LittleLong (in->numfaces); 532 } 533 } 534 535 /* 536 ================= 537 Mod_LoadEdges 538 ================= 539 */ 540 void Mod_LoadEdges (lump_t *l) 541 { 542 dedge_t *in; 543 medge_t *out; 544 int i, count; 545 546 in = (void *)(mod_base + l->fileofs); 547 if (l->filelen % sizeof(*in)) 548 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 549 count = l->filelen / sizeof(*in); 550 out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); 551 552 loadmodel->edges = out; 553 loadmodel->numedges = count; 554 555 for ( i=0 ; i<count ; i++, in++, out++) 556 { 557 out->v[0] = (unsigned short)LittleShort(in->v[0]); 558 out->v[1] = (unsigned short)LittleShort(in->v[1]); 559 } 560 } 561 562 /* 563 ================= 564 Mod_LoadTexinfo 565 ================= 566 */ 567 void Mod_LoadTexinfo (lump_t *l) 568 { 569 texinfo_t *in; 570 mtexinfo_t *out; 571 int i, j, count; 572 int miptex; 573 float len1, len2; 574 575 in = (void *)(mod_base + l->fileofs); 576 if (l->filelen % sizeof(*in)) 577 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 578 count = l->filelen / sizeof(*in); 579 out = Hunk_AllocName ( count*sizeof(*out), loadname); 580 581 loadmodel->texinfo = out; 582 loadmodel->numtexinfo = count; 583 584 for ( i=0 ; i<count ; i++, in++, out++) 585 { 586 #if 0 587 for (j=0 ; j<8 ; j++) 588 out->vecs[0][j] = LittleFloat (in->vecs[0][j]); 589 len1 = Length (in->vecs[0]); 590 len2 = Length (in->vecs[1]); 591 #else 592 for (j=0 ; j<4 ; j++) { 593 out->vecs[0][j] = LittleFloat (in->vecs[0][j]); 594 out->vecs[1][j] = LittleFloat (in->vecs[1][j]); 595 } 596 len1 = Length (out->vecs[0]); 597 len2 = Length (out->vecs[1]); 598 #endif 599 if (len1 + len2 < 2 /*0.001*/) 600 out->mipadjust = 1; 601 else 602 out->mipadjust = 1 / floor( (len1+len2)/2 ); 603 604 miptex = LittleLong (in->miptex); 605 out->flags = LittleLong (in->flags); 606 607 if (!loadmodel->textures) 608 { 609 out->texture = &r_notexture_mip; // checkerboard texture 610 out->flags = 0; 611 } 612 else 613 { 614 if (miptex >= loadmodel->numtextures) 615 SV_Error ("miptex >= loadmodel->numtextures"); 616 out->texture = loadmodel->textures[miptex]; 617 if (!out->texture) 618 { 619 out->texture = &r_notexture_mip; // texture not found 620 out->flags = 0; 621 } 622 } 623 } 624 } 625 626 /* 627 ================ 628 CalcSurfaceExtents 629 630 Fills in s->texturemins[] and s->extents[] 631 ================ 632 */ 633 void CalcSurfaceExtents (msurface_t *s) 634 { 635 float mins[2], maxs[2], val; 636 int i,j, e; 637 mvertex_t *v; 638 mtexinfo_t *tex; 639 int bmins[2], bmaxs[2]; 640 641 mins[0] = mins[1] = 999999; 642 maxs[0] = maxs[1] = -99999; 643 644 tex = s->texinfo; 645 646 for (i=0 ; i<s->numedges ; i++) 647 { 648 e = loadmodel->surfedges[s->firstedge+i]; 649 if (e >= 0) 650 v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; 651 else 652 v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; 653 654 for (j=0 ; j<2 ; j++) 655 { 656 val = v->position[0] * tex->vecs[j][0] + 657 v->position[1] * tex->vecs[j][1] + 658 v->position[2] * tex->vecs[j][2] + 659 tex->vecs[j][3]; 660 if (val < mins[j]) 661 mins[j] = val; 662 if (val > maxs[j]) 663 maxs[j] = val; 664 } 665 } 666 667 for (i=0 ; i<2 ; i++) 668 { 669 bmins[i] = floor(mins[i]/16); 670 bmaxs[i] = ceil(maxs[i]/16); 671 672 s->texturemins[i] = bmins[i] * 16; 673 s->extents[i] = (bmaxs[i] - bmins[i]) * 16; 674 if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256) 675 SV_Error ("Bad surface extents"); 676 } 677 } 678 679 680 /* 681 ================= 682 Mod_LoadFaces 683 ================= 684 */ 685 void Mod_LoadFaces (lump_t *l) 686 { 687 dface_t *in; 688 msurface_t *out; 689 int i, count, surfnum; 690 int planenum, side; 691 692 in = (void *)(mod_base + l->fileofs); 693 if (l->filelen % sizeof(*in)) 694 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 695 count = l->filelen / sizeof(*in); 696 out = Hunk_AllocName ( count*sizeof(*out), loadname); 697 698 loadmodel->surfaces = out; 699 loadmodel->numsurfaces = count; 700 701 for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) 702 { 703 out->firstedge = LittleLong(in->firstedge); 704 out->numedges = LittleShort(in->numedges); 705 out->flags = 0; 706 707 planenum = LittleShort(in->planenum); 708 side = LittleShort(in->side); 709 if (side) 710 out->flags |= SURF_PLANEBACK; 711 712 out->plane = loadmodel->planes + planenum; 713 714 out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); 715 716 CalcSurfaceExtents (out); 717 718 // lighting info 719 720 for (i=0 ; i<MAXLIGHTMAPS ; i++) 721 out->styles[i] = in->styles[i]; 722 i = LittleLong(in->lightofs); 723 if (i == -1) 724 out->samples = NULL; 725 else 726 out->samples = loadmodel->lightdata + i; 727 728 // set the drawing flags flag 729 730 if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky 731 { 732 out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); 733 continue; 734 } 735 736 if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent 737 { 738 out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); 739 for (i=0 ; i<2 ; i++) 740 { 741 out->extents[i] = 16384; 742 out->texturemins[i] = -8192; 743 } 744 continue; 745 } 746 } 747 } 748 749 750 /* 751 ================= 752 Mod_SetParent 753 ================= 754 */ 755 void Mod_SetParent (mnode_t *node, mnode_t *parent) 756 { 757 node->parent = parent; 758 if (node->contents < 0) 759 return; 760 Mod_SetParent (node->children[0], node); 761 Mod_SetParent (node->children[1], node); 762 } 763 764 /* 765 ================= 766 Mod_LoadNodes 767 ================= 768 */ 769 void Mod_LoadNodes (lump_t *l) 770 { 771 int i, j, count, p; 772 dnode_t *in; 773 mnode_t *out; 774 775 in = (void *)(mod_base + l->fileofs); 776 if (l->filelen % sizeof(*in)) 777 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 778 count = l->filelen / sizeof(*in); 779 out = Hunk_AllocName ( count*sizeof(*out), loadname); 780 781 loadmodel->nodes = out; 782 loadmodel->numnodes = count; 783 784 for ( i=0 ; i<count ; i++, in++, out++) 785 { 786 for (j=0 ; j<3 ; j++) 787 { 788 out->minmaxs[j] = LittleShort (in->mins[j]); 789 out->minmaxs[3+j] = LittleShort (in->maxs[j]); 790 } 791 792 p = LittleLong(in->planenum); 793 out->plane = loadmodel->planes + p; 794 795 out->firstsurface = LittleShort (in->firstface); 796 out->numsurfaces = LittleShort (in->numfaces); 797 798 for (j=0 ; j<2 ; j++) 799 { 800 p = LittleShort (in->children[j]); 801 if (p >= 0) 802 out->children[j] = loadmodel->nodes + p; 803 else 804 out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); 805 } 806 } 807 808 Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs 809 } 810 811 /* 812 ================= 813 Mod_LoadLeafs 814 ================= 815 */ 816 void Mod_LoadLeafs (lump_t *l) 817 { 818 dleaf_t *in; 819 mleaf_t *out; 820 int i, j, count, p; 821 822 in = (void *)(mod_base + l->fileofs); 823 if (l->filelen % sizeof(*in)) 824 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 825 count = l->filelen / sizeof(*in); 826 out = Hunk_AllocName ( count*sizeof(*out), loadname); 827 828 loadmodel->leafs = out; 829 loadmodel->numleafs = count; 830 831 for ( i=0 ; i<count ; i++, in++, out++) 832 { 833 for (j=0 ; j<3 ; j++) 834 { 835 out->minmaxs[j] = LittleShort (in->mins[j]); 836 out->minmaxs[3+j] = LittleShort (in->maxs[j]); 837 } 838 839 p = LittleLong(in->contents); 840 out->contents = p; 841 842 out->firstmarksurface = loadmodel->marksurfaces + 843 LittleShort(in->firstmarksurface); 844 out->nummarksurfaces = LittleShort(in->nummarksurfaces); 845 846 p = LittleLong(in->visofs); 847 if (p == -1) 848 out->compressed_vis = NULL; 849 else 850 out->compressed_vis = loadmodel->visdata + p; 851 out->efrags = NULL; 852 853 for (j=0 ; j<4 ; j++) 854 out->ambient_sound_level[j] = in->ambient_level[j]; 855 } 856 } 857 858 /* 859 ================= 860 Mod_LoadClipnodes 861 ================= 862 */ 863 void Mod_LoadClipnodes (lump_t *l) 864 { 865 dclipnode_t *in, *out; 866 int i, count; 867 hull_t *hull; 868 869 in = (void *)(mod_base + l->fileofs); 870 if (l->filelen % sizeof(*in)) 871 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 872 count = l->filelen / sizeof(*in); 873 out = Hunk_AllocName ( count*sizeof(*out), loadname); 874 875 loadmodel->clipnodes = out; 876 loadmodel->numclipnodes = count; 877 878 hull = &loadmodel->hulls[1]; 879 hull->clipnodes = out; 880 hull->firstclipnode = 0; 881 hull->lastclipnode = count-1; 882 hull->planes = loadmodel->planes; 883 hull->clip_mins[0] = -16; 884 hull->clip_mins[1] = -16; 885 hull->clip_mins[2] = -24; 886 hull->clip_maxs[0] = 16; 887 hull->clip_maxs[1] = 16; 888 hull->clip_maxs[2] = 32; 889 890 hull = &loadmodel->hulls[2]; 891 hull->clipnodes = out; 892 hull->firstclipnode = 0; 893 hull->lastclipnode = count-1; 894 hull->planes = loadmodel->planes; 895 hull->clip_mins[0] = -32; 896 hull->clip_mins[1] = -32; 897 hull->clip_mins[2] = -24; 898 hull->clip_maxs[0] = 32; 899 hull->clip_maxs[1] = 32; 900 hull->clip_maxs[2] = 64; 901 902 for (i=0 ; i<count ; i++, out++, in++) 903 { 904 out->planenum = LittleLong(in->planenum); 905 out->children[0] = LittleShort(in->children[0]); 906 out->children[1] = LittleShort(in->children[1]); 907 } 908 } 909 910 /* 911 ================= 912 Mod_MakeHull0 913 914 Deplicate the drawing hull structure as a clipping hull 915 ================= 916 */ 917 void Mod_MakeHull0 (void) 918 { 919 mnode_t *in, *child; 920 dclipnode_t *out; 921 int i, j, count; 922 hull_t *hull; 923 924 hull = &loadmodel->hulls[0]; 925 926 in = loadmodel->nodes; 927 count = loadmodel->numnodes; 928 out = Hunk_AllocName ( count*sizeof(*out), loadname); 929 930 hull->clipnodes = out; 931 hull->firstclipnode = 0; 932 hull->lastclipnode = count-1; 933 hull->planes = loadmodel->planes; 934 935 for (i=0 ; i<count ; i++, out++, in++) 936 { 937 out->planenum = in->plane - loadmodel->planes; 938 for (j=0 ; j<2 ; j++) 939 { 940 child = in->children[j]; 941 if (child->contents < 0) 942 out->children[j] = child->contents; 943 else 944 out->children[j] = child - loadmodel->nodes; 945 } 946 } 947 } 948 949 /* 950 ================= 951 Mod_LoadMarksurfaces 952 ================= 953 */ 954 void Mod_LoadMarksurfaces (lump_t *l) 955 { 956 int i, j, count; 957 short *in; 958 msurface_t **out; 959 960 in = (void *)(mod_base + l->fileofs); 961 if (l->filelen % sizeof(*in)) 962 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 963 count = l->filelen / sizeof(*in); 964 out = Hunk_AllocName ( count*sizeof(*out), loadname); 965 966 loadmodel->marksurfaces = out; 967 loadmodel->nummarksurfaces = count; 968 969 for ( i=0 ; i<count ; i++) 970 { 971 j = LittleShort(in[i]); 972 if (j >= loadmodel->numsurfaces) 973 SV_Error ("Mod_ParseMarksurfaces: bad surface number"); 974 out[i] = loadmodel->surfaces + j; 975 } 976 } 977 978 /* 979 ================= 980 Mod_LoadSurfedges 981 ================= 982 */ 983 void Mod_LoadSurfedges (lump_t *l) 984 { 985 int i, count; 986 int *in, *out; 987 988 in = (void *)(mod_base + l->fileofs); 989 if (l->filelen % sizeof(*in)) 990 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 991 count = l->filelen / sizeof(*in); 992 out = Hunk_AllocName ( count*sizeof(*out), loadname); 993 994 loadmodel->surfedges = out; 995 loadmodel->numsurfedges = count; 996 997 for ( i=0 ; i<count ; i++) 998 out[i] = LittleLong (in[i]); 999 } 1000 1001 /* 1002 ================= 1003 Mod_LoadPlanes 1004 ================= 1005 */ 1006 void Mod_LoadPlanes (lump_t *l) 1007 { 1008 int i, j; 1009 mplane_t *out; 1010 dplane_t *in; 1011 int count; 1012 int bits; 1013 1014 in = (void *)(mod_base + l->fileofs); 1015 if (l->filelen % sizeof(*in)) 1016 SV_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 1017 count = l->filelen / sizeof(*in); 1018 out = Hunk_AllocName ( count*2*sizeof(*out), loadname); 1019 1020 loadmodel->planes = out; 1021 loadmodel->numplanes = count; 1022 1023 for ( i=0 ; i<count ; i++, in++, out++) 1024 { 1025 bits = 0; 1026 for (j=0 ; j<3 ; j++) 1027 { 1028 out->normal[j] = LittleFloat (in->normal[j]); 1029 if (out->normal[j] < 0) 1030 bits |= 1<<j; 1031 } 1032 1033 out->dist = LittleFloat (in->dist); 1034 out->type = LittleLong (in->type); 1035 out->signbits = bits; 1036 } 1037 } 1038 1039 1040 /* 1041 ================= 1042 Mod_LoadBrushModel 1043 ================= 1044 */ 1045 void Mod_LoadBrushModel (model_t *mod, void *buffer) 1046 { 1047 int i, j; 1048 dheader_t *header; 1049 dmodel_t *bm; 1050 1051 loadmodel->type = mod_brush; 1052 1053 header = (dheader_t *)buffer; 1054 1055 i = LittleLong (header->version); 1056 if (i != BSPVERSION) 1057 SV_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); 1058 1059 // swap all the lumps 1060 mod_base = (byte *)header; 1061 1062 for (i=0 ; i<sizeof(dheader_t)/4 ; i++) 1063 ((int *)header)[i] = LittleLong ( ((int *)header)[i]); 1064 1065 // load into heap 1066 1067 mod->checksum = 0; 1068 mod->checksum2 = 0; 1069 1070 // checksum all of the map, except for entities 1071 for (i = 0; i < HEADER_LUMPS; i++) { 1072 if (i == LUMP_ENTITIES) 1073 continue; 1074 mod->checksum ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 1075 header->lumps[i].filelen)); 1076 1077 if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES) 1078 continue; 1079 mod->checksum2 ^= LittleLong(Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 1080 header->lumps[i].filelen)); 1081 } 1082 1083 Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); 1084 Mod_LoadEdges (&header->lumps[LUMP_EDGES]); 1085 Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); 1086 Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); 1087 Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); 1088 Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); 1089 Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); 1090 Mod_LoadFaces (&header->lumps[LUMP_FACES]); 1091 Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); 1092 Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); 1093 Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); 1094 Mod_LoadNodes (&header->lumps[LUMP_NODES]); 1095 Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); 1096 Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); 1097 Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); 1098 1099 Mod_MakeHull0 (); 1100 1101 mod->numframes = 2; // regular and alternate animation 1102 1103 // 1104 // set up the submodels (FIXME: this is confusing) 1105 // 1106 for (i=0 ; i<mod->numsubmodels ; i++) 1107 { 1108 bm = &mod->submodels[i]; 1109 1110 mod->hulls[0].firstclipnode = bm->headnode[0]; 1111 for (j=1 ; j<MAX_MAP_HULLS ; j++) 1112 { 1113 mod->hulls[j].firstclipnode = bm->headnode[j]; 1114 mod->hulls[j].lastclipnode = mod->numclipnodes-1; 1115 } 1116 1117 mod->firstmodelsurface = bm->firstface; 1118 mod->nummodelsurfaces = bm->numfaces; 1119 1120 VectorCopy (bm->maxs, mod->maxs); 1121 VectorCopy (bm->mins, mod->mins); 1122 1123 mod->numleafs = bm->visleafs; 1124 1125 if (i < mod->numsubmodels-1) 1126 { // duplicate the basic information 1127 char name[10]; 1128 1129 sprintf (name, "*%i", i+1); 1130 loadmodel = Mod_FindName (name); 1131 *loadmodel = *mod; 1132 strcpy (loadmodel->name, name); 1133 mod = loadmodel; 1134 } 1135 } 1136 } 1137 1138