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