1/* 2Copyright (C) 1996-1997 Id Software, Inc. 3 4This program is free software; you can redistribute it and/or 5modify it under the terms of the GNU General Public License 6as published by the Free Software Foundation; either version 2 7of the License, or (at your option) any later version. 8 9This program is distributed in the hope that it will be useful, 10but WITHOUT ANY WARRANTY; without even the implied warranty of 11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 13See the GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; if not, write to the Free Software 17Foundation, 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 "quakedef.h" 26#include "r_local.h" 27 28model_t *loadmodel; 29char loadname[32]; // for hunk tags 30 31void Mod_LoadSpriteModel (model_t *mod, void *buffer); 32void Mod_LoadBrushModel (model_t *mod, void *buffer); 33void Mod_LoadAliasModel (model_t *mod, void *buffer); 34model_t *Mod_LoadModel (model_t *mod, qboolean crash); 35 36byte mod_novis[MAX_MAP_LEAFS/8]; 37 38#define MAX_MOD_KNOWN 256 39model_t mod_known[MAX_MOD_KNOWN]; 40int mod_numknown; 41 42/* 43=============== 44Mod_Init 45=============== 46*/ 47void Mod_Init (void) 48{ 49 memset (mod_novis, 0xff, sizeof(mod_novis)); 50} 51 52/* 53=============== 54Mod_Init 55 56Caches the data if needed 57=============== 58*/ 59void *Mod_Extradata (model_t *mod) 60{ 61 void *r; 62 63 r = Cache_Check (&mod->cache); 64 if (r) 65 return r; 66 67 Mod_LoadModel (mod, true); 68 69 if (!mod->cache.data) 70 Sys_Error ("Mod_Extradata: caching failed"); 71 return mod->cache.data; 72} 73 74/* 75=============== 76Mod_PointInLeaf 77=============== 78*/ 79mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) 80{ 81 mnode_t *node; 82 float d; 83 mplane_t *plane; 84 85 if (!model || !model->nodes) 86 Sys_Error ("Mod_PointInLeaf: bad model"); 87 88 node = model->nodes; 89 while (1) 90 { 91 if (node->contents < 0) 92 return (mleaf_t *)node; 93 plane = node->plane; 94 d = DotProduct (p,plane->normal) - plane->dist; 95 if (d > 0) 96 node = node->children[0]; 97 else 98 node = node->children[1]; 99 } 100 101 return NULL; // never reached 102} 103 104 105/* 106=================== 107Mod_DecompressVis 108=================== 109*/ 110byte *Mod_DecompressVis (byte *in, model_t *model) 111{ 112 static byte decompressed[MAX_MAP_LEAFS/8]; 113 int c; 114 byte *out; 115 int row; 116 117 row = (model->numleafs+7)>>3; 118 out = decompressed; 119 120#if 0 121 memcpy (out, in, row); 122#else 123 if (!in) 124 { // no vis info, so make all visible 125 while (row) 126 { 127 *out++ = 0xff; 128 row--; 129 } 130 return decompressed; 131 } 132 133 do 134 { 135 if (*in) 136 { 137 *out++ = *in++; 138 continue; 139 } 140 141 c = in[1]; 142 in += 2; 143 while (c) 144 { 145 *out++ = 0; 146 c--; 147 } 148 } while (out - decompressed < row); 149#endif 150 151 return decompressed; 152} 153 154byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model) 155{ 156 if (leaf == model->leafs) 157 return mod_novis; 158 return Mod_DecompressVis (leaf->compressed_vis, model); 159} 160 161/* 162=================== 163Mod_ClearAll 164=================== 165*/ 166void Mod_ClearAll (void) 167{ 168 int i; 169 model_t *mod; 170 171 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) 172 if (mod->type != mod_alias) 173 mod->needload = true; 174} 175 176/* 177================== 178Mod_FindName 179 180================== 181*/ 182model_t *Mod_FindName (char *name) 183{ 184 int i; 185 model_t *mod; 186 187 if (!name[0]) 188 Sys_Error ("Mod_ForName: NULL name"); 189 190// 191// search the currently loaded models 192// 193 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) 194 if (!strcmp (mod->name, name) ) 195 break; 196 197 if (i == mod_numknown) 198 { 199 if (mod_numknown == MAX_MOD_KNOWN) 200 Sys_Error ("mod_numknown == MAX_MOD_KNOWN"); 201 strcpy (mod->name, name); 202 mod->needload = true; 203 mod_numknown++; 204 } 205 206 return mod; 207} 208 209/* 210================== 211Mod_TouchModel 212 213================== 214*/ 215void Mod_TouchModel (char *name) 216{ 217 model_t *mod; 218 219 mod = Mod_FindName (name); 220 221 if (!mod->needload) 222 { 223 if (mod->type == mod_alias) 224 Cache_Check (&mod->cache); 225 } 226} 227 228/* 229================== 230Mod_LoadModel 231 232Loads a model into the cache 233================== 234*/ 235model_t *Mod_LoadModel (model_t *mod, qboolean crash) 236{ 237 void *d; 238 unsigned *buf; 239 byte stackbuf[1024]; // avoid dirtying the cache heap 240 241 if (!mod->needload) 242 { 243 if (mod->type == mod_alias) 244 { 245 d = Cache_Check (&mod->cache); 246 if (d) 247 return mod; 248 } 249 else 250 return mod; // not cached at all 251 } 252 253// 254// because the world is so huge, load it one piece at a time 255// 256 if (!crash) 257 { 258 259 } 260 261// 262// load the file 263// 264 buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); 265 if (!buf) 266 { 267 if (crash) 268 Sys_Error ("Mod_NumForName: %s not found", mod->name); 269 return NULL; 270 } 271 272// 273// allocate a new model 274// 275 COM_FileBase (mod->name, loadname); 276 277 loadmodel = mod; 278 279// 280// fill it in 281// 282 283// call the apropriate loader 284 mod->needload = false; 285 286 switch (LittleLong(*(unsigned *)buf)) 287 { 288 case IDPOLYHEADER: 289 Mod_LoadAliasModel (mod, buf); 290 break; 291 292 case IDSPRITEHEADER: 293 Mod_LoadSpriteModel (mod, buf); 294 break; 295 296 default: 297 Mod_LoadBrushModel (mod, buf); 298 break; 299 } 300 301 return mod; 302} 303 304/* 305================== 306Mod_ForName 307 308Loads in a model for the given name 309================== 310*/ 311model_t *Mod_ForName (char *name, qboolean crash) 312{ 313 model_t *mod; 314 315 mod = Mod_FindName (name); 316 317 return Mod_LoadModel (mod, crash); 318} 319 320 321/* 322=============================================================================== 323 324 BRUSHMODEL LOADING 325 326=============================================================================== 327*/ 328 329byte *mod_base; 330 331 332/* 333================= 334Mod_LoadTextures 335================= 336*/ 337void Mod_LoadTextures (lump_t *l) 338{ 339 int i, j, pixels, num, max, altmax; 340 miptex_t *mt; 341 texture_t *tx, *tx2; 342 texture_t *anims[10]; 343 texture_t *altanims[10]; 344 dmiptexlump_t *m; 345 346 if (!l->filelen) 347 { 348 loadmodel->textures = NULL; 349 return; 350 } 351 m = (dmiptexlump_t *)(mod_base + l->fileofs); 352 353 m->nummiptex = LittleLong (m->nummiptex); 354 355 loadmodel->numtextures = m->nummiptex; 356 loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); 357 358 for (i=0 ; i<m->nummiptex ; i++) 359 { 360 m->dataofs[i] = LittleLong(m->dataofs[i]); 361 if (m->dataofs[i] == -1) 362 continue; 363 mt = (miptex_t *)((byte *)m + m->dataofs[i]); 364 mt->width = LittleLong (mt->width); 365 mt->height = LittleLong (mt->height); 366 for (j=0 ; j<MIPLEVELS ; j++) 367 mt->offsets[j] = LittleLong (mt->offsets[j]); 368 369 if ( (mt->width & 15) || (mt->height & 15) ) 370 Sys_Error ("Texture %s is not 16 aligned", mt->name); 371 pixels = mt->width*mt->height/64*85; 372 tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname ); 373 loadmodel->textures[i] = tx; 374 375 memcpy (tx->name, mt->name, sizeof(tx->name)); 376 tx->width = mt->width; 377 tx->height = mt->height; 378 for (j=0 ; j<MIPLEVELS ; j++) 379 tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t); 380 // the pixels immediately follow the structures 381 memcpy ( tx+1, mt+1, pixels); 382 383 if (!Q_strncmp(mt->name,"sky",3)) 384 R_InitSky (tx); 385 } 386 387// 388// sequence the animations 389// 390 for (i=0 ; i<m->nummiptex ; i++) 391 { 392 tx = loadmodel->textures[i]; 393 if (!tx || tx->name[0] != '+') 394 continue; 395 if (tx->anim_next) 396 continue; // allready sequenced 397 398 // find the number of frames in the animation 399 memset (anims, 0, sizeof(anims)); 400 memset (altanims, 0, sizeof(altanims)); 401 402 max = tx->name[1]; 403 altmax = 0; 404 if (max >= 'a' && max <= 'z') 405 max -= 'a' - 'A'; 406 if (max >= '0' && max <= '9') 407 { 408 max -= '0'; 409 altmax = 0; 410 anims[max] = tx; 411 max++; 412 } 413 else if (max >= 'A' && max <= 'J') 414 { 415 altmax = max - 'A'; 416 max = 0; 417 altanims[altmax] = tx; 418 altmax++; 419 } 420 else 421 Sys_Error ("Bad animating texture %s", tx->name); 422 423 for (j=i+1 ; j<m->nummiptex ; j++) 424 { 425 tx2 = loadmodel->textures[j]; 426 if (!tx2 || tx2->name[0] != '+') 427 continue; 428 if (strcmp (tx2->name+2, tx->name+2)) 429 continue; 430 431 num = tx2->name[1]; 432 if (num >= 'a' && num <= 'z') 433 num -= 'a' - 'A'; 434 if (num >= '0' && num <= '9') 435 { 436 num -= '0'; 437 anims[num] = tx2; 438 if (num+1 > max) 439 max = num + 1; 440 } 441 else if (num >= 'A' && num <= 'J') 442 { 443 num = num - 'A'; 444 altanims[num] = tx2; 445 if (num+1 > altmax) 446 altmax = num+1; 447 } 448 else 449 Sys_Error ("Bad animating texture %s", tx->name); 450 } 451 452#define ANIM_CYCLE 2 453 // link them all together 454 for (j=0 ; j<max ; j++) 455 { 456 tx2 = anims[j]; 457 if (!tx2) 458 Sys_Error ("Missing frame %i of %s",j, tx->name); 459 tx2->anim_total = max * ANIM_CYCLE; 460 tx2->anim_min = j * ANIM_CYCLE; 461 tx2->anim_max = (j+1) * ANIM_CYCLE; 462 tx2->anim_next = anims[ (j+1)%max ]; 463 if (altmax) 464 tx2->alternate_anims = altanims[0]; 465 } 466 for (j=0 ; j<altmax ; j++) 467 { 468 tx2 = altanims[j]; 469 if (!tx2) 470 Sys_Error ("Missing frame %i of %s",j, tx->name); 471 tx2->anim_total = altmax * ANIM_CYCLE; 472 tx2->anim_min = j * ANIM_CYCLE; 473 tx2->anim_max = (j+1) * ANIM_CYCLE; 474 tx2->anim_next = altanims[ (j+1)%altmax ]; 475 if (max) 476 tx2->alternate_anims = anims[0]; 477 } 478 } 479} 480 481/* 482================= 483Mod_LoadLighting 484================= 485*/ 486void Mod_LoadLighting (lump_t *l) 487{ 488 if (!l->filelen) 489 { 490 loadmodel->lightdata = NULL; 491 return; 492 } 493 loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname); 494 memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); 495} 496 497 498/* 499================= 500Mod_LoadVisibility 501================= 502*/ 503void Mod_LoadVisibility (lump_t *l) 504{ 505 if (!l->filelen) 506 { 507 loadmodel->visdata = NULL; 508 return; 509 } 510 loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname); 511 memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen); 512} 513 514 515/* 516================= 517Mod_LoadEntities 518================= 519*/ 520void Mod_LoadEntities (lump_t *l) 521{ 522 if (!l->filelen) 523 { 524 loadmodel->entities = NULL; 525 return; 526 } 527 loadmodel->entities = Hunk_AllocName ( l->filelen, loadname); 528 memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen); 529} 530 531 532/* 533================= 534Mod_LoadVertexes 535================= 536*/ 537void Mod_LoadVertexes (lump_t *l) 538{ 539 dvertex_t *in; 540 mvertex_t *out; 541 int i, count; 542 543 in = (void *)(mod_base + l->fileofs); 544 if (l->filelen % sizeof(*in)) 545 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 546 count = l->filelen / sizeof(*in); 547 out = Hunk_AllocName ( count*sizeof(*out), loadname); 548 549 loadmodel->vertexes = out; 550 loadmodel->numvertexes = count; 551 552 for ( i=0 ; i<count ; i++, in++, out++) 553 { 554 out->position[0] = LittleFloat (in->point[0]); 555 out->position[1] = LittleFloat (in->point[1]); 556 out->position[2] = LittleFloat (in->point[2]); 557 } 558} 559 560/* 561================= 562Mod_LoadSubmodels 563================= 564*/ 565void Mod_LoadSubmodels (lump_t *l) 566{ 567 dmodel_t *in; 568 dmodel_t *out; 569 int i, j, count; 570 571 in = (void *)(mod_base + l->fileofs); 572 if (l->filelen % sizeof(*in)) 573 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 574 count = l->filelen / sizeof(*in); 575 out = Hunk_AllocName ( count*sizeof(*out), loadname); 576 577 loadmodel->submodels = out; 578 loadmodel->numsubmodels = count; 579 580 for ( i=0 ; i<count ; i++, in++, out++) 581 { 582 for (j=0 ; j<3 ; j++) 583 { // spread the mins / maxs by a pixel 584 out->mins[j] = LittleFloat (in->mins[j]) - 1; 585 out->maxs[j] = LittleFloat (in->maxs[j]) + 1; 586 out->origin[j] = LittleFloat (in->origin[j]); 587 } 588 for (j=0 ; j<MAX_MAP_HULLS ; j++) 589 out->headnode[j] = LittleLong (in->headnode[j]); 590 out->visleafs = LittleLong (in->visleafs); 591 out->firstface = LittleLong (in->firstface); 592 out->numfaces = LittleLong (in->numfaces); 593 } 594} 595 596/* 597================= 598Mod_LoadEdges 599================= 600*/ 601void Mod_LoadEdges (lump_t *l) 602{ 603 dedge_t *in; 604 medge_t *out; 605 int i, count; 606 607 in = (void *)(mod_base + l->fileofs); 608 if (l->filelen % sizeof(*in)) 609 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 610 count = l->filelen / sizeof(*in); 611 out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname); 612 613 loadmodel->edges = out; 614 loadmodel->numedges = count; 615 616 for ( i=0 ; i<count ; i++, in++, out++) 617 { 618 out->v[0] = (unsigned short)LittleShort(in->v[0]); 619 out->v[1] = (unsigned short)LittleShort(in->v[1]); 620 } 621} 622 623/* 624================= 625Mod_LoadTexinfo 626================= 627*/ 628void Mod_LoadTexinfo (lump_t *l) 629{ 630 texinfo_t *in; 631 mtexinfo_t *out; 632 int i, j, count; 633 int miptex; 634 float len1, len2; 635 636 in = (void *)(mod_base + l->fileofs); 637 if (l->filelen % sizeof(*in)) 638 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 639 count = l->filelen / sizeof(*in); 640 out = Hunk_AllocName ( count*sizeof(*out), loadname); 641 642 loadmodel->texinfo = out; 643 loadmodel->numtexinfo = count; 644 645 for ( i=0 ; i<count ; i++, in++, out++) 646 { 647 for (j=0 ; j<8 ; j++) 648 out->vecs[0][j] = LittleFloat (in->vecs[0][j]); 649 len1 = Length (out->vecs[0]); 650 len2 = Length (out->vecs[1]); 651 len1 = (len1 + len2)/2; 652 if (len1 < 0.32) 653 out->mipadjust = 4; 654 else if (len1 < 0.49) 655 out->mipadjust = 3; 656 else if (len1 < 0.99) 657 out->mipadjust = 2; 658 else 659 out->mipadjust = 1; 660#if 0 661 if (len1 + len2 < 0.001) 662 out->mipadjust = 1; // don't crash 663 else 664 out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); 665#endif 666 667 miptex = LittleLong (in->miptex); 668 out->flags = LittleLong (in->flags); 669 670 if (!loadmodel->textures) 671 { 672 out->texture = r_notexture_mip; // checkerboard texture 673 out->flags = 0; 674 } 675 else 676 { 677 if (miptex >= loadmodel->numtextures) 678 Sys_Error ("miptex >= loadmodel->numtextures"); 679 out->texture = loadmodel->textures[miptex]; 680 if (!out->texture) 681 { 682 out->texture = r_notexture_mip; // texture not found 683 out->flags = 0; 684 } 685 } 686 } 687} 688 689/* 690================ 691CalcSurfaceExtents 692 693Fills in s->texturemins[] and s->extents[] 694================ 695*/ 696void CalcSurfaceExtents (msurface_t *s) 697{ 698 float mins[2], maxs[2], val; 699 int i,j, e; 700 mvertex_t *v; 701 mtexinfo_t *tex; 702 int bmins[2], bmaxs[2]; 703 704 mins[0] = mins[1] = 999999; 705 maxs[0] = maxs[1] = -99999; 706 707 tex = s->texinfo; 708 709 for (i=0 ; i<s->numedges ; i++) 710 { 711 e = loadmodel->surfedges[s->firstedge+i]; 712 if (e >= 0) 713 v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; 714 else 715 v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; 716 717 for (j=0 ; j<2 ; j++) 718 { 719 val = v->position[0] * tex->vecs[j][0] + 720 v->position[1] * tex->vecs[j][1] + 721 v->position[2] * tex->vecs[j][2] + 722 tex->vecs[j][3]; 723 if (val < mins[j]) 724 mins[j] = val; 725 if (val > maxs[j]) 726 maxs[j] = val; 727 } 728 } 729 730 for (i=0 ; i<2 ; i++) 731 { 732 bmins[i] = floor(mins[i]/16); 733 bmaxs[i] = ceil(maxs[i]/16); 734 735 s->texturemins[i] = bmins[i] * 16; 736 s->extents[i] = (bmaxs[i] - bmins[i]) * 16; 737 if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 256) 738 Sys_Error ("Bad surface extents"); 739 } 740} 741 742 743/* 744================= 745Mod_LoadFaces 746================= 747*/ 748void Mod_LoadFaces (lump_t *l) 749{ 750 dface_t *in; 751 msurface_t *out; 752 int i, count, surfnum; 753 int planenum, side; 754 755 in = (void *)(mod_base + l->fileofs); 756 if (l->filelen % sizeof(*in)) 757 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 758 count = l->filelen / sizeof(*in); 759 out = Hunk_AllocName ( count*sizeof(*out), loadname); 760 761 loadmodel->surfaces = out; 762 loadmodel->numsurfaces = count; 763 764 for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) 765 { 766 out->firstedge = LittleLong(in->firstedge); 767 out->numedges = LittleShort(in->numedges); 768 out->flags = 0; 769 770 planenum = LittleShort(in->planenum); 771 side = LittleShort(in->side); 772 if (side) 773 out->flags |= SURF_PLANEBACK; 774 775 out->plane = loadmodel->planes + planenum; 776 777 out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); 778 779 CalcSurfaceExtents (out); 780 781 // lighting info 782 783 for (i=0 ; i<MAXLIGHTMAPS ; i++) 784 out->styles[i] = in->styles[i]; 785 i = LittleLong(in->lightofs); 786 if (i == -1) 787 out->samples = NULL; 788 else 789 out->samples = loadmodel->lightdata + i; 790 791 // set the drawing flags flag 792 793 if (!Q_strncmp(out->texinfo->texture->name,"sky",3)) // sky 794 { 795 out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED); 796 continue; 797 } 798 799 if (!Q_strncmp(out->texinfo->texture->name,"*",1)) // turbulent 800 { 801 out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED); 802 for (i=0 ; i<2 ; i++) 803 { 804 out->extents[i] = 16384; 805 out->texturemins[i] = -8192; 806 } 807 continue; 808 } 809 } 810} 811 812 813/* 814================= 815Mod_SetParent 816================= 817*/ 818void Mod_SetParent (mnode_t *node, mnode_t *parent) 819{ 820 node->parent = parent; 821 if (node->contents < 0) 822 return; 823 Mod_SetParent (node->children[0], node); 824 Mod_SetParent (node->children[1], node); 825} 826 827/* 828================= 829Mod_LoadNodes 830================= 831*/ 832void Mod_LoadNodes (lump_t *l) 833{ 834 int i, j, count, p; 835 dnode_t *in; 836 mnode_t *out; 837 838 in = (void *)(mod_base + l->fileofs); 839 if (l->filelen % sizeof(*in)) 840 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 841 count = l->filelen / sizeof(*in); 842 out = Hunk_AllocName ( count*sizeof(*out), loadname); 843 844 loadmodel->nodes = out; 845 loadmodel->numnodes = count; 846 847 for ( i=0 ; i<count ; i++, in++, out++) 848 { 849 for (j=0 ; j<3 ; j++) 850 { 851 out->minmaxs[j] = LittleShort (in->mins[j]); 852 out->minmaxs[3+j] = LittleShort (in->maxs[j]); 853 } 854 855 p = LittleLong(in->planenum); 856 out->plane = loadmodel->planes + p; 857 858 out->firstsurface = LittleShort (in->firstface); 859 out->numsurfaces = LittleShort (in->numfaces); 860 861 for (j=0 ; j<2 ; j++) 862 { 863 p = LittleShort (in->children[j]); 864 if (p >= 0) 865 out->children[j] = loadmodel->nodes + p; 866 else 867 out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); 868 } 869 } 870 871 Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs 872} 873 874/* 875================= 876Mod_LoadLeafs 877================= 878*/ 879void Mod_LoadLeafs (lump_t *l) 880{ 881 dleaf_t *in; 882 mleaf_t *out; 883 int i, j, count, p; 884 885 in = (void *)(mod_base + l->fileofs); 886 if (l->filelen % sizeof(*in)) 887 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 888 count = l->filelen / sizeof(*in); 889 out = Hunk_AllocName ( count*sizeof(*out), loadname); 890 891 loadmodel->leafs = out; 892 loadmodel->numleafs = count; 893 894 for ( i=0 ; i<count ; i++, in++, out++) 895 { 896 for (j=0 ; j<3 ; j++) 897 { 898 out->minmaxs[j] = LittleShort (in->mins[j]); 899 out->minmaxs[3+j] = LittleShort (in->maxs[j]); 900 } 901 902 p = LittleLong(in->contents); 903 out->contents = p; 904 905 out->firstmarksurface = loadmodel->marksurfaces + 906 LittleShort(in->firstmarksurface); 907 out->nummarksurfaces = LittleShort(in->nummarksurfaces); 908 909 p = LittleLong(in->visofs); 910 if (p == -1) 911 out->compressed_vis = NULL; 912 else 913 out->compressed_vis = loadmodel->visdata + p; 914 out->efrags = NULL; 915 916 for (j=0 ; j<4 ; j++) 917 out->ambient_sound_level[j] = in->ambient_level[j]; 918 } 919} 920 921/* 922================= 923Mod_LoadClipnodes 924================= 925*/ 926void Mod_LoadClipnodes (lump_t *l) 927{ 928 dclipnode_t *in, *out; 929 int i, count; 930 hull_t *hull; 931 932 in = (void *)(mod_base + l->fileofs); 933 if (l->filelen % sizeof(*in)) 934 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 935 count = l->filelen / sizeof(*in); 936 out = Hunk_AllocName ( count*sizeof(*out), loadname); 937 938 loadmodel->clipnodes = out; 939 loadmodel->numclipnodes = count; 940 941 hull = &loadmodel->hulls[1]; 942 hull->clipnodes = out; 943 hull->firstclipnode = 0; 944 hull->lastclipnode = count-1; 945 hull->planes = loadmodel->planes; 946 hull->clip_mins[0] = -16; 947 hull->clip_mins[1] = -16; 948 hull->clip_mins[2] = -24; 949 hull->clip_maxs[0] = 16; 950 hull->clip_maxs[1] = 16; 951 hull->clip_maxs[2] = 32; 952 953 hull = &loadmodel->hulls[2]; 954 hull->clipnodes = out; 955 hull->firstclipnode = 0; 956 hull->lastclipnode = count-1; 957 hull->planes = loadmodel->planes; 958 hull->clip_mins[0] = -32; 959 hull->clip_mins[1] = -32; 960 hull->clip_mins[2] = -24; 961 hull->clip_maxs[0] = 32; 962 hull->clip_maxs[1] = 32; 963 hull->clip_maxs[2] = 64; 964 965 for (i=0 ; i<count ; i++, out++, in++) 966 { 967 out->planenum = LittleLong(in->planenum); 968 out->children[0] = LittleShort(in->children[0]); 969 out->children[1] = LittleShort(in->children[1]); 970 } 971} 972 973/* 974================= 975Mod_MakeHull0 976 977Deplicate the drawing hull structure as a clipping hull 978================= 979*/ 980void Mod_MakeHull0 (void) 981{ 982 mnode_t *in, *child; 983 dclipnode_t *out; 984 int i, j, count; 985 hull_t *hull; 986 987 hull = &loadmodel->hulls[0]; 988 989 in = loadmodel->nodes; 990 count = loadmodel->numnodes; 991 out = Hunk_AllocName ( count*sizeof(*out), loadname); 992 993 hull->clipnodes = out; 994 hull->firstclipnode = 0; 995 hull->lastclipnode = count-1; 996 hull->planes = loadmodel->planes; 997 998 for (i=0 ; i<count ; i++, out++, in++) 999 { 1000 out->planenum = in->plane - loadmodel->planes; 1001 for (j=0 ; j<2 ; j++) 1002 { 1003 child = in->children[j]; 1004 if (child->contents < 0) 1005 out->children[j] = child->contents; 1006 else 1007 out->children[j] = child - loadmodel->nodes; 1008 } 1009 } 1010} 1011 1012/* 1013================= 1014Mod_LoadMarksurfaces 1015================= 1016*/ 1017void Mod_LoadMarksurfaces (lump_t *l) 1018{ 1019 int i, j, count; 1020 short *in; 1021 msurface_t **out; 1022 1023 in = (void *)(mod_base + l->fileofs); 1024 if (l->filelen % sizeof(*in)) 1025 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 1026 count = l->filelen / sizeof(*in); 1027 out = Hunk_AllocName ( count*sizeof(*out), loadname); 1028 1029 loadmodel->marksurfaces = out; 1030 loadmodel->nummarksurfaces = count; 1031 1032 for ( i=0 ; i<count ; i++) 1033 { 1034 j = LittleShort(in[i]); 1035 if (j >= loadmodel->numsurfaces) 1036 Sys_Error ("Mod_ParseMarksurfaces: bad surface number"); 1037 out[i] = loadmodel->surfaces + j; 1038 } 1039} 1040 1041/* 1042================= 1043Mod_LoadSurfedges 1044================= 1045*/ 1046void Mod_LoadSurfedges (lump_t *l) 1047{ 1048 int i, count; 1049 int *in, *out; 1050 1051 in = (void *)(mod_base + l->fileofs); 1052 if (l->filelen % sizeof(*in)) 1053 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 1054 count = l->filelen / sizeof(*in); 1055 out = Hunk_AllocName ( count*sizeof(*out), loadname); 1056 1057 loadmodel->surfedges = out; 1058 loadmodel->numsurfedges = count; 1059 1060 for ( i=0 ; i<count ; i++) 1061 out[i] = LittleLong (in[i]); 1062} 1063 1064/* 1065================= 1066Mod_LoadPlanes 1067================= 1068*/ 1069void Mod_LoadPlanes (lump_t *l) 1070{ 1071 int i, j; 1072 mplane_t *out; 1073 dplane_t *in; 1074 int count; 1075 int bits; 1076 1077 in = (void *)(mod_base + l->fileofs); 1078 if (l->filelen % sizeof(*in)) 1079 Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name); 1080 count = l->filelen / sizeof(*in); 1081 out = Hunk_AllocName ( count*2*sizeof(*out), loadname); 1082 1083 loadmodel->planes = out; 1084 loadmodel->numplanes = count; 1085 1086 for ( i=0 ; i<count ; i++, in++, out++) 1087 { 1088 bits = 0; 1089 for (j=0 ; j<3 ; j++) 1090 { 1091 out->normal[j] = LittleFloat (in->normal[j]); 1092 if (out->normal[j] < 0) 1093 bits |= 1<<j; 1094 } 1095 1096 out->dist = LittleFloat (in->dist); 1097 out->type = LittleLong (in->type); 1098 out->signbits = bits; 1099 } 1100} 1101 1102/* 1103================= 1104RadiusFromBounds 1105================= 1106*/ 1107float RadiusFromBounds (vec3_t mins, vec3_t maxs) 1108{ 1109 int i; 1110 vec3_t corner; 1111 1112 for (i=0 ; i<3 ; i++) 1113 { 1114 corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]); 1115 } 1116 1117 return Length (corner); 1118} 1119 1120/* 1121================= 1122Mod_LoadBrushModel 1123================= 1124*/ 1125void Mod_LoadBrushModel (model_t *mod, void *buffer) 1126{ 1127 int i, j; 1128 dheader_t *header; 1129 dmodel_t *bm; 1130 1131 loadmodel->type = mod_brush; 1132 1133 header = (dheader_t *)buffer; 1134 1135 i = LittleLong (header->version); 1136 if (i != BSPVERSION) 1137 Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); 1138 1139// swap all the lumps 1140 mod_base = (byte *)header; 1141 1142 for (i=0 ; i<sizeof(dheader_t)/4 ; i++) 1143 ((int *)header)[i] = LittleLong ( ((int *)header)[i]); 1144 1145 mod->checksum = 0; 1146 mod->checksum2 = 0; 1147 1148// checksum all of the map, except for entities 1149 for (i = 0; i < HEADER_LUMPS; i++) { 1150 if (i == LUMP_ENTITIES) 1151 continue; 1152 mod->checksum ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 1153 header->lumps[i].filelen); 1154 1155 if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES) 1156 continue; 1157 mod->checksum2 ^= Com_BlockChecksum(mod_base + header->lumps[i].fileofs, 1158 header->lumps[i].filelen); 1159 } 1160 1161// load into heap 1162 1163 Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); 1164 Mod_LoadEdges (&header->lumps[LUMP_EDGES]); 1165 Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); 1166 Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]); 1167 Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); 1168 Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); 1169 Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); 1170 Mod_LoadFaces (&header->lumps[LUMP_FACES]); 1171 Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]); 1172 Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); 1173 Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); 1174 Mod_LoadNodes (&header->lumps[LUMP_NODES]); 1175 Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]); 1176 Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]); 1177 Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); 1178 1179 Mod_MakeHull0 (); 1180 1181 mod->numframes = 2; // regular and alternate animation 1182 1183// 1184// set up the submodels (FIXME: this is confusing) 1185// 1186 for (i=0 ; i<mod->numsubmodels ; i++) 1187 { 1188 bm = &mod->submodels[i]; 1189 1190 mod->hulls[0].firstclipnode = bm->headnode[0]; 1191 for (j=1 ; j<MAX_MAP_HULLS ; j++) 1192 { 1193 mod->hulls[j].firstclipnode = bm->headnode[j]; 1194 mod->hulls[j].lastclipnode = mod->numclipnodes-1; 1195 } 1196 1197 mod->firstmodelsurface = bm->firstface; 1198 mod->nummodelsurfaces = bm->numfaces; 1199 mod->radius = RadiusFromBounds (mod->mins, mod->maxs); 1200 1201 VectorCopy (bm->maxs, mod->maxs); 1202 VectorCopy (bm->mins, mod->mins); 1203 1204 mod->numleafs = bm->visleafs; 1205 1206 if (i < mod->numsubmodels-1) 1207 { // duplicate the basic information 1208 char name[10]; 1209 1210 sprintf (name, "*%i", i+1); 1211 loadmodel = Mod_FindName (name); 1212 *loadmodel = *mod; 1213 strcpy (loadmodel->name, name); 1214 mod = loadmodel; 1215 } 1216 } 1217} 1218 1219/* 1220============================================================================== 1221 1222ALIAS MODELS 1223 1224============================================================================== 1225*/ 1226 1227/* 1228================= 1229Mod_LoadAliasFrame 1230================= 1231*/ 1232void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv, 1233 trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name) 1234{ 1235 trivertx_t *pframe, *pinframe; 1236 int i, j; 1237 daliasframe_t *pdaliasframe; 1238 1239 pdaliasframe = (daliasframe_t *)pin; 1240 1241 strcpy (name, pdaliasframe->name); 1242 1243 for (i=0 ; i<3 ; i++) 1244 { 1245 // these are byte values, so we don't have to worry about 1246 // endianness 1247 pbboxmin->v[i] = pdaliasframe->bboxmin.v[i]; 1248 pbboxmax->v[i] = pdaliasframe->bboxmax.v[i]; 1249 } 1250 1251 pinframe = (trivertx_t *)(pdaliasframe + 1); 1252 pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname); 1253 1254 *pframeindex = (byte *)pframe - (byte *)pheader; 1255 1256 for (j=0 ; j<numv ; j++) 1257 { 1258 int k; 1259 1260 // these are all byte values, so no need to deal with endianness 1261 pframe[j].lightnormalindex = pinframe[j].lightnormalindex; 1262 1263 for (k=0 ; k<3 ; k++) 1264 { 1265 pframe[j].v[k] = pinframe[j].v[k]; 1266 } 1267 } 1268 1269 pinframe += numv; 1270 1271 return (void *)pinframe; 1272} 1273 1274 1275/* 1276================= 1277Mod_LoadAliasGroup 1278================= 1279*/ 1280void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv, 1281 trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name) 1282{ 1283 daliasgroup_t *pingroup; 1284 maliasgroup_t *paliasgroup; 1285 int i, numframes; 1286 daliasinterval_t *pin_intervals; 1287 float *poutintervals; 1288 void *ptemp; 1289 1290 pingroup = (daliasgroup_t *)pin; 1291 1292 numframes = LittleLong (pingroup->numframes); 1293 1294 paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) + 1295 (numframes - 1) * sizeof (paliasgroup->frames[0]), loadname); 1296 1297 paliasgroup->numframes = numframes; 1298 1299 for (i=0 ; i<3 ; i++) 1300 { 1301 // these are byte values, so we don't have to worry about endianness 1302 pbboxmin->v[i] = pingroup->bboxmin.v[i]; 1303 pbboxmax->v[i] = pingroup->bboxmax.v[i]; 1304 } 1305 1306 *pframeindex = (byte *)paliasgroup - (byte *)pheader; 1307 1308 pin_intervals = (daliasinterval_t *)(pingroup + 1); 1309 1310 poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); 1311 1312 paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader; 1313 1314 for (i=0 ; i<numframes ; i++) 1315 { 1316 *poutintervals = LittleFloat (pin_intervals->interval); 1317 if (*poutintervals <= 0.0) 1318 Sys_Error ("Mod_LoadAliasGroup: interval<=0"); 1319 1320 poutintervals++; 1321 pin_intervals++; 1322 } 1323 1324 ptemp = (void *)pin_intervals; 1325 1326 for (i=0 ; i<numframes ; i++) 1327 { 1328 ptemp = Mod_LoadAliasFrame (ptemp, 1329 &paliasgroup->frames[i].frame, 1330 numv, 1331 &paliasgroup->frames[i].bboxmin, 1332 &paliasgroup->frames[i].bboxmax, 1333 pheader, name); 1334 } 1335 1336 return ptemp; 1337} 1338 1339 1340/* 1341================= 1342Mod_LoadAliasSkin 1343================= 1344*/ 1345void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize, 1346 aliashdr_t *pheader) 1347{ 1348 int i; 1349 byte *pskin, *pinskin; 1350 unsigned short *pusskin; 1351 1352 pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname); 1353 pinskin = (byte *)pin; 1354 *pskinindex = (byte *)pskin - (byte *)pheader; 1355 1356 if (r_pixbytes == 1) 1357 { 1358 Q_memcpy (pskin, pinskin, skinsize); 1359 } 1360 else if (r_pixbytes == 2) 1361 { 1362 pusskin = (unsigned short *)pskin; 1363 1364 for (i=0 ; i<skinsize ; i++) 1365 pusskin[i] = d_8to16table[pinskin[i]]; 1366 } 1367 else 1368 { 1369 Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n", 1370 r_pixbytes); 1371 } 1372 1373 pinskin += skinsize; 1374 1375 return ((void *)pinskin); 1376} 1377 1378 1379/* 1380================= 1381Mod_LoadAliasSkinGroup 1382================= 1383*/ 1384void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize, 1385 aliashdr_t *pheader) 1386{ 1387 daliasskingroup_t *pinskingroup; 1388 maliasskingroup_t *paliasskingroup; 1389 int i, numskins; 1390 daliasskininterval_t *pinskinintervals; 1391 float *poutskinintervals; 1392 void *ptemp; 1393 1394 pinskingroup = (daliasskingroup_t *)pin; 1395 1396 numskins = LittleLong (pinskingroup->numskins); 1397 1398 paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) + 1399 (numskins - 1) * sizeof (paliasskingroup->skindescs[0]), 1400 loadname); 1401 1402 paliasskingroup->numskins = numskins; 1403 1404 *pskinindex = (byte *)paliasskingroup - (byte *)pheader; 1405 1406 pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); 1407 1408 poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname); 1409 1410 paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader; 1411 1412 for (i=0 ; i<numskins ; i++) 1413 { 1414 *poutskinintervals = LittleFloat (pinskinintervals->interval); 1415 if (*poutskinintervals <= 0) 1416 Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0"); 1417 1418 poutskinintervals++; 1419 pinskinintervals++; 1420 } 1421 1422 ptemp = (void *)pinskinintervals; 1423 1424 for (i=0 ; i<numskins ; i++) 1425 { 1426 ptemp = Mod_LoadAliasSkin (ptemp, 1427 &paliasskingroup->skindescs[i].skin, skinsize, pheader); 1428 } 1429 1430 return ptemp; 1431} 1432 1433 1434/* 1435================= 1436Mod_LoadAliasModel 1437================= 1438*/ 1439void Mod_LoadAliasModel (model_t *mod, void *buffer) 1440{ 1441 int i; 1442 mdl_t *pmodel, *pinmodel; 1443 stvert_t *pstverts, *pinstverts; 1444 aliashdr_t *pheader; 1445 mtriangle_t *ptri; 1446 dtriangle_t *pintriangles; 1447 int version, numframes, numskins; 1448 int size; 1449 daliasframetype_t *pframetype; 1450 daliasskintype_t *pskintype; 1451 maliasskindesc_t *pskindesc; 1452 int skinsize; 1453 int start, end, total; 1454 1455 if (!strcmp(loadmodel->name, "progs/player.mdl") || 1456 !strcmp(loadmodel->name, "progs/eyes.mdl")) { 1457 unsigned short crc; 1458 byte *p; 1459 int len; 1460 char st[40]; 1461 1462 CRC_Init(&crc); 1463 for (len = com_filesize, p = buffer; len; len--, p++) 1464 CRC_ProcessByte(&crc, *p); 1465 1466 sprintf(st, "%d", (int) crc); 1467 Info_SetValueForKey (cls.userinfo, 1468 !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, 1469 st, MAX_INFO_STRING); 1470 1471 if (cls.state >= ca_connected) { 1472 MSG_WriteByte (&cls.netchan.message, clc_stringcmd); 1473 sprintf(st, "setinfo %s %d", 1474 !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, 1475 (int)crc); 1476 SZ_Print (&cls.netchan.message, st); 1477 } 1478 } 1479 1480 start = Hunk_LowMark (); 1481 1482 pinmodel = (mdl_t *)buffer; 1483 1484 version = LittleLong (pinmodel->version); 1485 if (version != ALIAS_VERSION) 1486 Sys_Error ("%s has wrong version number (%i should be %i)", 1487 mod->name, version, ALIAS_VERSION); 1488 1489// 1490// allocate space for a working header, plus all the data except the frames, 1491// skin and group info 1492// 1493 size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) * 1494 sizeof (pheader->frames[0]) + 1495 sizeof (mdl_t) + 1496 LittleLong (pinmodel->numverts) * sizeof (stvert_t) + 1497 LittleLong (pinmodel->numtris) * sizeof (mtriangle_t); 1498 1499 pheader = Hunk_AllocName (size, loadname); 1500 pmodel = (mdl_t *) ((byte *)&pheader[1] + 1501 (LittleLong (pinmodel->numframes) - 1) * 1502 sizeof (pheader->frames[0])); 1503 1504// mod->cache.data = pheader; 1505 mod->flags = LittleLong (pinmodel->flags); 1506 1507// 1508// endian-adjust and copy the data, starting with the alias model header 1509// 1510 pmodel->boundingradius = LittleFloat (pinmodel->boundingradius); 1511 pmodel->numskins = LittleLong (pinmodel->numskins); 1512 pmodel->skinwidth = LittleLong (pinmodel->skinwidth); 1513 pmodel->skinheight = LittleLong (pinmodel->skinheight); 1514 1515 if (pmodel->skinheight > MAX_LBM_HEIGHT) 1516 Sys_Error ("model %s has a skin taller than %d", mod->name, 1517 MAX_LBM_HEIGHT); 1518 1519 pmodel->numverts = LittleLong (pinmodel->numverts); 1520 1521 if (pmodel->numverts <= 0) 1522 Sys_Error ("model %s has no vertices", mod->name); 1523 1524 if (pmodel->numverts > MAXALIASVERTS) 1525 Sys_Error ("model %s has too many vertices", mod->name); 1526 1527 pmodel->numtris = LittleLong (pinmodel->numtris); 1528 1529 if (pmodel->numtris <= 0) 1530 Sys_Error ("model %s has no triangles", mod->name); 1531 1532 pmodel->numframes = LittleLong (pinmodel->numframes); 1533 pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; 1534 mod->synctype = LittleLong (pinmodel->synctype); 1535 mod->numframes = pmodel->numframes; 1536 1537 for (i=0 ; i<3 ; i++) 1538 { 1539 pmodel->scale[i] = LittleFloat (pinmodel->scale[i]); 1540 pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); 1541 pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); 1542 } 1543 1544 numskins = pmodel->numskins; 1545 numframes = pmodel->numframes; 1546 1547 if (pmodel->skinwidth & 0x03) 1548 Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4"); 1549 1550 pheader->model = (byte *)pmodel - (byte *)pheader; 1551 1552// 1553// load the skins 1554// 1555 skinsize = pmodel->skinheight * pmodel->skinwidth; 1556 1557 if (numskins < 1) 1558 Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); 1559 1560 pskintype = (daliasskintype_t *)&pinmodel[1]; 1561 1562 pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), 1563 loadname); 1564 1565 pheader->skindesc = (byte *)pskindesc - (byte *)pheader; 1566 1567 for (i=0 ; i<numskins ; i++) 1568 { 1569 aliasskintype_t skintype; 1570 1571 skintype = LittleLong (pskintype->type); 1572 pskindesc[i].type = skintype; 1573 1574 if (skintype == ALIAS_SKIN_SINGLE) 1575 { 1576 pskintype = (daliasskintype_t *) 1577 Mod_LoadAliasSkin (pskintype + 1, 1578 &pskindesc[i].skin, 1579 skinsize, pheader); 1580 } 1581 else 1582 { 1583 pskintype = (daliasskintype_t *) 1584 Mod_LoadAliasSkinGroup (pskintype + 1, 1585 &pskindesc[i].skin, 1586 skinsize, pheader); 1587 } 1588 } 1589 1590// 1591// set base s and t vertices 1592// 1593 pstverts = (stvert_t *)&pmodel[1]; 1594 pinstverts = (stvert_t *)pskintype; 1595 1596 pheader->stverts = (byte *)pstverts - (byte *)pheader; 1597 1598 for (i=0 ; i<pmodel->numverts ; i++) 1599 { 1600 pstverts[i].onseam = LittleLong (pinstverts[i].onseam); 1601 // put s and t in 16.16 format 1602 pstverts[i].s = LittleLong (pinstverts[i].s) << 16; 1603 pstverts[i].t = LittleLong (pinstverts[i].t) << 16; 1604 } 1605 1606// 1607// set up the triangles 1608// 1609 ptri = (mtriangle_t *)&pstverts[pmodel->numverts]; 1610 pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts]; 1611 1612 pheader->triangles = (byte *)ptri - (byte *)pheader; 1613 1614 for (i=0 ; i<pmodel->numtris ; i++) 1615 { 1616 int j; 1617 1618 ptri[i].facesfront = LittleLong (pintriangles[i].facesfront); 1619 1620 for (j=0 ; j<3 ; j++) 1621 { 1622 ptri[i].vertindex[j] = 1623 LittleLong (pintriangles[i].vertindex[j]); 1624 } 1625 } 1626 1627// 1628// load the frames 1629// 1630 if (numframes < 1) 1631 Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); 1632 1633 pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris]; 1634 1635 for (i=0 ; i<numframes ; i++) 1636 { 1637 aliasframetype_t frametype; 1638 1639 frametype = LittleLong (pframetype->type); 1640 pheader->frames[i].type = frametype; 1641 1642 1643 if (frametype == ALIAS_SINGLE) 1644 { 1645 pframetype = (daliasframetype_t *) 1646 Mod_LoadAliasFrame (pframetype + 1, 1647 &pheader->frames[i].frame, 1648 pmodel->numverts, 1649 &pheader->frames[i].bboxmin, 1650 &pheader->frames[i].bboxmax, 1651 pheader, pheader->frames[i].name); 1652 } 1653 else 1654 { 1655 pframetype = (daliasframetype_t *) 1656 Mod_LoadAliasGroup (pframetype + 1, 1657 &pheader->frames[i].frame, 1658 pmodel->numverts, 1659 &pheader->frames[i].bboxmin, 1660 &pheader->frames[i].bboxmax, 1661 pheader, pheader->frames[i].name); 1662 } 1663 } 1664 1665 mod->type = mod_alias; 1666 1667// FIXME: do this right 1668 mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; 1669 mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; 1670 1671// 1672// move the complete, relocatable alias model to the cache 1673// 1674 end = Hunk_LowMark (); 1675 total = end - start; 1676 1677 Cache_Alloc (&mod->cache, total, loadname); 1678 if (!mod->cache.data) 1679 return; 1680 memcpy (mod->cache.data, pheader, total); 1681 1682 Hunk_FreeToLowMark (start); 1683} 1684 1685//============================================================================= 1686 1687/* 1688================= 1689Mod_LoadSpriteFrame 1690================= 1691*/ 1692void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe) 1693{ 1694 dspriteframe_t *pinframe; 1695 mspriteframe_t *pspriteframe; 1696 int i, width, height, size, origin[2]; 1697 unsigned short *ppixout; 1698 byte *ppixin; 1699 1700 pinframe = (dspriteframe_t *)pin; 1701 1702 width = LittleLong (pinframe->width); 1703 height = LittleLong (pinframe->height); 1704 size = width * height; 1705 1706 pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes, 1707 loadname); 1708 1709 Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); 1710 *ppframe = pspriteframe; 1711 1712 pspriteframe->width = width; 1713 pspriteframe->height = height; 1714 origin[0] = LittleLong (pinframe->origin[0]); 1715 origin[1] = LittleLong (pinframe->origin[1]); 1716 1717 pspriteframe->up = origin[1]; 1718 pspriteframe->down = origin[1] - height; 1719 pspriteframe->left = origin[0]; 1720 pspriteframe->right = width + origin[0]; 1721 1722 if (r_pixbytes == 1) 1723 { 1724 Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size); 1725 } 1726 else if (r_pixbytes == 2) 1727 { 1728 ppixin = (byte *)(pinframe + 1); 1729 ppixout = (unsigned short *)&pspriteframe->pixels[0]; 1730 1731 for (i=0 ; i<size ; i++) 1732 ppixout[i] = d_8to16table[ppixin[i]]; 1733 } 1734 else 1735 { 1736 Sys_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n", 1737 r_pixbytes); 1738 } 1739 1740 return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size); 1741} 1742 1743 1744/* 1745================= 1746Mod_LoadSpriteGroup 1747================= 1748*/ 1749void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe) 1750{ 1751 dspritegroup_t *pingroup; 1752 mspritegroup_t *pspritegroup; 1753 int i, numframes; 1754 dspriteinterval_t *pin_intervals; 1755 float *poutintervals; 1756 void *ptemp; 1757 1758 pingroup = (dspritegroup_t *)pin; 1759 1760 numframes = LittleLong (pingroup->numframes); 1761 1762 pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + 1763 (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname); 1764 1765 pspritegroup->numframes = numframes; 1766 1767 *ppframe = (mspriteframe_t *)pspritegroup; 1768 1769 pin_intervals = (dspriteinterval_t *)(pingroup + 1); 1770 1771 poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); 1772 1773 pspritegroup->intervals = poutintervals; 1774 1775 for (i=0 ; i<numframes ; i++) 1776 { 1777 *poutintervals = LittleFloat (pin_intervals->interval); 1778 if (*poutintervals <= 0.0) 1779 Sys_Error ("Mod_LoadSpriteGroup: interval<=0"); 1780 1781 poutintervals++; 1782 pin_intervals++; 1783 } 1784 1785 ptemp = (void *)pin_intervals; 1786 1787 for (i=0 ; i<numframes ; i++) 1788 { 1789 ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i]); 1790 } 1791 1792 return ptemp; 1793} 1794 1795 1796/* 1797================= 1798Mod_LoadSpriteModel 1799================= 1800*/ 1801void Mod_LoadSpriteModel (model_t *mod, void *buffer) 1802{ 1803 int i; 1804 int version; 1805 dsprite_t *pin; 1806 msprite_t *psprite; 1807 int numframes; 1808 int size; 1809 dspriteframetype_t *pframetype; 1810 1811 pin = (dsprite_t *)buffer; 1812 1813 version = LittleLong (pin->version); 1814 if (version != SPRITE_VERSION) 1815 Sys_Error ("%s has wrong version number " 1816 "(%i should be %i)", mod->name, version, SPRITE_VERSION); 1817 1818 numframes = LittleLong (pin->numframes); 1819 1820 size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); 1821 1822 psprite = Hunk_AllocName (size, loadname); 1823 1824 mod->cache.data = psprite; 1825 1826 psprite->type = LittleLong (pin->type); 1827 psprite->maxwidth = LittleLong (pin->width); 1828 psprite->maxheight = LittleLong (pin->height); 1829 psprite->beamlength = LittleFloat (pin->beamlength); 1830 mod->synctype = LittleLong (pin->synctype); 1831 psprite->numframes = numframes; 1832 1833 mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; 1834 mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; 1835 mod->mins[2] = -psprite->maxheight/2; 1836 mod->maxs[2] = psprite->maxheight/2; 1837 1838// 1839// load the frames 1840// 1841 if (numframes < 1) 1842 Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes); 1843 1844 mod->numframes = numframes; 1845 1846 pframetype = (dspriteframetype_t *)(pin + 1); 1847 1848 for (i=0 ; i<numframes ; i++) 1849 { 1850 spriteframetype_t frametype; 1851 1852 frametype = LittleLong (pframetype->type); 1853 psprite->frames[i].type = frametype; 1854 1855 if (frametype == SPR_SINGLE) 1856 { 1857 pframetype = (dspriteframetype_t *) 1858 Mod_LoadSpriteFrame (pframetype + 1, 1859 &psprite->frames[i].frameptr); 1860 } 1861 else 1862 { 1863 pframetype = (dspriteframetype_t *) 1864 Mod_LoadSpriteGroup (pframetype + 1, 1865 &psprite->frames[i].frameptr); 1866 } 1867 } 1868 1869 mod->type = mod_sprite; 1870} 1871 1872//============================================================================= 1873 1874/* 1875================ 1876Mod_Print 1877================ 1878*/ 1879void Mod_Print (void) 1880{ 1881 int i; 1882 model_t *mod; 1883 1884 Con_Printf ("Cached models:\n"); 1885 for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) 1886 { 1887 Con_Printf ("%8p : %s\n",mod->cache.data, mod->name); 1888 } 1889} 1890 1891 1892