|
|
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 "quakedef.h" ! 26: #include "r_local.h" ! 27: ! 28: model_t *loadmodel; ! 29: char loadname[32]; // for hunk tags ! 30: ! 31: void Mod_LoadSpriteModel (model_t *mod, void *buffer); ! 32: void Mod_LoadBrushModel (model_t *mod, void *buffer); ! 33: void Mod_LoadAliasModel (model_t *mod, void *buffer); ! 34: model_t *Mod_LoadModel (model_t *mod, qboolean crash); ! 35: ! 36: byte mod_novis[MAX_MAP_LEAFS/8]; ! 37: ! 38: #define MAX_MOD_KNOWN 256 ! 39: model_t mod_known[MAX_MOD_KNOWN]; ! 40: int mod_numknown; ! 41: ! 42: /* ! 43: =============== ! 44: Mod_Init ! 45: =============== ! 46: */ ! 47: void Mod_Init (void) ! 48: { ! 49: memset (mod_novis, 0xff, sizeof(mod_novis)); ! 50: } ! 51: ! 52: /* ! 53: =============== ! 54: Mod_Init ! 55: ! 56: Caches the data if needed ! 57: =============== ! 58: */ ! 59: void *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: =============== ! 76: Mod_PointInLeaf ! 77: =============== ! 78: */ ! 79: mleaf_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: =================== ! 107: Mod_DecompressVis ! 108: =================== ! 109: */ ! 110: byte *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: ! 154: byte *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: =================== ! 163: Mod_ClearAll ! 164: =================== ! 165: */ ! 166: void 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: ================== ! 178: Mod_FindName ! 179: ! 180: ================== ! 181: */ ! 182: model_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: ================== ! 211: Mod_TouchModel ! 212: ! 213: ================== ! 214: */ ! 215: void 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: ================== ! 230: Mod_LoadModel ! 231: ! 232: Loads a model into the cache ! 233: ================== ! 234: */ ! 235: model_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: ================== ! 306: Mod_ForName ! 307: ! 308: Loads in a model for the given name ! 309: ================== ! 310: */ ! 311: model_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: ! 329: byte *mod_base; ! 330: ! 331: ! 332: /* ! 333: ================= ! 334: Mod_LoadTextures ! 335: ================= ! 336: */ ! 337: void 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: ================= ! 483: Mod_LoadLighting ! 484: ================= ! 485: */ ! 486: void 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: ================= ! 500: Mod_LoadVisibility ! 501: ================= ! 502: */ ! 503: void 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: ================= ! 517: Mod_LoadEntities ! 518: ================= ! 519: */ ! 520: void 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: ================= ! 534: Mod_LoadVertexes ! 535: ================= ! 536: */ ! 537: void 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: ================= ! 562: Mod_LoadSubmodels ! 563: ================= ! 564: */ ! 565: void 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: ================= ! 598: Mod_LoadEdges ! 599: ================= ! 600: */ ! 601: void 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: ================= ! 625: Mod_LoadTexinfo ! 626: ================= ! 627: */ ! 628: void 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: ================ ! 691: CalcSurfaceExtents ! 692: ! 693: Fills in s->texturemins[] and s->extents[] ! 694: ================ ! 695: */ ! 696: void 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: ================= ! 745: Mod_LoadFaces ! 746: ================= ! 747: */ ! 748: void 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: ================= ! 815: Mod_SetParent ! 816: ================= ! 817: */ ! 818: void 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: ================= ! 829: Mod_LoadNodes ! 830: ================= ! 831: */ ! 832: void 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: ================= ! 876: Mod_LoadLeafs ! 877: ================= ! 878: */ ! 879: void 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: ================= ! 923: Mod_LoadClipnodes ! 924: ================= ! 925: */ ! 926: void 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: ================= ! 975: Mod_MakeHull0 ! 976: ! 977: Deplicate the drawing hull structure as a clipping hull ! 978: ================= ! 979: */ ! 980: void 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: ================= ! 1014: Mod_LoadMarksurfaces ! 1015: ================= ! 1016: */ ! 1017: void 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: ================= ! 1043: Mod_LoadSurfedges ! 1044: ================= ! 1045: */ ! 1046: void 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: ================= ! 1066: Mod_LoadPlanes ! 1067: ================= ! 1068: */ ! 1069: void 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: ================= ! 1104: RadiusFromBounds ! 1105: ================= ! 1106: */ ! 1107: float 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: ================= ! 1122: Mod_LoadBrushModel ! 1123: ================= ! 1124: */ ! 1125: void 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: ! 1222: ALIAS MODELS ! 1223: ! 1224: ============================================================================== ! 1225: */ ! 1226: ! 1227: /* ! 1228: ================= ! 1229: Mod_LoadAliasFrame ! 1230: ================= ! 1231: */ ! 1232: void * 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: ================= ! 1277: Mod_LoadAliasGroup ! 1278: ================= ! 1279: */ ! 1280: void * 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: ================= ! 1342: Mod_LoadAliasSkin ! 1343: ================= ! 1344: */ ! 1345: void * 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: ================= ! 1381: Mod_LoadAliasSkinGroup ! 1382: ================= ! 1383: */ ! 1384: void * 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: ================= ! 1436: Mod_LoadAliasModel ! 1437: ================= ! 1438: */ ! 1439: void 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: ================= ! 1689: Mod_LoadSpriteFrame ! 1690: ================= ! 1691: */ ! 1692: void * 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: ================= ! 1746: Mod_LoadSpriteGroup ! 1747: ================= ! 1748: */ ! 1749: void * 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: ================= ! 1798: Mod_LoadSpriteModel ! 1799: ================= ! 1800: */ ! 1801: void 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: ================ ! 1876: Mod_Print ! 1877: ================ ! 1878: */ ! 1879: void 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.