r_model.c (27632B)
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 // 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 "r_local.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 // the inline * models from the current map are kept seperate 42 model_t mod_inline[MAX_MOD_KNOWN]; 43 44 int registration_sequence; 45 int modfilelen; 46 47 //=============================================================================== 48 49 50 /* 51 ================ 52 Mod_Modellist_f 53 ================ 54 */ 55 void Mod_Modellist_f (void) 56 { 57 int i; 58 model_t *mod; 59 int total; 60 61 total = 0; 62 ri.Con_Printf (PRINT_ALL,"Loaded models:\n"); 63 for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) 64 { 65 if (!mod->name[0]) 66 continue; 67 ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name); 68 total += mod->extradatasize; 69 } 70 ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total); 71 } 72 73 /* 74 =============== 75 Mod_Init 76 =============== 77 */ 78 void Mod_Init (void) 79 { 80 memset (mod_novis, 0xff, sizeof(mod_novis)); 81 } 82 83 /* 84 ================== 85 Mod_ForName 86 87 Loads in a model for the given name 88 ================== 89 */ 90 model_t *Mod_ForName (char *name, qboolean crash) 91 { 92 model_t *mod; 93 unsigned *buf; 94 int i; 95 96 if (!name[0]) 97 ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name"); 98 99 // 100 // inline models are grabbed only from worldmodel 101 // 102 if (name[0] == '*') 103 { 104 i = atoi(name+1); 105 if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) 106 ri.Sys_Error (ERR_DROP, "bad inline model number"); 107 return &mod_inline[i]; 108 } 109 110 // 111 // search the currently loaded models 112 // 113 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) 114 if (!strcmp (mod->name, name) ) 115 return mod; 116 117 // 118 // find a free model slot spot 119 // 120 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) 121 { 122 if (!mod->name[0]) 123 break; // free spot 124 } 125 if (i == mod_numknown) 126 { 127 if (mod_numknown == MAX_MOD_KNOWN) 128 ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); 129 mod_numknown++; 130 } 131 strcpy (mod->name, name); 132 133 // 134 // load the file 135 // 136 modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf); 137 if (!buf) 138 { 139 if (crash) 140 ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name); 141 memset (mod->name, 0, sizeof(mod->name)); 142 return NULL; 143 } 144 145 loadmodel = mod; 146 147 // 148 // fill it in 149 // 150 151 // call the apropriate loader 152 153 switch (LittleLong(*(unsigned *)buf)) 154 { 155 case IDALIASHEADER: 156 loadmodel->extradata = Hunk_Begin (0x200000); 157 Mod_LoadAliasModel (mod, buf); 158 break; 159 160 case IDSPRITEHEADER: 161 loadmodel->extradata = Hunk_Begin (0x10000); 162 Mod_LoadSpriteModel (mod, buf); 163 break; 164 165 case IDBSPHEADER: 166 loadmodel->extradata = Hunk_Begin (0x1000000); 167 Mod_LoadBrushModel (mod, buf); 168 break; 169 170 default: 171 ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name); 172 break; 173 } 174 175 loadmodel->extradatasize = Hunk_End (); 176 177 ri.FS_FreeFile (buf); 178 179 return mod; 180 } 181 182 183 /* 184 =============== 185 Mod_PointInLeaf 186 =============== 187 */ 188 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) 189 { 190 mnode_t *node; 191 float d; 192 mplane_t *plane; 193 194 if (!model || !model->nodes) 195 ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model"); 196 197 node = model->nodes; 198 while (1) 199 { 200 if (node->contents != -1) 201 return (mleaf_t *)node; 202 plane = node->plane; 203 d = DotProduct (p,plane->normal) - plane->dist; 204 if (d > 0) 205 node = node->children[0]; 206 else 207 node = node->children[1]; 208 } 209 210 return NULL; // never reached 211 } 212 213 214 /* 215 =================== 216 Mod_DecompressVis 217 =================== 218 */ 219 byte *Mod_DecompressVis (byte *in, model_t *model) 220 { 221 static byte decompressed[MAX_MAP_LEAFS/8]; 222 int c; 223 byte *out; 224 int row; 225 226 row = (model->vis->numclusters+7)>>3; 227 out = decompressed; 228 229 #if 0 230 memcpy (out, in, row); 231 #else 232 if (!in) 233 { // no vis info, so make all visible 234 while (row) 235 { 236 *out++ = 0xff; 237 row--; 238 } 239 return decompressed; 240 } 241 242 do 243 { 244 if (*in) 245 { 246 *out++ = *in++; 247 continue; 248 } 249 250 c = in[1]; 251 in += 2; 252 while (c) 253 { 254 *out++ = 0; 255 c--; 256 } 257 } while (out - decompressed < row); 258 #endif 259 260 return decompressed; 261 } 262 263 /* 264 ============== 265 Mod_ClusterPVS 266 ============== 267 */ 268 byte *Mod_ClusterPVS (int cluster, model_t *model) 269 { 270 if (cluster == -1 || !model->vis) 271 return mod_novis; 272 return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS], 273 model); 274 } 275 276 /* 277 =============================================================================== 278 279 BRUSHMODEL LOADING 280 281 =============================================================================== 282 */ 283 284 byte *mod_base; 285 286 287 /* 288 ================= 289 Mod_LoadLighting 290 291 Converts the 24 bit lighting down to 8 bit 292 by taking the brightest component 293 ================= 294 */ 295 void Mod_LoadLighting (lump_t *l) 296 { 297 int i, size; 298 byte *in; 299 300 if (!l->filelen) 301 { 302 loadmodel->lightdata = NULL; 303 return; 304 } 305 size = l->filelen/3; 306 loadmodel->lightdata = Hunk_Alloc (size); 307 in = (void *)(mod_base + l->fileofs); 308 for (i=0 ; i<size ; i++, in+=3) 309 { 310 if (in[0] > in[1] && in[0] > in[2]) 311 loadmodel->lightdata[i] = in[0]; 312 else if (in[1] > in[0] && in[1] > in[2]) 313 loadmodel->lightdata[i] = in[1]; 314 else 315 loadmodel->lightdata[i] = in[2]; 316 } 317 } 318 319 320 int r_leaftovis[MAX_MAP_LEAFS]; 321 int r_vistoleaf[MAX_MAP_LEAFS]; 322 int r_numvisleafs; 323 324 void R_NumberLeafs (mnode_t *node) 325 { 326 mleaf_t *leaf; 327 int leafnum; 328 329 if (node->contents != -1) 330 { 331 leaf = (mleaf_t *)node; 332 leafnum = leaf - loadmodel->leafs; 333 if (leaf->contents & CONTENTS_SOLID) 334 return; 335 r_leaftovis[leafnum] = r_numvisleafs; 336 r_vistoleaf[r_numvisleafs] = leafnum; 337 r_numvisleafs++; 338 return; 339 } 340 341 R_NumberLeafs (node->children[0]); 342 R_NumberLeafs (node->children[1]); 343 } 344 345 346 /* 347 ================= 348 Mod_LoadVisibility 349 ================= 350 */ 351 void Mod_LoadVisibility (lump_t *l) 352 { 353 int i; 354 355 if (!l->filelen) 356 { 357 loadmodel->vis = NULL; 358 return; 359 } 360 loadmodel->vis = Hunk_Alloc ( l->filelen); 361 memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen); 362 363 loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters); 364 for (i=0 ; i<loadmodel->vis->numclusters ; i++) 365 { 366 loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]); 367 loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]); 368 } 369 } 370 371 372 /* 373 ================= 374 Mod_LoadVertexes 375 ================= 376 */ 377 void Mod_LoadVertexes (lump_t *l) 378 { 379 dvertex_t *in; 380 mvertex_t *out; 381 int i, count; 382 383 in = (void *)(mod_base + l->fileofs); 384 if (l->filelen % sizeof(*in)) 385 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 386 count = l->filelen / sizeof(*in); 387 out = Hunk_Alloc ( (count+8)*sizeof(*out)); // extra for skybox 388 389 loadmodel->vertexes = out; 390 loadmodel->numvertexes = count; 391 392 for ( i=0 ; i<count ; i++, in++, out++) 393 { 394 out->position[0] = LittleFloat (in->point[0]); 395 out->position[1] = LittleFloat (in->point[1]); 396 out->position[2] = LittleFloat (in->point[2]); 397 } 398 } 399 400 /* 401 ================= 402 Mod_LoadSubmodels 403 ================= 404 */ 405 void Mod_LoadSubmodels (lump_t *l) 406 { 407 dmodel_t *in; 408 dmodel_t *out; 409 int i, j, count; 410 411 in = (void *)(mod_base + l->fileofs); 412 if (l->filelen % sizeof(*in)) 413 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 414 count = l->filelen / sizeof(*in); 415 out = Hunk_Alloc ( count*sizeof(*out)); 416 417 loadmodel->submodels = out; 418 loadmodel->numsubmodels = count; 419 420 for ( i=0 ; i<count ; i++, in++, out++) 421 { 422 for (j=0 ; j<3 ; j++) 423 { // spread the mins / maxs by a pixel 424 out->mins[j] = LittleFloat (in->mins[j]) - 1; 425 out->maxs[j] = LittleFloat (in->maxs[j]) + 1; 426 out->origin[j] = LittleFloat (in->origin[j]); 427 } 428 out->headnode = LittleLong (in->headnode); 429 out->firstface = LittleLong (in->firstface); 430 out->numfaces = LittleLong (in->numfaces); 431 } 432 } 433 434 /* 435 ================= 436 Mod_LoadEdges 437 ================= 438 */ 439 void Mod_LoadEdges (lump_t *l) 440 { 441 dedge_t *in; 442 medge_t *out; 443 int i, count; 444 445 in = (void *)(mod_base + l->fileofs); 446 if (l->filelen % sizeof(*in)) 447 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 448 count = l->filelen / sizeof(*in); 449 out = Hunk_Alloc ( (count + 13) * sizeof(*out)); // extra for skybox 450 451 loadmodel->edges = out; 452 loadmodel->numedges = count; 453 454 for ( i=0 ; i<count ; i++, in++, out++) 455 { 456 out->v[0] = (unsigned short)LittleShort(in->v[0]); 457 out->v[1] = (unsigned short)LittleShort(in->v[1]); 458 } 459 } 460 461 /* 462 ================= 463 Mod_LoadTexinfo 464 ================= 465 */ 466 void Mod_LoadTexinfo (lump_t *l) 467 { 468 texinfo_t *in; 469 mtexinfo_t *out, *step; 470 int i, j, count; 471 float len1, len2; 472 char name[MAX_QPATH]; 473 int next; 474 475 in = (void *)(mod_base + l->fileofs); 476 if (l->filelen % sizeof(*in)) 477 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 478 count = l->filelen / sizeof(*in); 479 out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox 480 481 loadmodel->texinfo = out; 482 loadmodel->numtexinfo = count; 483 484 for ( i=0 ; i<count ; i++, in++, out++) 485 { 486 for (j=0 ; j<8 ; j++) 487 out->vecs[0][j] = LittleFloat (in->vecs[0][j]); 488 len1 = VectorLength (out->vecs[0]); 489 len2 = VectorLength (out->vecs[1]); 490 len1 = (len1 + len2)/2; 491 if (len1 < 0.32) 492 out->mipadjust = 4; 493 else if (len1 < 0.49) 494 out->mipadjust = 3; 495 else if (len1 < 0.99) 496 out->mipadjust = 2; 497 else 498 out->mipadjust = 1; 499 #if 0 500 if (len1 + len2 < 0.001) 501 out->mipadjust = 1; // don't crash 502 else 503 out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); 504 #endif 505 506 out->flags = LittleLong (in->flags); 507 508 next = LittleLong (in->nexttexinfo); 509 if (next > 0) 510 out->next = loadmodel->texinfo + next; 511 512 Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); 513 out->image = R_FindImage (name, it_wall); 514 if (!out->image) 515 { 516 out->image = r_notexture_mip; // texture not found 517 out->flags = 0; 518 } 519 } 520 521 // count animation frames 522 for (i=0 ; i<count ; i++) 523 { 524 out = &loadmodel->texinfo[i]; 525 out->numframes = 1; 526 for (step = out->next ; step && step != out ; step=step->next) 527 out->numframes++; 528 } 529 } 530 531 /* 532 ================ 533 CalcSurfaceExtents 534 535 Fills in s->texturemins[] and s->extents[] 536 ================ 537 */ 538 void CalcSurfaceExtents (msurface_t *s) 539 { 540 float mins[2], maxs[2], val; 541 int i,j, e; 542 mvertex_t *v; 543 mtexinfo_t *tex; 544 int bmins[2], bmaxs[2]; 545 546 mins[0] = mins[1] = 999999; 547 maxs[0] = maxs[1] = -99999; 548 549 tex = s->texinfo; 550 551 for (i=0 ; i<s->numedges ; i++) 552 { 553 e = loadmodel->surfedges[s->firstedge+i]; 554 if (e >= 0) 555 v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; 556 else 557 v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; 558 559 for (j=0 ; j<2 ; j++) 560 { 561 val = v->position[0] * tex->vecs[j][0] + 562 v->position[1] * tex->vecs[j][1] + 563 v->position[2] * tex->vecs[j][2] + 564 tex->vecs[j][3]; 565 if (val < mins[j]) 566 mins[j] = val; 567 if (val > maxs[j]) 568 maxs[j] = val; 569 } 570 } 571 572 for (i=0 ; i<2 ; i++) 573 { 574 bmins[i] = floor(mins[i]/16); 575 bmaxs[i] = ceil(maxs[i]/16); 576 577 s->texturemins[i] = bmins[i] * 16; 578 s->extents[i] = (bmaxs[i] - bmins[i]) * 16; 579 if (s->extents[i] < 16) 580 s->extents[i] = 16; // take at least one cache block 581 if ( !(tex->flags & (SURF_WARP|SURF_SKY)) && s->extents[i] > 256) 582 ri.Sys_Error (ERR_DROP,"Bad surface extents"); 583 } 584 } 585 586 587 /* 588 ================= 589 Mod_LoadFaces 590 ================= 591 */ 592 void Mod_LoadFaces (lump_t *l) 593 { 594 dface_t *in; 595 msurface_t *out; 596 int i, count, surfnum; 597 int planenum, side; 598 599 in = (void *)(mod_base + l->fileofs); 600 if (l->filelen % sizeof(*in)) 601 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 602 count = l->filelen / sizeof(*in); 603 out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox 604 605 loadmodel->surfaces = out; 606 loadmodel->numsurfaces = count; 607 608 for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) 609 { 610 out->firstedge = LittleLong(in->firstedge); 611 out->numedges = LittleShort(in->numedges); 612 if (out->numedges < 3) 613 ri.Sys_Error (ERR_DROP,"Surface with %s edges", out->numedges); 614 out->flags = 0; 615 616 planenum = LittleShort(in->planenum); 617 side = LittleShort(in->side); 618 if (side) 619 out->flags |= SURF_PLANEBACK; 620 621 out->plane = loadmodel->planes + planenum; 622 623 out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); 624 625 CalcSurfaceExtents (out); 626 627 // lighting info is converted from 24 bit on disk to 8 bit 628 629 for (i=0 ; i<MAXLIGHTMAPS ; i++) 630 out->styles[i] = in->styles[i]; 631 i = LittleLong(in->lightofs); 632 if (i == -1) 633 out->samples = NULL; 634 else 635 out->samples = loadmodel->lightdata + i/3; 636 637 // set the drawing flags flag 638 639 if (!out->texinfo->image) 640 continue; 641 if (out->texinfo->flags & SURF_SKY) 642 { 643 out->flags |= SURF_DRAWSKY; 644 continue; 645 } 646 647 if (out->texinfo->flags & SURF_WARP) 648 { 649 out->flags |= SURF_DRAWTURB; 650 for (i=0 ; i<2 ; i++) 651 { 652 out->extents[i] = 16384; 653 out->texturemins[i] = -8192; 654 } 655 continue; 656 } 657 //============== 658 //PGM 659 // this marks flowing surfaces as turbulent, but with the new 660 // SURF_FLOW flag. 661 if (out->texinfo->flags & SURF_FLOWING) 662 { 663 out->flags |= SURF_DRAWTURB | SURF_FLOW; 664 for (i=0 ; i<2 ; i++) 665 { 666 out->extents[i] = 16384; 667 out->texturemins[i] = -8192; 668 } 669 continue; 670 } 671 //PGM 672 //============== 673 } 674 } 675 676 677 /* 678 ================= 679 Mod_SetParent 680 ================= 681 */ 682 void Mod_SetParent (mnode_t *node, mnode_t *parent) 683 { 684 node->parent = parent; 685 if (node->contents != -1) 686 return; 687 Mod_SetParent (node->children[0], node); 688 Mod_SetParent (node->children[1], node); 689 } 690 691 /* 692 ================= 693 Mod_LoadNodes 694 ================= 695 */ 696 void Mod_LoadNodes (lump_t *l) 697 { 698 int i, j, count, p; 699 dnode_t *in; 700 mnode_t *out; 701 702 in = (void *)(mod_base + l->fileofs); 703 if (l->filelen % sizeof(*in)) 704 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 705 count = l->filelen / sizeof(*in); 706 out = Hunk_Alloc ( count*sizeof(*out)); 707 708 loadmodel->nodes = out; 709 loadmodel->numnodes = count; 710 711 for ( i=0 ; i<count ; i++, in++, out++) 712 { 713 for (j=0 ; j<3 ; j++) 714 { 715 out->minmaxs[j] = LittleShort (in->mins[j]); 716 out->minmaxs[3+j] = LittleShort (in->maxs[j]); 717 } 718 719 p = LittleLong(in->planenum); 720 out->plane = loadmodel->planes + p; 721 722 out->firstsurface = LittleShort (in->firstface); 723 out->numsurfaces = LittleShort (in->numfaces); 724 out->contents = CONTENTS_NODE; // differentiate from leafs 725 726 for (j=0 ; j<2 ; j++) 727 { 728 p = LittleLong (in->children[j]); 729 if (p >= 0) 730 out->children[j] = loadmodel->nodes + p; 731 else 732 out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); 733 } 734 } 735 736 Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs 737 } 738 739 /* 740 ================= 741 Mod_LoadLeafs 742 ================= 743 */ 744 void Mod_LoadLeafs (lump_t *l) 745 { 746 dleaf_t *in; 747 mleaf_t *out; 748 int i, j, count; 749 750 in = (void *)(mod_base + l->fileofs); 751 if (l->filelen % sizeof(*in)) 752 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 753 count = l->filelen / sizeof(*in); 754 out = Hunk_Alloc ( count*sizeof(*out)); 755 756 loadmodel->leafs = out; 757 loadmodel->numleafs = count; 758 759 for ( i=0 ; i<count ; i++, in++, out++) 760 { 761 for (j=0 ; j<3 ; j++) 762 { 763 out->minmaxs[j] = LittleShort (in->mins[j]); 764 out->minmaxs[3+j] = LittleShort (in->maxs[j]); 765 } 766 767 out->contents = LittleLong(in->contents); 768 out->cluster = LittleShort(in->cluster); 769 out->area = LittleShort(in->area); 770 771 out->firstmarksurface = loadmodel->marksurfaces + 772 LittleShort(in->firstleafface); 773 out->nummarksurfaces = LittleShort(in->numleaffaces); 774 } 775 } 776 777 778 /* 779 ================= 780 Mod_LoadMarksurfaces 781 ================= 782 */ 783 void Mod_LoadMarksurfaces (lump_t *l) 784 { 785 int i, j, count; 786 short *in; 787 msurface_t **out; 788 789 in = (void *)(mod_base + l->fileofs); 790 if (l->filelen % sizeof(*in)) 791 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 792 count = l->filelen / sizeof(*in); 793 out = Hunk_Alloc ( count*sizeof(*out)); 794 795 loadmodel->marksurfaces = out; 796 loadmodel->nummarksurfaces = count; 797 798 for ( i=0 ; i<count ; i++) 799 { 800 j = LittleShort(in[i]); 801 if (j >= loadmodel->numsurfaces) 802 ri.Sys_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number"); 803 out[i] = loadmodel->surfaces + j; 804 } 805 } 806 807 /* 808 ================= 809 Mod_LoadSurfedges 810 ================= 811 */ 812 void Mod_LoadSurfedges (lump_t *l) 813 { 814 int i, count; 815 int *in, *out; 816 817 in = (void *)(mod_base + l->fileofs); 818 if (l->filelen % sizeof(*in)) 819 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 820 count = l->filelen / sizeof(*in); 821 out = Hunk_Alloc ( (count+24)*sizeof(*out)); // extra for skybox 822 823 loadmodel->surfedges = out; 824 loadmodel->numsurfedges = count; 825 826 for ( i=0 ; i<count ; i++) 827 out[i] = LittleLong (in[i]); 828 } 829 830 /* 831 ================= 832 Mod_LoadPlanes 833 ================= 834 */ 835 void Mod_LoadPlanes (lump_t *l) 836 { 837 int i, j; 838 mplane_t *out; 839 dplane_t *in; 840 int count; 841 int bits; 842 843 in = (void *)(mod_base + l->fileofs); 844 if (l->filelen % sizeof(*in)) 845 ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 846 count = l->filelen / sizeof(*in); 847 out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox 848 849 loadmodel->planes = out; 850 loadmodel->numplanes = count; 851 852 for ( i=0 ; i<count ; i++, in++, out++) 853 { 854 bits = 0; 855 for (j=0 ; j<3 ; j++) 856 { 857 out->normal[j] = LittleFloat (in->normal[j]); 858 if (out->normal[j] < 0) 859 bits |= 1<<j; 860 } 861 862 out->dist = LittleFloat (in->dist); 863 out->type = LittleLong (in->type); 864 out->signbits = bits; 865 } 866 } 867 868 869 /* 870 ================= 871 Mod_LoadBrushModel 872 ================= 873 */ 874 void Mod_LoadBrushModel (model_t *mod, void *buffer) 875 { 876 int i; 877 dheader_t *header; 878 dmodel_t *bm; 879 880 loadmodel->type = mod_brush; 881 if (loadmodel != mod_known) 882 ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world"); 883 884 header = (dheader_t *)buffer; 885 886 i = LittleLong (header->version); 887 if (i != BSPVERSION) 888 ri.Sys_Error (ERR_DROP,"Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); 889 890 // swap all the lumps 891 mod_base = (byte *)header; 892 893 for (i=0 ; i<sizeof(dheader_t)/4 ; i++) 894 ((int *)header)[i] = LittleLong ( ((int *)header)[i]); 895 896 // load into heap 897 898 Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); 899 Mod_LoadEdges (&header->lumps[LUMP_EDGES]); 900 Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); 901 Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); 902 Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); 903 Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); 904 Mod_LoadFaces (&header->lumps[LUMP_FACES]); 905 Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]); 906 Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); 907 Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); 908 Mod_LoadNodes (&header->lumps[LUMP_NODES]); 909 Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); 910 r_numvisleafs = 0; 911 R_NumberLeafs (loadmodel->nodes); 912 913 // 914 // set up the submodels 915 // 916 for (i=0 ; i<mod->numsubmodels ; i++) 917 { 918 model_t *starmod; 919 920 bm = &mod->submodels[i]; 921 starmod = &mod_inline[i]; 922 923 *starmod = *loadmodel; 924 925 starmod->firstmodelsurface = bm->firstface; 926 starmod->nummodelsurfaces = bm->numfaces; 927 starmod->firstnode = bm->headnode; 928 if (starmod->firstnode >= loadmodel->numnodes) 929 ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i); 930 931 VectorCopy (bm->maxs, starmod->maxs); 932 VectorCopy (bm->mins, starmod->mins); 933 934 if (i == 0) 935 *loadmodel = *starmod; 936 } 937 938 R_InitSkyBox (); 939 } 940 941 /* 942 ============================================================================== 943 944 ALIAS MODELS 945 946 ============================================================================== 947 */ 948 949 /* 950 ================= 951 Mod_LoadAliasModel 952 ================= 953 */ 954 void Mod_LoadAliasModel (model_t *mod, void *buffer) 955 { 956 int i, j; 957 dmdl_t *pinmodel, *pheader; 958 dstvert_t *pinst, *poutst; 959 dtriangle_t *pintri, *pouttri; 960 daliasframe_t *pinframe, *poutframe; 961 int *pincmd, *poutcmd; 962 int version; 963 964 pinmodel = (dmdl_t *)buffer; 965 966 version = LittleLong (pinmodel->version); 967 if (version != ALIAS_VERSION) 968 ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", 969 mod->name, version, ALIAS_VERSION); 970 971 pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end)); 972 973 // byte swap the header fields and sanity check 974 for (i=0 ; i<sizeof(dmdl_t)/4 ; i++) 975 ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]); 976 977 if (pheader->skinheight > MAX_LBM_HEIGHT) 978 ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name, 979 MAX_LBM_HEIGHT); 980 981 if (pheader->num_xyz <= 0) 982 ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name); 983 984 if (pheader->num_xyz > MAX_VERTS) 985 ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name); 986 987 if (pheader->num_st <= 0) 988 ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name); 989 990 if (pheader->num_tris <= 0) 991 ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name); 992 993 if (pheader->num_frames <= 0) 994 ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name); 995 996 // 997 // load base s and t vertices (not used in gl version) 998 // 999 pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st); 1000 poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st); 1001 1002 for (i=0 ; i<pheader->num_st ; i++) 1003 { 1004 poutst[i].s = LittleShort (pinst[i].s); 1005 poutst[i].t = LittleShort (pinst[i].t); 1006 } 1007 1008 // 1009 // load triangle lists 1010 // 1011 pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris); 1012 pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris); 1013 1014 for (i=0 ; i<pheader->num_tris ; i++) 1015 { 1016 for (j=0 ; j<3 ; j++) 1017 { 1018 pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]); 1019 pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]); 1020 } 1021 } 1022 1023 // 1024 // load the frames 1025 // 1026 for (i=0 ; i<pheader->num_frames ; i++) 1027 { 1028 pinframe = (daliasframe_t *) ((byte *)pinmodel 1029 + pheader->ofs_frames + i * pheader->framesize); 1030 poutframe = (daliasframe_t *) ((byte *)pheader 1031 + pheader->ofs_frames + i * pheader->framesize); 1032 1033 memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name)); 1034 for (j=0 ; j<3 ; j++) 1035 { 1036 poutframe->scale[j] = LittleFloat (pinframe->scale[j]); 1037 poutframe->translate[j] = LittleFloat (pinframe->translate[j]); 1038 } 1039 // verts are all 8 bit, so no swapping needed 1040 memcpy (poutframe->verts, pinframe->verts, 1041 pheader->num_xyz*sizeof(dtrivertx_t)); 1042 1043 } 1044 1045 mod->type = mod_alias; 1046 1047 // 1048 // load the glcmds 1049 // 1050 pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds); 1051 poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds); 1052 for (i=0 ; i<pheader->num_glcmds ; i++) 1053 poutcmd[i] = LittleLong (pincmd[i]); 1054 1055 1056 // register all skins 1057 memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, 1058 pheader->num_skins*MAX_SKINNAME); 1059 for (i=0 ; i<pheader->num_skins ; i++) 1060 { 1061 mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); 1062 } 1063 } 1064 1065 /* 1066 ============================================================================== 1067 1068 SPRITE MODELS 1069 1070 ============================================================================== 1071 */ 1072 1073 /* 1074 ================= 1075 Mod_LoadSpriteModel 1076 ================= 1077 */ 1078 void Mod_LoadSpriteModel (model_t *mod, void *buffer) 1079 { 1080 dsprite_t *sprin, *sprout; 1081 int i; 1082 1083 sprin = (dsprite_t *)buffer; 1084 sprout = Hunk_Alloc (modfilelen); 1085 1086 sprout->ident = LittleLong (sprin->ident); 1087 sprout->version = LittleLong (sprin->version); 1088 sprout->numframes = LittleLong (sprin->numframes); 1089 1090 if (sprout->version != SPRITE_VERSION) 1091 ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", 1092 mod->name, sprout->version, SPRITE_VERSION); 1093 1094 if (sprout->numframes > MAX_MD2SKINS) 1095 ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)", 1096 mod->name, sprout->numframes, MAX_MD2SKINS); 1097 1098 // byte swap everything 1099 for (i=0 ; i<sprout->numframes ; i++) 1100 { 1101 sprout->frames[i].width = LittleLong (sprin->frames[i].width); 1102 sprout->frames[i].height = LittleLong (sprin->frames[i].height); 1103 sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x); 1104 sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y); 1105 memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME); 1106 mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite); 1107 } 1108 1109 mod->type = mod_sprite; 1110 } 1111 1112 //============================================================================= 1113 1114 /* 1115 @@@@@@@@@@@@@@@@@@@@@ 1116 R_BeginRegistration 1117 1118 Specifies the model that will be used as the world 1119 @@@@@@@@@@@@@@@@@@@@@ 1120 */ 1121 void R_BeginRegistration (char *model) 1122 { 1123 char fullname[MAX_QPATH]; 1124 cvar_t *flushmap; 1125 1126 registration_sequence++; 1127 r_oldviewcluster = -1; // force markleafs 1128 Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model); 1129 1130 D_FlushCaches (); 1131 // explicitly free the old map if different 1132 // this guarantees that mod_known[0] is the world map 1133 flushmap = ri.Cvar_Get ("flushmap", "0", 0); 1134 if ( strcmp(mod_known[0].name, fullname) || flushmap->value) 1135 Mod_Free (&mod_known[0]); 1136 r_worldmodel = R_RegisterModel (fullname); 1137 R_NewMap (); 1138 } 1139 1140 1141 /* 1142 @@@@@@@@@@@@@@@@@@@@@ 1143 R_RegisterModel 1144 1145 @@@@@@@@@@@@@@@@@@@@@ 1146 */ 1147 struct model_s *R_RegisterModel (char *name) 1148 { 1149 model_t *mod; 1150 int i; 1151 dsprite_t *sprout; 1152 dmdl_t *pheader; 1153 1154 mod = Mod_ForName (name, false); 1155 if (mod) 1156 { 1157 mod->registration_sequence = registration_sequence; 1158 1159 // register any images used by the models 1160 if (mod->type == mod_sprite) 1161 { 1162 sprout = (dsprite_t *)mod->extradata; 1163 for (i=0 ; i<sprout->numframes ; i++) 1164 mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite); 1165 } 1166 else if (mod->type == mod_alias) 1167 { 1168 pheader = (dmdl_t *)mod->extradata; 1169 for (i=0 ; i<pheader->num_skins ; i++) 1170 mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); 1171 //PGM 1172 mod->numframes = pheader->num_frames; 1173 //PGM 1174 } 1175 else if (mod->type == mod_brush) 1176 { 1177 for (i=0 ; i<mod->numtexinfo ; i++) 1178 mod->texinfo[i].image->registration_sequence = registration_sequence; 1179 } 1180 } 1181 return mod; 1182 } 1183 1184 /* 1185 @@@@@@@@@@@@@@@@@@@@@ 1186 R_EndRegistration 1187 1188 @@@@@@@@@@@@@@@@@@@@@ 1189 */ 1190 void R_EndRegistration (void) 1191 { 1192 int i; 1193 model_t *mod; 1194 1195 for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++) 1196 { 1197 if (!mod->name[0]) 1198 continue; 1199 if (mod->registration_sequence != registration_sequence) 1200 { // don't need this model 1201 Hunk_Free (mod->extradata); 1202 memset (mod, 0, sizeof(*mod)); 1203 } 1204 else 1205 { // make sure it is paged in 1206 Com_PageInMemory (mod->extradata, mod->extradatasize); 1207 } 1208 } 1209 1210 R_FreeUnusedImages (); 1211 } 1212 1213 1214 //============================================================================= 1215 1216 /* 1217 ================ 1218 Mod_Free 1219 ================ 1220 */ 1221 void Mod_Free (model_t *mod) 1222 { 1223 Hunk_Free (mod->extradata); 1224 memset (mod, 0, sizeof(*mod)); 1225 } 1226 1227 /* 1228 ================ 1229 Mod_FreeAll 1230 ================ 1231 */ 1232 void Mod_FreeAll (void) 1233 { 1234 int i; 1235 1236 for (i=0 ; i<mod_numknown ; i++) 1237 { 1238 if (mod_known[i].extradatasize) 1239 Mod_Free (&mod_known[i]); 1240 } 1241 }