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