--- quake2/ref_gl/gl_model.c 2018/04/24 17:58:33 1.1.1.1 +++ quake2/ref_gl/gl_model.c 2018/04/24 17:59:25 1.1.1.2 @@ -1,18 +1,26 @@ // models.c -- model loading and caching + #include "gl_local.h" + model_t *loadmodel; int modfilelen; + void Mod_LoadSpriteModel (model_t *mod, void *buffer); void Mod_LoadBrushModel (model_t *mod, void *buffer); void Mod_LoadAliasModel (model_t *mod, void *buffer); model_t *Mod_LoadModel (model_t *mod, qboolean crash); + byte mod_novis[MAX_MAP_LEAFS/8]; + #define MAX_MOD_KNOWN 512 model_t mod_known[MAX_MOD_KNOWN]; int mod_numknown; + // the inline * models from the current map are kept seperate model_t mod_inline[MAX_MOD_KNOWN]; + int registration_sequence; + /* =============== Mod_PointInLeaf @@ -26,6 +34,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, mode if (!model || !model->nodes) ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model"); + node = model->nodes; while (1) { @@ -41,6 +50,8 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, mode return NULL; // never reached } + + /* =================== Mod_DecompressVis @@ -52,8 +63,10 @@ byte *Mod_DecompressVis (byte *in, model int c; byte *out; int row; + row = (model->vis->numclusters+7)>>3; out = decompressed; + if (!in) { // no vis info, so make all visible while (row) @@ -63,6 +76,7 @@ byte *Mod_DecompressVis (byte *in, model } return decompressed; } + do { if (*in) @@ -82,6 +96,7 @@ byte *Mod_DecompressVis (byte *in, model return decompressed; } + /* ============== Mod_ClusterPVS @@ -94,7 +109,10 @@ byte *Mod_ClusterPVS (int cluster, model return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS], model); } + + //=============================================================================== + /* ================ Mod_Modellist_f @@ -105,6 +123,7 @@ void Mod_Modellist_f (void) int i; model_t *mod; int total; + total = 0; ri.Con_Printf (PRINT_ALL,"Loaded models:\n"); for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) @@ -116,6 +135,7 @@ void Mod_Modellist_f (void) } ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total); } + /* =============== Mod_Init @@ -125,9 +145,13 @@ void Mod_Init (void) { memset (mod_novis, 0xff, sizeof(mod_novis)); } + + + /* ================== Mod_ForName + Loads in a model for the given name ================== */ @@ -150,6 +174,7 @@ model_t *Mod_ForName (char *name, qboole ri.Sys_Error (ERR_DROP, "bad inline model number"); return &mod_inline[i]; } + // // search the currently loaded models // @@ -190,9 +215,12 @@ model_t *Mod_ForName (char *name, qboole } loadmodel = mod; + // // fill it in // + + // call the apropriate loader switch (LittleLong(*(unsigned *)buf)) @@ -211,20 +239,30 @@ model_t *Mod_ForName (char *name, qboole loadmodel->extradata = Hunk_Begin (0x1000000); Mod_LoadBrushModel (mod, buf); break; + default: ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name); break; } + loadmodel->extradatasize = Hunk_End (); + ri.FS_FreeFile (buf); + return mod; } + /* =============================================================================== + BRUSHMODEL LOADING + =============================================================================== */ + byte *mod_base; + + /* ================= Mod_LoadLighting @@ -240,6 +278,8 @@ void Mod_LoadLighting (lump_t *l) loadmodel->lightdata = Hunk_Alloc ( l->filelen); memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); } + + /* ================= Mod_LoadVisibility @@ -248,6 +288,7 @@ Mod_LoadVisibility void Mod_LoadVisibility (lump_t *l) { int i; + if (!l->filelen) { loadmodel->vis = NULL; @@ -255,6 +296,7 @@ void Mod_LoadVisibility (lump_t *l) } loadmodel->vis = Hunk_Alloc ( l->filelen); memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen); + loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters); for (i=0 ; ivis->numclusters ; i++) { @@ -262,6 +304,8 @@ void Mod_LoadVisibility (lump_t *l) loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]); } } + + /* ================= Mod_LoadVertexes @@ -272,13 +316,16 @@ void Mod_LoadVertexes (lump_t *l) dvertex_t *in; mvertex_t *out; int i, count; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->vertexes = out; loadmodel->numvertexes = count; + for ( i=0 ; iposition[0] = LittleFloat (in->point[0]); @@ -286,6 +333,7 @@ void Mod_LoadVertexes (lump_t *l) out->position[2] = LittleFloat (in->point[2]); } } + /* ================= RadiusFromBounds @@ -295,12 +343,16 @@ float RadiusFromBounds (vec3_t mins, vec { int i; vec3_t corner; + for (i=0 ; i<3 ; i++) { corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]); } + return VectorLength (corner); } + + /* ================= Mod_LoadSubmodels @@ -311,13 +363,16 @@ void Mod_LoadSubmodels (lump_t *l) dmodel_t *in; mmodel_t *out; int i, j, count; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->submodels = out; loadmodel->numsubmodels = count; + for ( i=0 ; inumfaces = LittleLong (in->numfaces); } } + /* ================= Mod_LoadEdges @@ -342,19 +398,23 @@ void Mod_LoadEdges (lump_t *l) dedge_t *in; medge_t *out; int i, count; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( (count + 1) * sizeof(*out)); + loadmodel->edges = out; loadmodel->numedges = count; + for ( i=0 ; iv[0] = (unsigned short)LittleShort(in->v[0]); out->v[1] = (unsigned short)LittleShort(in->v[1]); } } + /* ================= Mod_LoadTexinfo @@ -367,22 +427,29 @@ void Mod_LoadTexinfo (lump_t *l) int i, j, count; char name[MAX_QPATH]; int next; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->texinfo = out; loadmodel->numtexinfo = count; + for ( i=0 ; ivecs[0][j] = LittleFloat (in->vecs[0][j]); + out->flags = LittleLong (in->flags); next = LittleLong (in->nexttexinfo); if (next > 0) out->next = loadmodel->texinfo + next; + else + out->next = NULL; Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); + out->image = GL_FindImage (name, it_wall); if (!out->image) { @@ -390,6 +457,7 @@ void Mod_LoadTexinfo (lump_t *l) out->image = r_notexture; } } + // count animation frames for (i=0 ; inumframes++; } } + /* ================ CalcSurfaceExtents + Fills in s->texturemins[] and s->extents[] ================ */ @@ -412,8 +482,10 @@ void CalcSurfaceExtents (msurface_t *s) mvertex_t *v; mtexinfo_t *tex; int bmins[2], bmaxs[2]; + mins[0] = mins[1] = 999999; maxs[0] = maxs[1] = -99999; + tex = s->texinfo; for (i=0 ; inumedges ; i++) @@ -436,20 +508,26 @@ void CalcSurfaceExtents (msurface_t *s) maxs[j] = val; } } + for (i=0 ; i<2 ; i++) { bmins[i] = floor(mins[i]/16); bmaxs[i] = ceil(maxs[i]/16); + s->texturemins[i] = bmins[i] * 16; s->extents[i] = (bmaxs[i] - bmins[i]) * 16; + // if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ ) // ri.Sys_Error (ERR_DROP, "Bad surface extents"); } } + + void GL_BuildPolygonFromSurface(msurface_t *fa); void GL_CreateSurfaceLightmap (msurface_t *surf); void GL_EndBuildingLightmaps (void); void GL_BeginBuildingLightmaps (model_t *m); + /* ================= Mod_LoadFaces @@ -462,33 +540,43 @@ void Mod_LoadFaces (lump_t *l) int i, count, surfnum; int planenum, side; int ti; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->surfaces = out; loadmodel->numsurfaces = count; + currentmodel = loadmodel; + GL_BeginBuildingLightmaps (loadmodel); + for ( surfnum=0 ; surfnumfirstedge = LittleLong(in->firstedge); out->numedges = LittleShort(in->numedges); out->flags = 0; + out->polys = NULL; + planenum = LittleShort(in->planenum); side = LittleShort(in->side); if (side) out->flags |= SURF_PLANEBACK; + out->plane = loadmodel->planes + planenum; ti = LittleShort (in->texinfo); if (ti < 0 || ti >= loadmodel->numtexinfo) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad texinfo number"); out->texinfo = loadmodel->texinfo + ti; + CalcSurfaceExtents (out); // lighting info + for (i=0 ; istyles[i] = in->styles[i]; i = LittleLong(in->lightofs); @@ -509,14 +597,20 @@ void Mod_LoadFaces (lump_t *l) } GL_SubdivideSurface (out); // cut up polygon for warps } + // create lightmaps and polygons if ( !(out->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP) ) ) GL_CreateSurfaceLightmap (out); + if (! (out->texinfo->flags & SURF_WARP) ) GL_BuildPolygonFromSurface(out); + } + GL_EndBuildingLightmaps (); } + + /* ================= Mod_SetParent @@ -530,6 +624,7 @@ void Mod_SetParent (mnode_t *node, mnode Mod_SetParent (node->children[0], node); Mod_SetParent (node->children[1], node); } + /* ================= Mod_LoadNodes @@ -540,13 +635,16 @@ void Mod_LoadNodes (lump_t *l) int i, j, count, p; dnode_t *in; mnode_t *out; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->nodes = out; loadmodel->numnodes = count; + for ( i=0 ; iplanenum); out->plane = loadmodel->planes + p; + out->firstsurface = LittleShort (in->firstface); out->numsurfaces = LittleShort (in->numfaces); out->contents = -1; // differentiate from leafs + for (j=0 ; j<2 ; j++) { p = LittleLong (in->children[j]); @@ -572,6 +672,7 @@ void Mod_LoadNodes (lump_t *l) Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs } + /* ================= Mod_LoadLeafs @@ -583,13 +684,16 @@ void Mod_LoadLeafs (lump_t *l) mleaf_t *out; int i, j, count, p; // glpoly_t *poly; + in = (void *)(mod_base + l->fileofs); if (l->filelen % sizeof(*in)) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->leafs = out; loadmodel->numleafs = count; + for ( i=0 ; iminmaxs[j] = LittleShort (in->mins[j]); out->minmaxs[3+j] = LittleShort (in->maxs[j]); } + p = LittleLong(in->contents); out->contents = p; + out->cluster = LittleShort(in->cluster); out->area = LittleShort(in->area); + out->firstmarksurface = loadmodel->marksurfaces + LittleShort(in->firstleafface); out->nummarksurfaces = LittleShort(in->numleaffaces); @@ -619,6 +726,7 @@ void Mod_LoadLeafs (lump_t *l) #endif } } + /* ================= Mod_LoadMarksurfaces @@ -635,8 +743,10 @@ void Mod_LoadMarksurfaces (lump_t *l) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name); count = l->filelen / sizeof(*in); out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->marksurfaces = out; loadmodel->nummarksurfaces = count; + for ( i=0 ; isurfaces + j; } } + /* ================= Mod_LoadSurfedges @@ -662,12 +773,17 @@ void Mod_LoadSurfedges (lump_t *l) if (count < 1 || count >= MAX_MAP_SURFEDGES) ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad surfedges count in %s: %i", loadmodel->name, count); + out = Hunk_Alloc ( count*sizeof(*out)); + loadmodel->surfedges = out; loadmodel->numsurfedges = count; + for ( i=0 ; iplanes = out; loadmodel->numplanes = count; + for ( i=0 ; inormal[j] < 0) bits |= 1<dist = LittleFloat (in->dist); out->type = LittleLong (in->type); out->signbits = bits; } } + /* ================= Mod_LoadBrushModel @@ -717,14 +836,19 @@ void Mod_LoadBrushModel (model_t *mod, v loadmodel->type = mod_brush; if (loadmodel != mod_known) ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world"); + header = (dheader_t *)buffer; + i = LittleLong (header->version); if (i != BSPVERSION) ri.Sys_Error (ERR_DROP, "Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION); + // swap all the lumps mod_base = (byte *)header; + for (i=0 ; ilumps[LUMP_VERTEXES]); @@ -747,8 +871,10 @@ void Mod_LoadBrushModel (model_t *mod, v for (i=0 ; inumsubmodels ; i++) { model_t *starmod; + bm = &mod->submodels[i]; starmod = &mod_inline[i]; + *starmod = *loadmodel; starmod->firstmodelsurface = bm->firstface; @@ -763,14 +889,19 @@ void Mod_LoadBrushModel (model_t *mod, v if (i == 0) *loadmodel = *starmod; + starmod->numleafs = bm->visleafs; } } + /* ============================================================================== + ALIAS MODELS + ============================================================================== */ + /* ================= Mod_LoadAliasModel @@ -785,44 +916,57 @@ void Mod_LoadAliasModel (model_t *mod, v daliasframe_t *pinframe, *poutframe; int *pincmd, *poutcmd; int version; + pinmodel = (dmdl_t *)buffer; + version = LittleLong (pinmodel->version); if (version != ALIAS_VERSION) ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", mod->name, version, ALIAS_VERSION); + pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end)); // byte swap the header fields and sanity check for (i=0 ; iskinheight > MAX_LBM_HEIGHT) ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT); + if (pheader->num_xyz <= 0) ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name); + if (pheader->num_xyz > MAX_VERTS) ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name); + if (pheader->num_st <= 0) ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name); + if (pheader->num_tris <= 0) ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name); + if (pheader->num_frames <= 0) ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name); + // // load base s and t vertices (not used in gl version) // pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st); poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st); + for (i=0 ; inum_st ; i++) { poutst[i].s = LittleShort (pinst[i].s); poutst[i].t = LittleShort (pinst[i].t); } + // // load triangle lists // pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris); pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris); + for (i=0 ; inum_tris ; i++) { for (j=0 ; j<3 ; j++) @@ -831,6 +975,7 @@ void Mod_LoadAliasModel (model_t *mod, v pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]); } } + // // load the frames // @@ -840,6 +985,7 @@ void Mod_LoadAliasModel (model_t *mod, v + pheader->ofs_frames + i * pheader->framesize); poutframe = (daliasframe_t *) ((byte *)pheader + pheader->ofs_frames + i * pheader->framesize); + memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name)); for (j=0 ; j<3 ; j++) { @@ -849,8 +995,11 @@ void Mod_LoadAliasModel (model_t *mod, v // verts are all 8 bit, so no swapping needed memcpy (poutframe->verts, pinframe->verts, pheader->num_xyz*sizeof(dtrivertx_t)); + } + mod->type = mod_alias; + // // load the glcmds // @@ -858,6 +1007,8 @@ void Mod_LoadAliasModel (model_t *mod, v poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds); for (i=0 ; inum_glcmds ; i++) poutcmd[i] = LittleLong (pincmd[i]); + + // register all skins memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins, pheader->num_skins*MAX_SKINNAME); @@ -866,6 +1017,7 @@ void Mod_LoadAliasModel (model_t *mod, v mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME , it_skin); } + mod->mins[0] = -32; mod->mins[1] = -32; mod->mins[2] = -32; @@ -873,11 +1025,15 @@ void Mod_LoadAliasModel (model_t *mod, v mod->maxs[1] = 32; mod->maxs[2] = 32; } + /* ============================================================================== + SPRITE MODELS + ============================================================================== */ + /* ================= Mod_LoadSpriteModel @@ -887,17 +1043,22 @@ void Mod_LoadSpriteModel (model_t *mod, { dsprite_t *sprin, *sprout; int i; + sprin = (dsprite_t *)buffer; sprout = Hunk_Alloc (modfilelen); + sprout->ident = LittleLong (sprin->ident); sprout->version = LittleLong (sprin->version); sprout->numframes = LittleLong (sprin->numframes); + if (sprout->version != SPRITE_VERSION) ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", mod->name, sprout->version, SPRITE_VERSION); + if (sprout->numframes > MAX_MD2SKINS) ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)", mod->name, sprout->numframes, MAX_MD2SKINS); + // byte swap everything for (i=0 ; inumframes ; i++) { @@ -909,12 +1070,16 @@ void Mod_LoadSpriteModel (model_t *mod, mod->skins[i] = GL_FindImage (sprout->frames[i].name, it_sprite); } + mod->type = mod_sprite; } + //============================================================================= + /* @@@@@@@@@@@@@@@@@@@@@ R_BeginRegistration + Specifies the model that will be used as the world @@@@@@@@@@@@@@@@@@@@@ */ @@ -922,20 +1087,27 @@ void R_BeginRegistration (char *model) { char fullname[MAX_QPATH]; cvar_t *flushmap; + registration_sequence++; r_oldviewcluster = -1; // force markleafs + Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model); + // explicitly free the old map if different // this guarantees that mod_known[0] is the world map flushmap = ri.Cvar_Get ("flushmap", "0", 0); if ( strcmp(mod_known[0].name, fullname) || flushmap->value) Mod_Free (&mod_known[0]); r_worldmodel = Mod_ForName(fullname, true); + r_viewcluster = -1; } + + /* @@@@@@@@@@@@@@@@@@@@@ R_RegisterModel + @@@@@@@@@@@@@@@@@@@@@ */ struct model_s *R_RegisterModel (char *name) @@ -944,10 +1116,12 @@ struct model_s *R_RegisterModel (char *n int i; dsprite_t *sprout; dmdl_t *pheader; + mod = Mod_ForName (name, false); if (mod) { mod->registration_sequence = registration_sequence; + // register any images used by the models if (mod->type == mod_sprite) { @@ -969,15 +1143,19 @@ struct model_s *R_RegisterModel (char *n } return mod; } + + /* @@@@@@@@@@@@@@@@@@@@@ R_EndRegistration + @@@@@@@@@@@@@@@@@@@@@ */ void R_EndRegistration (void) { int i; model_t *mod; + for (i=0, mod=mod_known ; iname[0]) @@ -987,9 +1165,14 @@ void R_EndRegistration (void) Mod_Free (mod); } } + GL_FreeUnusedImages (); } + + //============================================================================= + + /* ================ Mod_Free @@ -1000,6 +1183,7 @@ void Mod_Free (model_t *mod) Hunk_Free (mod->extradata); memset (mod, 0, sizeof(*mod)); } + /* ================ Mod_FreeAll @@ -1008,6 +1192,7 @@ Mod_FreeAll void Mod_FreeAll (void) { int i; + for (i=0 ; i