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