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