// models.c -- model loading and caching // models are the only shared resource between a client and server running// on the same machine. #include <u.h>#include <libc.h>#include <stdio.h>#include "dat.h"#include "fns.h" model_t *loadmodel;char loadname[32]; // for hunk tags 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 256model_t mod_known[MAX_MOD_KNOWN];int mod_numknown; // the inline * models from the current map are kept seperatemodel_t mod_inline[MAX_MOD_KNOWN]; int registration_sequence;int modfilelen; //=============================================================================== /*================Mod_Modellist_f================*/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++) { if (!mod->name[0]) continue; ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name); total += mod->extradatasize; } ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);} /*===============Mod_Init===============*/void Mod_Init (void){ memset (mod_novis, 0xff, sizeof(mod_novis));} /*==================Mod_ForName Loads in a model for the given name==================*/model_t *Mod_ForName (char *name, qboolean crash){ model_t *mod; unsigned *buf; int i; if (!name[0]) ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name"); // // inline models are grabbed only from worldmodel // if (name[0] == '*') { i = atoi(name+1); if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) ri.Sys_Error (ERR_DROP, "bad inline model number"); return &mod_inline[i]; } // // search the currently loaded models // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) if (!strcmp (mod->name, name) ) return mod; // // find a free model slot spot // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) break; // free spot } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); mod_numknown++; } strcpy (mod->name, name); // // load the file // modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf); if (!buf) { if (crash) ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name); memset (mod->name, 0, sizeof(mod->name)); return NULL; } loadmodel = mod; // // fill it in // // call the apropriate loader switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: loadmodel->extradata = Hunk_Begin (0x200000); Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: loadmodel->extradata = Hunk_Begin (0x10000); Mod_LoadSpriteModel (mod, buf); break; case IDBSPHEADER: 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;} /*===============Mod_PointInLeaf===============*/mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model){ mnode_t *node; float d; mplane_t *plane; if (!model || !model->nodes) ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model"); node = model->nodes; while (1) { if (node->contents != -1) return (mleaf_t *)node; plane = node->plane; d = DotProduct (p,plane->normal) - plane->dist; if (d > 0) node = node->children[0]; else node = node->children[1]; }} /*===================Mod_DecompressVis===================*/byte *Mod_DecompressVis (byte *in, model_t *model){ static byte decompressed[MAX_MAP_LEAFS/8]; int c; byte *out; int row; row = (model->vis->numclusters+7)>>3; out = decompressed; /* memcpy (out, in, row); */ if (!in) { // no vis info, so make all visible while (row) { *out++ = 0xff; row--; } return decompressed; } do { if (*in) { *out++ = *in++; continue; } c = in[1]; in += 2; while (c) { *out++ = 0; c--; } } while (out - decompressed < row); return decompressed;} /*==============Mod_ClusterPVS==============*/byte *Mod_ClusterPVS (int cluster, model_t *model){ if (cluster == -1 || !model->vis) return mod_novis; return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS], model);} /*=============================================================================== BRUSHMODEL LOADING ===============================================================================*/ byte *mod_base; /*=================Mod_LoadLighting Converts the 24 bit lighting down to 8 bitby taking the brightest component=================*/void Mod_LoadLighting (lump_t *l){ int i, size; byte *in; if (!l->filelen) { loadmodel->lightdata = NULL; return; } size = l->filelen/3; loadmodel->lightdata = Hunk_Alloc (size); in = (void *)(mod_base + l->fileofs); for (i=0 ; i<size ; i++, in+=3) { if (in[0] > in[1] && in[0] > in[2]) loadmodel->lightdata[i] = in[0]; else if (in[1] > in[0] && in[1] > in[2]) loadmodel->lightdata[i] = in[1]; else loadmodel->lightdata[i] = in[2]; }} int r_leaftovis[MAX_MAP_LEAFS];int r_vistoleaf[MAX_MAP_LEAFS];int r_numvisleafs; void R_NumberLeafs (mnode_t *node){ mleaf_t *leaf; int leafnum; if (node->contents != -1) { leaf = (mleaf_t *)node; leafnum = leaf - loadmodel->leafs; if (leaf->contents & CONTENTS_SOLID) return; r_leaftovis[leafnum] = r_numvisleafs; r_vistoleaf[r_numvisleafs] = leafnum; r_numvisleafs++; return; } R_NumberLeafs (node->children[0]); R_NumberLeafs (node->children[1]);} /*=================Mod_LoadVisibility=================*/void Mod_LoadVisibility (lump_t *l){ int i; if (!l->filelen) { loadmodel->vis = NULL; return; } 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 ; i<loadmodel->vis->numclusters ; i++) { loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]); loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]); }} /*=================Mod_LoadVertexes=================*/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+8)*sizeof(*out)); // extra for skybox loadmodel->vertexes = out; loadmodel->numvertexes = count; for ( i=0 ; i<count ; i++, in++, out++) { out->position[0] = LittleFloat (in->point[0]); out->position[1] = LittleFloat (in->point[1]); out->position[2] = LittleFloat (in->point[2]); }} /*=================Mod_LoadSubmodels=================*/void Mod_LoadSubmodels (lump_t *l){ dmodel_t *in; dmodel_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 ; i<count ; i++, in++, out++) { for (j=0 ; j<3 ; j++) { // spread the mins / maxs by a pixel out->mins[j] = LittleFloat (in->mins[j]) - 1; out->maxs[j] = LittleFloat (in->maxs[j]) + 1; out->origin[j] = LittleFloat (in->origin[j]); } out->headnode = LittleLong (in->headnode); out->firstface = LittleLong (in->firstface); out->numfaces = LittleLong (in->numfaces); }} /*=================Mod_LoadEdges=================*/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 + 13) * sizeof(*out)); // extra for skybox loadmodel->edges = out; loadmodel->numedges = count; for ( i=0 ; i<count ; i++, in++, out++) { out->v[0] = (unsigned short)LittleShort(in->v[0]); out->v[1] = (unsigned short)LittleShort(in->v[1]); }} /*=================Mod_LoadTexinfo=================*/void Mod_LoadTexinfo (lump_t *l){ texinfo_t *in; mtexinfo_t *out, *step; int i, j, count; float len1, len2; 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+6)*sizeof(*out)); // extra for skybox loadmodel->texinfo = out; loadmodel->numtexinfo = count; for ( i=0 ; i<count ; i++, in++, out++) { for (j=0 ; j<8 ; j++) out->vecs[0][j] = LittleFloat (in->vecs[0][j]); len1 = VectorLength (out->vecs[0]); len2 = VectorLength (out->vecs[1]); len1 = (len1 + len2)/2; if (len1 < 0.32) out->mipadjust = 4; else if (len1 < 0.49) out->mipadjust = 3; else if (len1 < 0.99) out->mipadjust = 2; else out->mipadjust = 1; /* if (len1 + len2 < 0.001) out->mipadjust = 1; // don't crash else out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); */ out->flags = LittleLong (in->flags); next = LittleLong (in->nexttexinfo); if (next > 0) out->next = loadmodel->texinfo + next; Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); out->image = R_FindImage (name, it_wall); if (!out->image) { out->image = r_notexture_mip; // texture not found out->flags = 0; }Lines 1–500 of 1205. Load more
// models.c -- model loading and caching // models are the only shared resource between a client and server running // on the same machine. #include <u.h> #include <libc.h> #include <stdio.h> #include "dat.h" #include "fns.h" model_t *loadmodel; char loadname[32]; // for hunk tags 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 256 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; int modfilelen; //=============================================================================== /* ================ Mod_Modellist_f ================ */ 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++) { if (!mod->name[0]) continue; ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name); total += mod->extradatasize; } ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total); } /* =============== Mod_Init =============== */ void Mod_Init (void) { memset (mod_novis, 0xff, sizeof(mod_novis)); } /* ================== Mod_ForName Loads in a model for the given name ================== */ model_t *Mod_ForName (char *name, qboolean crash) { model_t *mod; unsigned *buf; int i; if (!name[0]) ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name"); // // inline models are grabbed only from worldmodel // if (name[0] == '*') { i = atoi(name+1); if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels) ri.Sys_Error (ERR_DROP, "bad inline model number"); return &mod_inline[i]; } // // search the currently loaded models // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) if (!strcmp (mod->name, name) ) return mod; // // find a free model slot spot // for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) { if (!mod->name[0]) break; // free spot } if (i == mod_numknown) { if (mod_numknown == MAX_MOD_KNOWN) ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); mod_numknown++; } strcpy (mod->name, name); // // load the file // modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf); if (!buf) { if (crash) ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name); memset (mod->name, 0, sizeof(mod->name)); return NULL; } loadmodel = mod; // // fill it in // // call the apropriate loader switch (LittleLong(*(unsigned *)buf)) { case IDALIASHEADER: loadmodel->extradata = Hunk_Begin (0x200000); Mod_LoadAliasModel (mod, buf); break; case IDSPRITEHEADER: loadmodel->extradata = Hunk_Begin (0x10000); Mod_LoadSpriteModel (mod, buf); break; case IDBSPHEADER: 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; } /* =============== Mod_PointInLeaf =============== */ mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) { mnode_t *node; float d; mplane_t *plane; if (!model || !model->nodes) ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model"); node = model->nodes; while (1) { if (node->contents != -1) return (mleaf_t *)node; plane = node->plane; d = DotProduct (p,plane->normal) - plane->dist; if (d > 0) node = node->children[0]; else node = node->children[1]; } } /* =================== Mod_DecompressVis =================== */ byte *Mod_DecompressVis (byte *in, model_t *model) { static byte decompressed[MAX_MAP_LEAFS/8]; int c; byte *out; int row; row = (model->vis->numclusters+7)>>3; out = decompressed; /* memcpy (out, in, row); */ if (!in) { // no vis info, so make all visible while (row) { *out++ = 0xff; row--; } return decompressed; } do { if (*in) { *out++ = *in++; continue; } c = in[1]; in += 2; while (c) { *out++ = 0; c--; } } while (out - decompressed < row); return decompressed; } /* ============== Mod_ClusterPVS ============== */ byte *Mod_ClusterPVS (int cluster, model_t *model) { if (cluster == -1 || !model->vis) return mod_novis; return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS], model); } /* =============================================================================== BRUSHMODEL LOADING =============================================================================== */ byte *mod_base; /* ================= Mod_LoadLighting Converts the 24 bit lighting down to 8 bit by taking the brightest component ================= */ void Mod_LoadLighting (lump_t *l) { int i, size; byte *in; if (!l->filelen) { loadmodel->lightdata = NULL; return; } size = l->filelen/3; loadmodel->lightdata = Hunk_Alloc (size); in = (void *)(mod_base + l->fileofs); for (i=0 ; i<size ; i++, in+=3) { if (in[0] > in[1] && in[0] > in[2]) loadmodel->lightdata[i] = in[0]; else if (in[1] > in[0] && in[1] > in[2]) loadmodel->lightdata[i] = in[1]; else loadmodel->lightdata[i] = in[2]; } } int r_leaftovis[MAX_MAP_LEAFS]; int r_vistoleaf[MAX_MAP_LEAFS]; int r_numvisleafs; void R_NumberLeafs (mnode_t *node) { mleaf_t *leaf; int leafnum; if (node->contents != -1) { leaf = (mleaf_t *)node; leafnum = leaf - loadmodel->leafs; if (leaf->contents & CONTENTS_SOLID) return; r_leaftovis[leafnum] = r_numvisleafs; r_vistoleaf[r_numvisleafs] = leafnum; r_numvisleafs++; return; } R_NumberLeafs (node->children[0]); R_NumberLeafs (node->children[1]); } /* ================= Mod_LoadVisibility ================= */ void Mod_LoadVisibility (lump_t *l) { int i; if (!l->filelen) { loadmodel->vis = NULL; return; } 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 ; i<loadmodel->vis->numclusters ; i++) { loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]); loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]); } } /* ================= Mod_LoadVertexes ================= */ 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+8)*sizeof(*out)); // extra for skybox loadmodel->vertexes = out; loadmodel->numvertexes = count; for ( i=0 ; i<count ; i++, in++, out++) { out->position[0] = LittleFloat (in->point[0]); out->position[1] = LittleFloat (in->point[1]); out->position[2] = LittleFloat (in->point[2]); } } /* ================= Mod_LoadSubmodels ================= */ void Mod_LoadSubmodels (lump_t *l) { dmodel_t *in; dmodel_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 ; i<count ; i++, in++, out++) { for (j=0 ; j<3 ; j++) { // spread the mins / maxs by a pixel out->mins[j] = LittleFloat (in->mins[j]) - 1; out->maxs[j] = LittleFloat (in->maxs[j]) + 1; out->origin[j] = LittleFloat (in->origin[j]); } out->headnode = LittleLong (in->headnode); out->firstface = LittleLong (in->firstface); out->numfaces = LittleLong (in->numfaces); } } /* ================= Mod_LoadEdges ================= */ 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 + 13) * sizeof(*out)); // extra for skybox loadmodel->edges = out; loadmodel->numedges = count; for ( i=0 ; i<count ; i++, in++, out++) { out->v[0] = (unsigned short)LittleShort(in->v[0]); out->v[1] = (unsigned short)LittleShort(in->v[1]); } } /* ================= Mod_LoadTexinfo ================= */ void Mod_LoadTexinfo (lump_t *l) { texinfo_t *in; mtexinfo_t *out, *step; int i, j, count; float len1, len2; 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+6)*sizeof(*out)); // extra for skybox loadmodel->texinfo = out; loadmodel->numtexinfo = count; for ( i=0 ; i<count ; i++, in++, out++) { for (j=0 ; j<8 ; j++) out->vecs[0][j] = LittleFloat (in->vecs[0][j]); len1 = VectorLength (out->vecs[0]); len2 = VectorLength (out->vecs[1]); len1 = (len1 + len2)/2; if (len1 < 0.32) out->mipadjust = 4; else if (len1 < 0.49) out->mipadjust = 3; else if (len1 < 0.99) out->mipadjust = 2; else out->mipadjust = 1; /* if (len1 + len2 < 0.001) out->mipadjust = 1; // don't crash else out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); */ out->flags = LittleLong (in->flags); next = LittleLong (in->nexttexinfo); if (next > 0) out->next = loadmodel->texinfo + next; Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture); out->image = R_FindImage (name, it_wall); if (!out->image) { out->image = r_notexture_mip; // texture not found out->flags = 0; }