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