|
|
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 "r_local.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 256 ! 19: model_t mod_known[MAX_MOD_KNOWN]; ! 20: int mod_numknown; ! 21: ! 22: // the inline * models from the current map are kept seperate ! 23: model_t mod_inline[MAX_MOD_KNOWN]; ! 24: ! 25: int registration_sequence; ! 26: int modfilelen; ! 27: ! 28: //=============================================================================== ! 29: ! 30: ! 31: /* ! 32: ================ ! 33: Mod_Modellist_f ! 34: ================ ! 35: */ ! 36: void Mod_Modellist_f (void) ! 37: { ! 38: int i; ! 39: model_t *mod; ! 40: int total; ! 41: ! 42: total = 0; ! 43: ri.Con_Printf (PRINT_ALL,"Loaded models:\n"); ! 44: for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) ! 45: { ! 46: if (!mod->name[0]) ! 47: continue; ! 48: ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name); ! 49: total += mod->extradatasize; ! 50: } ! 51: ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total); ! 52: } ! 53: ! 54: /* ! 55: =============== ! 56: Mod_Init ! 57: =============== ! 58: */ ! 59: void Mod_Init (void) ! 60: { ! 61: memset (mod_novis, 0xff, sizeof(mod_novis)); ! 62: } ! 63: ! 64: /* ! 65: ================== ! 66: Mod_ForName ! 67: ! 68: Loads in a model for the given name ! 69: ================== ! 70: */ ! 71: model_t *Mod_ForName (char *name, qboolean crash) ! 72: { ! 73: model_t *mod; ! 74: unsigned *buf; ! 75: int i; ! 76: ! 77: if (!name[0]) ! 78: ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name"); ! 79: ! 80: // ! 81: // inline models are grabbed only from worldmodel ! 82: // ! 83: if (name[0] == '*') ! 84: { ! 85: i = atoi(name+1); ! 86: if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) ! 87: ri.Sys_Error (ERR_DROP, "bad inline model number"); ! 88: return &mod_inline[i]; ! 89: } ! 90: ! 91: // ! 92: // search the currently loaded models ! 93: // ! 94: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) ! 95: if (!strcmp (mod->name, name) ) ! 96: return mod; ! 97: ! 98: // ! 99: // find a free model slot spot ! 100: // ! 101: for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) ! 102: { ! 103: if (!mod->name[0]) ! 104: break; // free spot ! 105: } ! 106: if (i == mod_numknown) ! 107: { ! 108: if (mod_numknown == MAX_MOD_KNOWN) ! 109: ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); ! 110: mod_numknown++; ! 111: } ! 112: strcpy (mod->name, name); ! 113: ! 114: // ! 115: // load the file ! 116: // ! 117: modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf); ! 118: if (!buf) ! 119: { ! 120: if (crash) ! 121: ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name); ! 122: memset (mod->name, 0, sizeof(mod->name)); ! 123: return NULL; ! 124: } ! 125: ! 126: loadmodel = mod; ! 127: ! 128: // ! 129: // fill it in ! 130: // ! 131: ! 132: // call the apropriate loader ! 133: ! 134: switch (LittleLong(*(unsigned *)buf)) ! 135: { ! 136: case IDALIASHEADER: ! 137: loadmodel->extradata = Hunk_Begin (0x200000); ! 138: Mod_LoadAliasModel (mod, buf); ! 139: break; ! 140: ! 141: case IDSPRITEHEADER: ! 142: loadmodel->extradata = Hunk_Begin (0x10000); ! 143: Mod_LoadSpriteModel (mod, buf); ! 144: break; ! 145: ! 146: case IDBSPHEADER: ! 147: loadmodel->extradata = Hunk_Begin (0x1000000); ! 148: Mod_LoadBrushModel (mod, buf); ! 149: break; ! 150: ! 151: default: ! 152: ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name); ! 153: break; ! 154: } ! 155: ! 156: loadmodel->extradatasize = Hunk_End (); ! 157: ! 158: ri.FS_FreeFile (buf); ! 159: ! 160: return mod; ! 161: } ! 162: ! 163: ! 164: /* ! 165: =============== ! 166: Mod_PointInLeaf ! 167: =============== ! 168: */ ! 169: mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) ! 170: { ! 171: mnode_t *node; ! 172: float d; ! 173: mplane_t *plane; ! 174: ! 175: if (!model || !model->nodes) ! 176: ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model"); ! 177: ! 178: node = model->nodes; ! 179: while (1) ! 180: { ! 181: if (node->contents != -1) ! 182: return (mleaf_t *)node; ! 183: plane = node->plane; ! 184: d = DotProduct (p,plane->normal) - plane->dist; ! 185: if (d > 0) ! 186: node = node->children[0]; ! 187: else ! 188: node = node->children[1]; ! 189: } ! 190: ! 191: return NULL; // never reached ! 192: } ! 193: ! 194: ! 195: /* ! 196: =================== ! 197: Mod_DecompressVis ! 198: =================== ! 199: */ ! 200: byte *Mod_DecompressVis (byte *in, model_t *model) ! 201: { ! 202: static byte decompressed[MAX_MAP_LEAFS/8]; ! 203: int c; ! 204: byte *out; ! 205: int row; ! 206: ! 207: row = (model->vis->numclusters+7)>>3; ! 208: out = decompressed; ! 209: ! 210: #if 0 ! 211: memcpy (out, in, row); ! 212: #else ! 213: if (!in) ! 214: { // no vis info, so make all visible ! 215: while (row) ! 216: { ! 217: *out++ = 0xff; ! 218: row--; ! 219: } ! 220: return decompressed; ! 221: } ! 222: ! 223: do ! 224: { ! 225: if (*in) ! 226: { ! 227: *out++ = *in++; ! 228: continue; ! 229: } ! 230: ! 231: c = in[1]; ! 232: in += 2; ! 233: while (c) ! 234: { ! 235: *out++ = 0; ! 236: c--; ! 237: } ! 238: } while (out - decompressed < row); ! 239: #endif ! 240: ! 241: return decompressed; ! 242: } ! 243: ! 244: /* ! 245: ============== ! 246: Mod_ClusterPVS ! 247: ============== ! 248: */ ! 249: byte *Mod_ClusterPVS (int cluster, model_t *model) ! 250: { ! 251: if (cluster == -1 || !model->vis) ! 252: return mod_novis; ! 253: return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS], ! 254: model); ! 255: } ! 256: ! 257: /* ! 258: =============================================================================== ! 259: ! 260: BRUSHMODEL LOADING ! 261: ! 262: =============================================================================== ! 263: */ ! 264: ! 265: byte *mod_base; ! 266: ! 267: ! 268: /* ! 269: ================= ! 270: Mod_LoadLighting ! 271: ! 272: Converts the 24 bit lighting down to 8 bit ! 273: by taking the brightest component ! 274: ================= ! 275: */ ! 276: void Mod_LoadLighting (lump_t *l) ! 277: { ! 278: int i, size; ! 279: byte *in; ! 280: ! 281: if (!l->filelen) ! 282: { ! 283: loadmodel->lightdata = NULL; ! 284: return; ! 285: } ! 286: size = l->filelen/3; ! 287: loadmodel->lightdata = Hunk_Alloc (size); ! 288: in = (void *)(mod_base + l->fileofs); ! 289: for (i=0 ; i<size ; i++, in+=3) ! 290: { ! 291: if (in[0] > in[1] && in[0] > in[2]) ! 292: loadmodel->lightdata[i] = in[0]; ! 293: else if (in[1] > in[0] && in[1] > in[2]) ! 294: loadmodel->lightdata[i] = in[1]; ! 295: else ! 296: loadmodel->lightdata[i] = in[2]; ! 297: } ! 298: } ! 299: ! 300: ! 301: int r_leaftovis[MAX_MAP_LEAFS]; ! 302: int r_vistoleaf[MAX_MAP_LEAFS]; ! 303: int r_numvisleafs; ! 304: ! 305: void R_NumberLeafs (mnode_t *node) ! 306: { ! 307: mleaf_t *leaf; ! 308: int leafnum; ! 309: ! 310: if (node->contents != -1) ! 311: { ! 312: leaf = (mleaf_t *)node; ! 313: leafnum = leaf - loadmodel->leafs; ! 314: if (leaf->contents & CONTENTS_SOLID) ! 315: return; ! 316: r_leaftovis[leafnum] = r_numvisleafs; ! 317: r_vistoleaf[r_numvisleafs] = leafnum; ! 318: r_numvisleafs++; ! 319: return; ! 320: } ! 321: ! 322: R_NumberLeafs (node->children[0]); ! 323: R_NumberLeafs (node->children[1]); ! 324: } ! 325: ! 326: ! 327: /* ! 328: ================= ! 329: Mod_LoadVisibility ! 330: ================= ! 331: */ ! 332: void Mod_LoadVisibility (lump_t *l) ! 333: { ! 334: int i; ! 335: ! 336: if (!l->filelen) ! 337: { ! 338: loadmodel->vis = NULL; ! 339: return; ! 340: } ! 341: loadmodel->vis = Hunk_Alloc ( l->filelen); ! 342: memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen); ! 343: ! 344: loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters); ! 345: for (i=0 ; i<loadmodel->vis->numclusters ; i++) ! 346: { ! 347: loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]); ! 348: loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]); ! 349: } ! 350: } ! 351: ! 352: ! 353: /* ! 354: ================= ! 355: Mod_LoadVertexes ! 356: ================= ! 357: */ ! 358: void Mod_LoadVertexes (lump_t *l) ! 359: { ! 360: dvertex_t *in; ! 361: mvertex_t *out; ! 362: int i, count; ! 363: ! 364: in = (void *)(mod_base + l->fileofs); ! 365: if (l->filelen % sizeof(*in)) ! 366: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 367: count = l->filelen / sizeof(*in); ! 368: out = Hunk_Alloc ( (count+8)*sizeof(*out)); // extra for skybox ! 369: ! 370: loadmodel->vertexes = out; ! 371: loadmodel->numvertexes = count; ! 372: ! 373: for ( i=0 ; i<count ; i++, in++, out++) ! 374: { ! 375: out->position[0] = LittleFloat (in->point[0]); ! 376: out->position[1] = LittleFloat (in->point[1]); ! 377: out->position[2] = LittleFloat (in->point[2]); ! 378: } ! 379: } ! 380: ! 381: /* ! 382: ================= ! 383: Mod_LoadSubmodels ! 384: ================= ! 385: */ ! 386: void Mod_LoadSubmodels (lump_t *l) ! 387: { ! 388: dmodel_t *in; ! 389: dmodel_t *out; ! 390: int i, j, count; ! 391: ! 392: in = (void *)(mod_base + l->fileofs); ! 393: if (l->filelen % sizeof(*in)) ! 394: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 395: count = l->filelen / sizeof(*in); ! 396: out = Hunk_Alloc ( count*sizeof(*out)); ! 397: ! 398: loadmodel->submodels = out; ! 399: loadmodel->numsubmodels = count; ! 400: ! 401: for ( i=0 ; i<count ; i++, in++, out++) ! 402: { ! 403: for (j=0 ; j<3 ; j++) ! 404: { // spread the mins / maxs by a pixel ! 405: out->mins[j] = LittleFloat (in->mins[j]) - 1; ! 406: out->maxs[j] = LittleFloat (in->maxs[j]) + 1; ! 407: out->origin[j] = LittleFloat (in->origin[j]); ! 408: } ! 409: out->headnode = LittleLong (in->headnode); ! 410: out->firstface = LittleLong (in->firstface); ! 411: out->numfaces = LittleLong (in->numfaces); ! 412: } ! 413: } ! 414: ! 415: /* ! 416: ================= ! 417: Mod_LoadEdges ! 418: ================= ! 419: */ ! 420: void Mod_LoadEdges (lump_t *l) ! 421: { ! 422: dedge_t *in; ! 423: medge_t *out; ! 424: int i, count; ! 425: ! 426: in = (void *)(mod_base + l->fileofs); ! 427: if (l->filelen % sizeof(*in)) ! 428: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 429: count = l->filelen / sizeof(*in); ! 430: out = Hunk_Alloc ( (count + 13) * sizeof(*out)); // extra for skybox ! 431: ! 432: loadmodel->edges = out; ! 433: loadmodel->numedges = count; ! 434: ! 435: for ( i=0 ; i<count ; i++, in++, out++) ! 436: { ! 437: out->v[0] = (unsigned short)LittleShort(in->v[0]); ! 438: out->v[1] = (unsigned short)LittleShort(in->v[1]); ! 439: } ! 440: } ! 441: ! 442: /* ! 443: ================= ! 444: Mod_LoadTexinfo ! 445: ================= ! 446: */ ! 447: void Mod_LoadTexinfo (lump_t *l) ! 448: { ! 449: texinfo_t *in; ! 450: mtexinfo_t *out, *step; ! 451: int i, j, count; ! 452: float len1, len2; ! 453: char name[MAX_QPATH]; ! 454: int next; ! 455: ! 456: in = (void *)(mod_base + l->fileofs); ! 457: if (l->filelen % sizeof(*in)) ! 458: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 459: count = l->filelen / sizeof(*in); ! 460: out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox ! 461: ! 462: loadmodel->texinfo = out; ! 463: loadmodel->numtexinfo = count; ! 464: ! 465: for ( i=0 ; i<count ; i++, in++, out++) ! 466: { ! 467: for (j=0 ; j<8 ; j++) ! 468: out->vecs[0][j] = LittleFloat (in->vecs[0][j]); ! 469: len1 = VectorLength (out->vecs[0]); ! 470: len2 = VectorLength (out->vecs[1]); ! 471: len1 = (len1 + len2)/2; ! 472: if (len1 < 0.32) ! 473: out->mipadjust = 4; ! 474: else if (len1 < 0.49) ! 475: out->mipadjust = 3; ! 476: else if (len1 < 0.99) ! 477: out->mipadjust = 2; ! 478: else ! 479: out->mipadjust = 1; ! 480: #if 0 ! 481: if (len1 + len2 < 0.001) ! 482: out->mipadjust = 1; // don't crash ! 483: else ! 484: out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); ! 485: #endif ! 486: ! 487: out->flags = LittleLong (in->flags); ! 488: ! 489: next = LittleLong (in->nexttexinfo); ! 490: if (next > 0) ! 491: out->next = loadmodel->texinfo + next; ! 492: ! 493: Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); ! 494: out->image = R_FindImage (name, it_wall); ! 495: if (!out->image) ! 496: { ! 497: out->image = r_notexture_mip; // texture not found ! 498: out->flags = 0; ! 499: } ! 500: } ! 501: ! 502: // count animation frames ! 503: for (i=0 ; i<count ; i++) ! 504: { ! 505: out = &loadmodel->texinfo[i]; ! 506: out->numframes = 1; ! 507: for (step = out->next ; step && step != out ; step=step->next) ! 508: out->numframes++; ! 509: } ! 510: } ! 511: ! 512: /* ! 513: ================ ! 514: CalcSurfaceExtents ! 515: ! 516: Fills in s->texturemins[] and s->extents[] ! 517: ================ ! 518: */ ! 519: void CalcSurfaceExtents (msurface_t *s) ! 520: { ! 521: float mins[2], maxs[2], val; ! 522: int i,j, e; ! 523: mvertex_t *v; ! 524: mtexinfo_t *tex; ! 525: int bmins[2], bmaxs[2]; ! 526: ! 527: mins[0] = mins[1] = 999999; ! 528: maxs[0] = maxs[1] = -99999; ! 529: ! 530: tex = s->texinfo; ! 531: ! 532: for (i=0 ; i<s->numedges ; i++) ! 533: { ! 534: e = loadmodel->surfedges[s->firstedge+i]; ! 535: if (e >= 0) ! 536: v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; ! 537: else ! 538: v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; ! 539: ! 540: for (j=0 ; j<2 ; j++) ! 541: { ! 542: val = v->position[0] * tex->vecs[j][0] + ! 543: v->position[1] * tex->vecs[j][1] + ! 544: v->position[2] * tex->vecs[j][2] + ! 545: tex->vecs[j][3]; ! 546: if (val < mins[j]) ! 547: mins[j] = val; ! 548: if (val > maxs[j]) ! 549: maxs[j] = val; ! 550: } ! 551: } ! 552: ! 553: for (i=0 ; i<2 ; i++) ! 554: { ! 555: bmins[i] = floor(mins[i]/16); ! 556: bmaxs[i] = ceil(maxs[i]/16); ! 557: ! 558: s->texturemins[i] = bmins[i] * 16; ! 559: s->extents[i] = (bmaxs[i] - bmins[i]) * 16; ! 560: if (s->extents[i] < 16) ! 561: s->extents[i] = 16; // take at least one cache block ! 562: if ( !(tex->flags & (SURF_WARP|SURF_SKY)) && s->extents[i] > 256) ! 563: ri.Sys_Error (ERR_DROP,"Bad surface extents"); ! 564: } ! 565: } ! 566: ! 567: ! 568: /* ! 569: ================= ! 570: Mod_LoadFaces ! 571: ================= ! 572: */ ! 573: void Mod_LoadFaces (lump_t *l) ! 574: { ! 575: dface_t *in; ! 576: msurface_t *out; ! 577: int i, count, surfnum; ! 578: int planenum, side; ! 579: ! 580: in = (void *)(mod_base + l->fileofs); ! 581: if (l->filelen % sizeof(*in)) ! 582: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 583: count = l->filelen / sizeof(*in); ! 584: out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox ! 585: ! 586: loadmodel->surfaces = out; ! 587: loadmodel->numsurfaces = count; ! 588: ! 589: for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) ! 590: { ! 591: out->firstedge = LittleLong(in->firstedge); ! 592: out->numedges = LittleShort(in->numedges); ! 593: if (out->numedges < 3) ! 594: ri.Sys_Error (ERR_DROP,"Surface with %s edges", out->numedges); ! 595: out->flags = 0; ! 596: ! 597: planenum = LittleShort(in->planenum); ! 598: side = LittleShort(in->side); ! 599: if (side) ! 600: out->flags |= SURF_PLANEBACK; ! 601: ! 602: out->plane = loadmodel->planes + planenum; ! 603: ! 604: out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); ! 605: ! 606: CalcSurfaceExtents (out); ! 607: ! 608: // lighting info is converted from 24 bit on disk to 8 bit ! 609: ! 610: for (i=0 ; i<MAXLIGHTMAPS ; i++) ! 611: out->styles[i] = in->styles[i]; ! 612: i = LittleLong(in->lightofs); ! 613: if (i == -1) ! 614: out->samples = NULL; ! 615: else ! 616: out->samples = loadmodel->lightdata + i/3; ! 617: ! 618: // set the drawing flags flag ! 619: ! 620: if (!out->texinfo->image) ! 621: continue; ! 622: if (out->texinfo->flags & SURF_SKY) ! 623: { ! 624: out->flags |= SURF_DRAWSKY; ! 625: continue; ! 626: } ! 627: ! 628: if (out->texinfo->flags & SURF_WARP) ! 629: { ! 630: out->flags |= SURF_DRAWTURB; ! 631: for (i=0 ; i<2 ; i++) ! 632: { ! 633: out->extents[i] = 16384; ! 634: out->texturemins[i] = -8192; ! 635: } ! 636: continue; ! 637: } ! 638: } ! 639: } ! 640: ! 641: ! 642: /* ! 643: ================= ! 644: Mod_SetParent ! 645: ================= ! 646: */ ! 647: void Mod_SetParent (mnode_t *node, mnode_t *parent) ! 648: { ! 649: node->parent = parent; ! 650: if (node->contents != -1) ! 651: return; ! 652: Mod_SetParent (node->children[0], node); ! 653: Mod_SetParent (node->children[1], node); ! 654: } ! 655: ! 656: /* ! 657: ================= ! 658: Mod_LoadNodes ! 659: ================= ! 660: */ ! 661: void Mod_LoadNodes (lump_t *l) ! 662: { ! 663: int i, j, count, p; ! 664: dnode_t *in; ! 665: mnode_t *out; ! 666: ! 667: in = (void *)(mod_base + l->fileofs); ! 668: if (l->filelen % sizeof(*in)) ! 669: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 670: count = l->filelen / sizeof(*in); ! 671: out = Hunk_Alloc ( count*sizeof(*out)); ! 672: ! 673: loadmodel->nodes = out; ! 674: loadmodel->numnodes = count; ! 675: ! 676: for ( i=0 ; i<count ; i++, in++, out++) ! 677: { ! 678: for (j=0 ; j<3 ; j++) ! 679: { ! 680: out->minmaxs[j] = LittleShort (in->mins[j]); ! 681: out->minmaxs[3+j] = LittleShort (in->maxs[j]); ! 682: } ! 683: ! 684: p = LittleLong(in->planenum); ! 685: out->plane = loadmodel->planes + p; ! 686: ! 687: out->firstsurface = LittleShort (in->firstface); ! 688: out->numsurfaces = LittleShort (in->numfaces); ! 689: out->contents = CONTENTS_NODE; // differentiate from leafs ! 690: ! 691: for (j=0 ; j<2 ; j++) ! 692: { ! 693: p = LittleLong (in->children[j]); ! 694: if (p >= 0) ! 695: out->children[j] = loadmodel->nodes + p; ! 696: else ! 697: out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); ! 698: } ! 699: } ! 700: ! 701: Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs ! 702: } ! 703: ! 704: /* ! 705: ================= ! 706: Mod_LoadLeafs ! 707: ================= ! 708: */ ! 709: void Mod_LoadLeafs (lump_t *l) ! 710: { ! 711: dleaf_t *in; ! 712: mleaf_t *out; ! 713: int i, j, count; ! 714: ! 715: in = (void *)(mod_base + l->fileofs); ! 716: if (l->filelen % sizeof(*in)) ! 717: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 718: count = l->filelen / sizeof(*in); ! 719: out = Hunk_Alloc ( count*sizeof(*out)); ! 720: ! 721: loadmodel->leafs = out; ! 722: loadmodel->numleafs = count; ! 723: ! 724: for ( i=0 ; i<count ; i++, in++, out++) ! 725: { ! 726: for (j=0 ; j<3 ; j++) ! 727: { ! 728: out->minmaxs[j] = LittleShort (in->mins[j]); ! 729: out->minmaxs[3+j] = LittleShort (in->maxs[j]); ! 730: } ! 731: ! 732: out->contents = LittleLong(in->contents); ! 733: out->cluster = LittleShort(in->cluster); ! 734: out->area = LittleShort(in->area); ! 735: ! 736: out->firstmarksurface = loadmodel->marksurfaces + ! 737: LittleShort(in->firstleafface); ! 738: out->nummarksurfaces = LittleShort(in->numleaffaces); ! 739: } ! 740: } ! 741: ! 742: ! 743: /* ! 744: ================= ! 745: Mod_LoadMarksurfaces ! 746: ================= ! 747: */ ! 748: void Mod_LoadMarksurfaces (lump_t *l) ! 749: { ! 750: int i, j, count; ! 751: short *in; ! 752: msurface_t **out; ! 753: ! 754: in = (void *)(mod_base + l->fileofs); ! 755: if (l->filelen % sizeof(*in)) ! 756: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 757: count = l->filelen / sizeof(*in); ! 758: out = Hunk_Alloc ( count*sizeof(*out)); ! 759: ! 760: loadmodel->marksurfaces = out; ! 761: loadmodel->nummarksurfaces = count; ! 762: ! 763: for ( i=0 ; i<count ; i++) ! 764: { ! 765: j = LittleShort(in[i]); ! 766: if (j >= loadmodel->numsurfaces) ! 767: ri.Sys_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number"); ! 768: out[i] = loadmodel->surfaces + j; ! 769: } ! 770: } ! 771: ! 772: /* ! 773: ================= ! 774: Mod_LoadSurfedges ! 775: ================= ! 776: */ ! 777: void Mod_LoadSurfedges (lump_t *l) ! 778: { ! 779: int i, count; ! 780: int *in, *out; ! 781: ! 782: in = (void *)(mod_base + l->fileofs); ! 783: if (l->filelen % sizeof(*in)) ! 784: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 785: count = l->filelen / sizeof(*in); ! 786: out = Hunk_Alloc ( (count+24)*sizeof(*out)); // extra for skybox ! 787: ! 788: loadmodel->surfedges = out; ! 789: loadmodel->numsurfedges = count; ! 790: ! 791: for ( i=0 ; i<count ; i++) ! 792: out[i] = LittleLong (in[i]); ! 793: } ! 794: ! 795: /* ! 796: ================= ! 797: Mod_LoadPlanes ! 798: ================= ! 799: */ ! 800: void Mod_LoadPlanes (lump_t *l) ! 801: { ! 802: int i, j; ! 803: mplane_t *out; ! 804: dplane_t *in; ! 805: int count; ! 806: int bits; ! 807: ! 808: in = (void *)(mod_base + l->fileofs); ! 809: if (l->filelen % sizeof(*in)) ! 810: ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); ! 811: count = l->filelen / sizeof(*in); ! 812: out = Hunk_Alloc ( (count+6)*sizeof(*out)); // extra for skybox ! 813: ! 814: loadmodel->planes = out; ! 815: loadmodel->numplanes = count; ! 816: ! 817: for ( i=0 ; i<count ; i++, in++, out++) ! 818: { ! 819: bits = 0; ! 820: for (j=0 ; j<3 ; j++) ! 821: { ! 822: out->normal[j] = LittleFloat (in->normal[j]); ! 823: if (out->normal[j] < 0) ! 824: bits |= 1<<j; ! 825: } ! 826: ! 827: out->dist = LittleFloat (in->dist); ! 828: out->type = LittleLong (in->type); ! 829: out->signbits = bits; ! 830: } ! 831: } ! 832: ! 833: ! 834: /* ! 835: ================= ! 836: Mod_LoadBrushModel ! 837: ================= ! 838: */ ! 839: void Mod_LoadBrushModel (model_t *mod, void *buffer) ! 840: { ! 841: int i; ! 842: dheader_t *header; ! 843: dmodel_t *bm; ! 844: ! 845: loadmodel->type = mod_brush; ! 846: if (loadmodel != mod_known) ! 847: ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world"); ! 848: ! 849: header = (dheader_t *)buffer; ! 850: ! 851: i = LittleLong (header->version); ! 852: if (i != BSPVERSION) ! 853: ri.Sys_Error (ERR_DROP,"Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); ! 854: ! 855: // swap all the lumps ! 856: mod_base = (byte *)header; ! 857: ! 858: for (i=0 ; i<sizeof(dheader_t)/4 ; i++) ! 859: ((int *)header)[i] = LittleLong ( ((int *)header)[i]); ! 860: ! 861: // load into heap ! 862: ! 863: Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); ! 864: Mod_LoadEdges (&header->lumps[LUMP_EDGES]); ! 865: Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); ! 866: Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); ! 867: Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); ! 868: Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); ! 869: Mod_LoadFaces (&header->lumps[LUMP_FACES]); ! 870: Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]); ! 871: Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); ! 872: Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); ! 873: Mod_LoadNodes (&header->lumps[LUMP_NODES]); ! 874: Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); ! 875: r_numvisleafs = 0; ! 876: R_NumberLeafs (loadmodel->nodes); ! 877: ! 878: // ! 879: // set up the submodels ! 880: // ! 881: for (i=0 ; i<mod->numsubmodels ; i++) ! 882: { ! 883: model_t *starmod; ! 884: ! 885: bm = &mod->submodels[i]; ! 886: starmod = &mod_inline[i]; ! 887: ! 888: *starmod = *loadmodel; ! 889: ! 890: starmod->firstmodelsurface = bm->firstface; ! 891: starmod->nummodelsurfaces = bm->numfaces; ! 892: starmod->firstnode = bm->headnode; ! 893: if (starmod->firstnode >= loadmodel->numnodes) ! 894: ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i); ! 895: ! 896: VectorCopy (bm->maxs, starmod->maxs); ! 897: VectorCopy (bm->mins, starmod->mins); ! 898: ! 899: if (i == 0) ! 900: *loadmodel = *starmod; ! 901: } ! 902: ! 903: R_InitSkyBox (); ! 904: } ! 905: ! 906: /* ! 907: ============================================================================== ! 908: ! 909: ALIAS MODELS ! 910: ! 911: ============================================================================== ! 912: */ ! 913: ! 914: /* ! 915: ================= ! 916: Mod_LoadAliasModel ! 917: ================= ! 918: */ ! 919: void Mod_LoadAliasModel (model_t *mod, void *buffer) ! 920: { ! 921: int i, j; ! 922: dmdl_t *pinmodel, *pheader; ! 923: dstvert_t *pinst, *poutst; ! 924: dtriangle_t *pintri, *pouttri; ! 925: daliasframe_t *pinframe, *poutframe; ! 926: int *pincmd, *poutcmd; ! 927: int version; ! 928: ! 929: pinmodel = (dmdl_t *)buffer; ! 930: ! 931: version = LittleLong (pinmodel->version); ! 932: if (version != ALIAS_VERSION) ! 933: ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", ! 934: mod->name, version, ALIAS_VERSION); ! 935: ! 936: pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end)); ! 937: ! 938: // byte swap the header fields and sanity check ! 939: for (i=0 ; i<sizeof(dmdl_t)/4 ; i++) ! 940: ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]); ! 941: ! 942: if (pheader->skinheight > MAX_LBM_HEIGHT) ! 943: ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name, ! 944: MAX_LBM_HEIGHT); ! 945: ! 946: if (pheader->num_xyz <= 0) ! 947: ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name); ! 948: ! 949: if (pheader->num_xyz > MAX_VERTS) ! 950: ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name); ! 951: ! 952: if (pheader->num_st <= 0) ! 953: ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name); ! 954: ! 955: if (pheader->num_tris <= 0) ! 956: ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name); ! 957: ! 958: if (pheader->num_frames <= 0) ! 959: ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name); ! 960: ! 961: // ! 962: // load base s and t vertices (not used in gl version) ! 963: // ! 964: pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st); ! 965: poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st); ! 966: ! 967: for (i=0 ; i<pheader->num_st ; i++) ! 968: { ! 969: poutst[i].s = LittleShort (pinst[i].s); ! 970: poutst[i].t = LittleShort (pinst[i].t); ! 971: } ! 972: ! 973: // ! 974: // load triangle lists ! 975: // ! 976: pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris); ! 977: pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris); ! 978: ! 979: for (i=0 ; i<pheader->num_tris ; i++) ! 980: { ! 981: for (j=0 ; j<3 ; j++) ! 982: { ! 983: pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]); ! 984: pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]); ! 985: } ! 986: } ! 987: ! 988: // ! 989: // load the frames ! 990: // ! 991: for (i=0 ; i<pheader->num_frames ; i++) ! 992: { ! 993: pinframe = (daliasframe_t *) ((byte *)pinmodel ! 994: + pheader->ofs_frames + i * pheader->framesize); ! 995: poutframe = (daliasframe_t *) ((byte *)pheader ! 996: + pheader->ofs_frames + i * pheader->framesize); ! 997: ! 998: memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name)); ! 999: for (j=0 ; j<3 ; j++) ! 1000: { ! 1001: poutframe->scale[j] = LittleFloat (pinframe->scale[j]); ! 1002: poutframe->translate[j] = LittleFloat (pinframe->translate[j]); ! 1003: } ! 1004: // verts are all 8 bit, so no swapping needed ! 1005: memcpy (poutframe->verts, pinframe->verts, ! 1006: pheader->num_xyz*sizeof(dtrivertx_t)); ! 1007: ! 1008: } ! 1009: ! 1010: mod->type = mod_alias; ! 1011: ! 1012: // ! 1013: // load the glcmds ! 1014: // ! 1015: pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds); ! 1016: poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds); ! 1017: for (i=0 ; i<pheader->num_glcmds ; i++) ! 1018: poutcmd[i] = LittleLong (pincmd[i]); ! 1019: ! 1020: ! 1021: // register all skins ! 1022: memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, ! 1023: pheader->num_skins*MAX_SKINNAME); ! 1024: for (i=0 ; i<pheader->num_skins ; i++) ! 1025: { ! 1026: mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); ! 1027: } ! 1028: } ! 1029: ! 1030: /* ! 1031: ============================================================================== ! 1032: ! 1033: SPRITE MODELS ! 1034: ! 1035: ============================================================================== ! 1036: */ ! 1037: ! 1038: /* ! 1039: ================= ! 1040: Mod_LoadSpriteModel ! 1041: ================= ! 1042: */ ! 1043: void Mod_LoadSpriteModel (model_t *mod, void *buffer) ! 1044: { ! 1045: dsprite_t *sprin, *sprout; ! 1046: int i; ! 1047: ! 1048: sprin = (dsprite_t *)buffer; ! 1049: sprout = Hunk_Alloc (modfilelen); ! 1050: ! 1051: sprout->ident = LittleLong (sprin->ident); ! 1052: sprout->version = LittleLong (sprin->version); ! 1053: sprout->numframes = LittleLong (sprin->numframes); ! 1054: ! 1055: if (sprout->version != SPRITE_VERSION) ! 1056: ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", ! 1057: mod->name, sprout->version, SPRITE_VERSION); ! 1058: ! 1059: if (sprout->numframes > MAX_MD2SKINS) ! 1060: ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)", ! 1061: mod->name, sprout->numframes, MAX_MD2SKINS); ! 1062: ! 1063: // byte swap everything ! 1064: for (i=0 ; i<sprout->numframes ; i++) ! 1065: { ! 1066: sprout->frames[i].width = LittleLong (sprin->frames[i].width); ! 1067: sprout->frames[i].height = LittleLong (sprin->frames[i].height); ! 1068: sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x); ! 1069: sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y); ! 1070: memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME); ! 1071: mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite); ! 1072: } ! 1073: ! 1074: mod->type = mod_sprite; ! 1075: } ! 1076: ! 1077: //============================================================================= ! 1078: ! 1079: /* ! 1080: @@@@@@@@@@@@@@@@@@@@@ ! 1081: R_BeginRegistration ! 1082: ! 1083: Specifies the model that will be used as the world ! 1084: @@@@@@@@@@@@@@@@@@@@@ ! 1085: */ ! 1086: void R_BeginRegistration (char *model) ! 1087: { ! 1088: char fullname[MAX_QPATH]; ! 1089: cvar_t *flushmap; ! 1090: ! 1091: registration_sequence++; ! 1092: r_oldviewcluster = -1; // force markleafs ! 1093: Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model); ! 1094: ! 1095: D_FlushCaches (); ! 1096: // explicitly free the old map if different ! 1097: // this guarantees that mod_known[0] is the world map ! 1098: flushmap = ri.Cvar_Get ("flushmap", "0", 0); ! 1099: if ( strcmp(mod_known[0].name, fullname) || flushmap->value) ! 1100: Mod_Free (&mod_known[0]); ! 1101: r_worldmodel = R_RegisterModel (fullname); ! 1102: R_NewMap (); ! 1103: } ! 1104: ! 1105: ! 1106: /* ! 1107: @@@@@@@@@@@@@@@@@@@@@ ! 1108: R_RegisterModel ! 1109: ! 1110: @@@@@@@@@@@@@@@@@@@@@ ! 1111: */ ! 1112: struct model_s *R_RegisterModel (char *name) ! 1113: { ! 1114: model_t *mod; ! 1115: int i; ! 1116: dsprite_t *sprout; ! 1117: dmdl_t *pheader; ! 1118: ! 1119: mod = Mod_ForName (name, false); ! 1120: if (mod) ! 1121: { ! 1122: mod->registration_sequence = registration_sequence; ! 1123: ! 1124: // register any images used by the models ! 1125: if (mod->type == mod_sprite) ! 1126: { ! 1127: sprout = (dsprite_t *)mod->extradata; ! 1128: for (i=0 ; i<sprout->numframes ; i++) ! 1129: mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite); ! 1130: } ! 1131: else if (mod->type == mod_alias) ! 1132: { ! 1133: pheader = (dmdl_t *)mod->extradata; ! 1134: for (i=0 ; i<pheader->num_skins ; i++) ! 1135: mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); ! 1136: } ! 1137: else if (mod->type == mod_brush) ! 1138: { ! 1139: for (i=0 ; i<mod->numtexinfo ; i++) ! 1140: mod->texinfo[i].image->registration_sequence = registration_sequence; ! 1141: } ! 1142: } ! 1143: return mod; ! 1144: } ! 1145: ! 1146: /* ! 1147: @@@@@@@@@@@@@@@@@@@@@ ! 1148: R_EndRegistration ! 1149: ! 1150: @@@@@@@@@@@@@@@@@@@@@ ! 1151: */ ! 1152: void R_EndRegistration (void) ! 1153: { ! 1154: int i; ! 1155: model_t *mod; ! 1156: ! 1157: for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++) ! 1158: { ! 1159: if (!mod->name[0]) ! 1160: continue; ! 1161: if (mod->registration_sequence != registration_sequence) ! 1162: { // don't need this model ! 1163: Hunk_Free (mod->extradata); ! 1164: memset (mod, 0, sizeof(*mod)); ! 1165: } ! 1166: else ! 1167: { // make sure it is paged in ! 1168: Com_PageInMemory (mod->extradata, mod->extradatasize); ! 1169: } ! 1170: } ! 1171: ! 1172: R_FreeUnusedImages (); ! 1173: } ! 1174: ! 1175: ! 1176: //============================================================================= ! 1177: ! 1178: /* ! 1179: ================ ! 1180: Mod_Free ! 1181: ================ ! 1182: */ ! 1183: void Mod_Free (model_t *mod) ! 1184: { ! 1185: Hunk_Free (mod->extradata); ! 1186: memset (mod, 0, sizeof(*mod)); ! 1187: } ! 1188: ! 1189: /* ! 1190: ================ ! 1191: Mod_FreeAll ! 1192: ================ ! 1193: */ ! 1194: void Mod_FreeAll (void) ! 1195: { ! 1196: int i; ! 1197: ! 1198: for (i=0 ; i<mod_numknown ; i++) ! 1199: { ! 1200: if (mod_known[i].extradatasize) ! 1201: Mod_Free (&mod_known[i]); ! 1202: } ! 1203: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.