diff options
Diffstat (limited to 'source/sw_model.c')
-rw-r--r-- | source/sw_model.c | 1292 |
1 files changed, 189 insertions, 1103 deletions
diff --git a/source/sw_model.c b/source/sw_model.c index 28678b5..1bebf9d 100644 --- a/source/sw_model.c +++ b/source/sw_model.c @@ -24,507 +24,40 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "sw_local.h" -model_t *loadmodel; - -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; - -/* -================ -R_ModelForHandle -================ -*/ -model_t *R_ModelForHandle( qhandle_t hModel ) { - if( !hModel ) { - return NULL; - } - - if( hModel < 0 ) { - // inline model - if( !r_worldmodel ) { - return NULL; - } - hModel = -hModel; - if( hModel >= r_worldmodel->numsubmodels ) { - Com_Error( ERR_DROP, "R_ModelForHandle: out of range inline hModel: %i", hModel ); - } - return &mod_inline[hModel]; - } - - if( hModel >= mod_numknown + 1 ) { - Com_Error( ERR_DROP, "R_ModelForHandle: out of range hModel: %i", hModel ); - } - return &mod_known[hModel - 1]; -} - -//=============================================================================== - - -/* -================ -Mod_Modellist_f -================ -*/ -void Mod_Modellist_f (void) -{ - int i; - model_t *mod; - int total; - - total = 0; - Com_Printf("Loaded models:\n"); - for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) - { - if (!mod->name[0]) - continue; - Com_Printf( "%8"PRIz" : %s\n",mod->pool.cursize, mod->name); - total += mod->pool.cursize; - } - Com_Printf( "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 -================== -*/ -qhandle_t Mod_ForName (const char *name, qboolean crash) -{ - model_t *mod; - byte *buf; - int i; - - if (!name || !name[0]) - Com_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) - Com_Error (ERR_DROP, "bad inline model number"); - return -i; - } - - // - // search the currently loaded models - // - for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) - if (!strcmp (mod->name, name) ) - return i + 1; - - // - // 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) - Com_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN"); - mod_numknown++; - } - Q_strncpyz( mod->name, name, sizeof( mod->name ) ); - - // - // load the file - // - modfilelen = fs.LoadFile (mod->name, (void **)&buf); - if (!buf) - { - if (crash) - Com_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name); - memset (mod->name, 0, sizeof(mod->name)); - return 0; - } - - loadmodel = mod; - - // - // fill it in - // - - // call the apropriate loader - switch (LittleLong(*(unsigned *)buf)) - { - case IDALIASHEADER: - sys.HunkBegin (&loadmodel->pool, 0x200000); - Mod_LoadAliasModel (mod, buf); - break; - - case IDSPRITEHEADER: - sys.HunkBegin (&loadmodel->pool, 0x10000); - Mod_LoadSpriteModel (mod, buf); - break; - - case IDBSPHEADER: - sys.HunkBegin (&loadmodel->pool, 0x1000000); - Mod_LoadBrushModel (mod, buf); - break; - - default: - Com_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name); - break; - } - - - - fs.FreeFile (buf); - - return ( mod - mod_known ) + 1; -} - - -/* -=============== -Mod_PointInLeaf -=============== -*/ -mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model) -{ - mnode_t *node; - float d; - mplane_t *plane; - - if (!model || !model->nodes) - Com_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]; - } - - return NULL; // never reached -} - - -/* -=================== -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; - -#if 0 - memcpy (out, in, row); -#else - 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); -#endif - - 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 = sys.HunkAlloc (&loadmodel->pool, 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]; - } -} - -/* -================= -Mod_LoadVisibility -================= -*/ -void Mod_LoadVisibility (lump_t *l) -{ - int i; - - if (!l->filelen) - { - loadmodel->vis = NULL; - return; - } - loadmodel->vis = sys.HunkAlloc (&loadmodel->pool, 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)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, (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 +ProcessTexinfo ================= */ -void Mod_LoadSubmodels (lump_t *l) -{ - dmodel_t *in; - dmodel_t *out; - int i, j, count; +static void ProcessTexinfo( bsp_t *bsp ) { + mtexinfo_t *tex; + int i; + vec_t len1, len2; + char name[MAX_QPATH]; - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, 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)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, (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)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, (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; + tex = bsp->texinfo; + for( i = 0; i < bsp->numtexinfo; i++, tex++ ) { + len1 = VectorLength( tex->axis[0] ); + len2 = VectorLength( tex->axis[1] ); + len1 = ( len1 + len2 ) / 2; + if( len1 < 0.32 ) + tex->mipadjust = 4; + else if( len1 < 0.49 ) + tex->mipadjust = 3; + else if( len1 < 0.99 ) + tex->mipadjust = 2; else - out->mipadjust = 1; -#if 0 - if (len1 + len2 < 0.001) - out->mipadjust = 1; // don't crash - else - out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 ); -#endif - - out->flags = LittleLong (in->flags); + tex->mipadjust = 1; - next = LittleLong (in->nexttexinfo); - if (next > 0) - out->next = loadmodel->texinfo + next; - - Q_concat( name, sizeof( name ), "textures/", in->texture, ".wal", NULL ); - out->image = R_FindImage (name, it_wall); - if (!out->image) - { - out->image = r_notexture_mip; // texture not found - out->flags = 0; + Q_concat( name, sizeof( name ), "textures/", tex->name, ".wal", NULL ); + tex->image = IMG_Find( name, it_wall ); + if( !tex->image ) { + tex->image = r_notexture; // texture not found + //tex->flags = 0; } } - - // count animation frames - for (i=0 ; i<count ; i++) - { - out = &loadmodel->texinfo[i]; - out->numframes = 1; - for (step = out->next ; step && step != out ; step=step->next) - out->numframes++; - } } /* @@ -534,406 +67,74 @@ CalcSurfaceExtents Fills in s->texturemins[] and s->extents[] ================ */ -void CalcSurfaceExtents (msurface_t *s) -{ - float mins[2], maxs[2], val; - int i,j, e; +static void CalcSurfaceExtents( mface_t *s ) { + vec_t mins[2], maxs[2], val; + int i, j; + msurfedge_t *e; mvertex_t *v; mtexinfo_t *tex; int bmins[2], bmaxs[2]; mins[0] = mins[1] = 999999; - maxs[0] = maxs[1] = -99999; + maxs[0] = maxs[1] = -999999; tex = s->texinfo; - - for (i=0 ; i<s->numedges ; i++) - { - e = loadmodel->surfedges[s->firstedge+i]; - if (e >= 0) - v = &loadmodel->vertexes[loadmodel->edges[e].v[0]]; - else - v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]]; - - for (j=0 ; j<2 ; j++) - { - val = v->position[0] * tex->vecs[j][0] + - v->position[1] * tex->vecs[j][1] + - v->position[2] * tex->vecs[j][2] + - tex->vecs[j][3]; - if (val < mins[j]) + e = s->firstsurfedge; + for( i = 0; i < s->numsurfedges; i++, e++ ) { + v = e->edge->v[e->vert]; + for( j = 0; j < 2; j++ ) { + val = DotProduct( v->point, tex->axis[j] ) + tex->offset[j]; + if( val < mins[j] ) mins[j] = val; - if (val > maxs[j]) + if( val > maxs[j] ) maxs[j] = val; } } - for (i=0 ; i<2 ; i++) - { - bmins[i] = floor(mins[i]/16); - bmaxs[i] = ceil(maxs[i]/16); + 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 (s->extents[i] < 16) + s->texturemins[i] = bmins[i] << 4; + s->extents[i] = ( bmaxs[i] - bmins[i] ) << 4; + if( s->extents[i] < 16 ) { s->extents[i] = 16; // take at least one cache block - if ( !(tex->flags & (SURF_WARP|SURF_SKY)) && s->extents[i] > 256) - Com_Error (ERR_DROP,"Bad surface extents"); + } else if( s->extents[i] > 256 ) { + Com_Error( ERR_DROP, "Bad surface extents" ); + } } } /* ================= -Mod_LoadFaces +ProcessFaces ================= */ -void Mod_LoadFaces (lump_t *l) -{ - dface_t *in; - msurface_t *out; - int i, count, surfnum; - int planenum, side; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, (count+6)*sizeof(*out)); // extra for skybox - - loadmodel->surfaces = out; - loadmodel->numsurfaces = count; - - for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++) - { - out->firstedge = LittleLong(in->firstedge); - out->numedges = LittleShort(in->numedges); - if (out->numedges < 3) - Com_Error (ERR_DROP,"Surface with %d edges", out->numedges); - out->flags = 0; - - planenum = LittleShort(in->planenum); - side = LittleShort(in->side); - if (side) - out->flags |= SURF_PLANEBACK; - - out->plane = loadmodel->planes + planenum; - - out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo); - - CalcSurfaceExtents (out); - - // lighting info is converted from 24 bit on disk to 8 bit +static void ProcessFaces( bsp_t *bsp ) { + mface_t *s; + int i, j; - for (i=0 ; i<MAXLIGHTMAPS ; i++) - out->styles[i] = in->styles[i]; - i = LittleLong(in->lightofs); - if (i == -1) - out->samples = NULL; - else - out->samples = loadmodel->lightdata + i/3; - - // set the drawing flags flag - - if (!out->texinfo->image) - continue; - if (out->texinfo->flags & SURF_SKY) - { - out->flags |= SURF_DRAWSKY; + s = bsp->faces; + for( i = 0; i < bsp->numfaces; i++, s++ ) { + // set the drawing flags + if( s->texinfo->c.flags & SURF_SKY ) { continue; } - - if (out->texinfo->flags & SURF_WARP) - { - out->flags |= SURF_DRAWTURB; - for (i=0 ; i<2 ; i++) - { - out->extents[i] = 16384; - out->texturemins[i] = -8192; + if( s->texinfo->c.flags & (SURF_WARP|SURF_FLOWING) ) { + s->drawflags |= DSURF_TURB; + for( j = 0; j < 2; j++ ) { + s->extents[j] = 16384; + s->texturemins[j] = -8192; } continue; } -//============== -//PGM - // this marks flowing surfaces as turbulent, but with the new - // SURF_FLOW flag. - if (out->texinfo->flags & SURF_FLOWING) - { - out->flags |= SURF_DRAWTURB | SURF_FLOW; - for (i=0 ; i<2 ; i++) - { - out->extents[i] = 16384; - out->texturemins[i] = -8192; - } - continue; - } -//PGM -//============== - } -} - - -/* -================= -Mod_SetParent -================= -*/ -void Mod_SetParent (mnode_t *node, mnode_t *parent) -{ - node->parent = parent; - if (node->contents != -1) - return; - Mod_SetParent (node->children[0], node); - Mod_SetParent (node->children[1], node); -} - -/* -================= -Mod_LoadNodes -================= -*/ -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)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, count*sizeof(*out)); - - loadmodel->nodes = out; - loadmodel->numnodes = count; - - for ( i=0 ; i<count ; i++, in++, out++) - { - for (j=0 ; j<3 ; j++) - { - out->minmaxs[j] = ( signed short )LittleShort (in->mins[j]); - out->minmaxs[3+j] = ( signed short )LittleShort (in->maxs[j]); - } - - p = LittleLong(in->planenum); - out->plane = loadmodel->planes + p; - - out->firstsurface = LittleShort (in->firstface); - out->numsurfaces = LittleShort (in->numfaces); - out->contents = CONTENTS_NODE; // differentiate from leafs - - for (j=0 ; j<2 ; j++) - { - p = LittleLong (in->children[j]); - if (p >= 0) - out->children[j] = loadmodel->nodes + p; - else - out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p)); - } - } - - Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs -} - -/* -================= -Mod_LoadLeafs -================= -*/ -void Mod_LoadLeafs (lump_t *l) -{ - dleaf_t *in; - mleaf_t *out; - int i, j, count; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, count*sizeof(*out)); - - loadmodel->leafs = out; - loadmodel->numleafs = count; - - for ( i=0 ; i<count ; i++, in++, out++) - { - for (j=0 ; j<3 ; j++) - { - out->minmaxs[j] = ( signed short )LittleShort (in->mins[j]); - out->minmaxs[3+j] = ( signed short )LittleShort (in->maxs[j]); - } - - out->contents = LittleLong(in->contents); - out->cluster = LittleShort(in->cluster); - out->area = LittleShort(in->area); - - out->firstmarksurface = loadmodel->marksurfaces + - LittleShort(in->firstleafface); - out->nummarksurfaces = LittleShort(in->numleaffaces); - } -} - - -/* -================= -Mod_LoadMarksurfaces -================= -*/ -void Mod_LoadMarksurfaces (lump_t *l) -{ - int i, j, count; - short *in; - msurface_t **out; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, count*sizeof(*out)); - - loadmodel->marksurfaces = out; - loadmodel->nummarksurfaces = count; - - for ( i=0 ; i<count ; i++) - { - j = LittleShort(in[i]); - if (j >= loadmodel->numsurfaces) - Com_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number"); - out[i] = loadmodel->surfaces + j; + CalcSurfaceExtents( s ); } } -/* -================= -Mod_LoadSurfedges -================= -*/ -void Mod_LoadSurfedges (lump_t *l) -{ - int i, count; - int *in, *out; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, (count+24)*sizeof(*out)); // extra for skybox - loadmodel->surfedges = out; - loadmodel->numsurfedges = count; - for ( i=0 ; i<count ; i++) - out[i] = LittleLong (in[i]); -} - -/* -================= -Mod_LoadPlanes -================= -*/ -void Mod_LoadPlanes (lump_t *l) -{ - int i, j; - mplane_t *out; - dplane_t *in; - int count; - int bits; - - in = (void *)(mod_base + l->fileofs); - if (l->filelen % sizeof(*in)) - Com_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name); - count = l->filelen / sizeof(*in); - out = sys.HunkAlloc (&loadmodel->pool, (count+6)*sizeof(*out)); // extra for skybox - - loadmodel->planes = out; - loadmodel->numplanes = count; - - for ( i=0 ; i<count ; i++, in++, out++) - { - bits = 0; - for (j=0 ; j<3 ; j++) - { - out->normal[j] = LittleFloat (in->normal[j]); - if (out->normal[j] < 0) - bits |= 1<<j; - } - - out->dist = LittleFloat (in->dist); - out->type = LittleLong (in->type); - out->signbits = bits; - } -} - - -/* -================= -Mod_LoadBrushModel -================= -*/ -void Mod_LoadBrushModel (model_t *mod, void *buffer) -{ - int i; - dheader_t *header; - dmodel_t *bm; - - loadmodel->type = mod_brush; - if (loadmodel != mod_known) - Com_Error (ERR_DROP, "Loaded a brush model after the world"); - - header = (dheader_t *)buffer; - - i = LittleLong (header->version); - if (i != BSPVERSION) - Com_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 ; i<sizeof(dheader_t)/4 ; i++) - ((int *)header)[i] = LittleLong ( ((int *)header)[i]); - -// load into heap - - Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]); - Mod_LoadEdges (&header->lumps[LUMP_EDGES]); - Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]); - Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]); - Mod_LoadPlanes (&header->lumps[LUMP_PLANES]); - Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]); - Mod_LoadFaces (&header->lumps[LUMP_FACES]); - Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]); - Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]); - Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]); - Mod_LoadNodes (&header->lumps[LUMP_NODES]); - Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]); - -// -// set up the submodels -// - for (i=0 ; i<mod->numsubmodels ; i++) - { - model_t *starmod; - - bm = &mod->submodels[i]; - starmod = &mod_inline[i]; - - *starmod = *loadmodel; - - starmod->firstmodelsurface = bm->firstface; - starmod->nummodelsurfaces = bm->numfaces; - starmod->firstnode = bm->headnode; - if (starmod->firstnode >= loadmodel->numnodes) - Com_Error (ERR_DROP, "Inline model %i has bad firstnode", i); - - VectorCopy (bm->maxs, starmod->maxs); - VectorCopy (bm->mins, starmod->mins); - - if (i == 0) - *loadmodel = *starmod; - } - - R_InitSkyBox (); -} /* ============================================================================== @@ -948,166 +149,129 @@ ALIAS MODELS Mod_LoadAliasModel ================= */ -void Mod_LoadAliasModel (model_t *mod, void *buffer) -{ - int i, j; - dmdl_t *pinmodel, *pheader; - dstvert_t *pinst, *poutst; - dtriangle_t *pintri, *pouttri; - daliasframe_t *pinframe, *poutframe; - int *pincmd, *poutcmd; - int version; - - pinmodel = (dmdl_t *)buffer; - - version = LittleLong (pinmodel->version); - if (version != ALIAS_VERSION) - Com_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", - mod->name, version, ALIAS_VERSION); - - pheader = sys.HunkAlloc (&mod->pool, LittleLong(pinmodel->ofs_end)); - - // byte swap the header fields and sanity check - for (i=0 ; i<sizeof(dmdl_t)/4 ; i++) - ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]); - - if (pheader->skinheight > MAX_LBM_HEIGHT) - Com_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name, - MAX_LBM_HEIGHT); - - if (pheader->num_xyz <= 0) - Com_Error (ERR_DROP, "model %s has no vertices", mod->name); - - if (pheader->num_xyz > MAX_VERTS) - Com_Error (ERR_DROP, "model %s has too many vertices", mod->name); - - if (pheader->num_st <= 0) - Com_Error (ERR_DROP, "model %s has no st vertices", mod->name); - - if (pheader->num_tris <= 0) - Com_Error (ERR_DROP, "model %s has no triangles", mod->name); - - if (pheader->num_frames <= 0) - Com_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 ; i<pheader->num_st ; i++) - { - poutst[i].s = ( signed short )LittleShort (pinst[i].s); - poutst[i].t = ( signed short )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 ; i<pheader->num_tris ; i++) - { - for (j=0 ; j<3 ; j++) - { - pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]); - pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]); - } - } - -// -// load the frames -// - for (i=0 ; i<pheader->num_frames ; i++) - { - pinframe = (daliasframe_t *) ((byte *)pinmodel - + 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++) - { - poutframe->scale[j] = LittleFloat (pinframe->scale[j]); - poutframe->translate[j] = LittleFloat (pinframe->translate[j]); +qboolean MOD_LoadMD2( model_t *model, const void *rawdata, size_t length ) { + dmd2header_t header; + dmd2frame_t *src_frame; + //dmd2trivertx_t *src_vert; + dmd2triangle_t *src_tri; + dmd2stvert_t *src_st; + maliasframe_t *dst_frame; + //maliasvert_t *dst_vert; + maliastri_t *dst_tri; + maliasst_t *dst_st; + char skinname[MAX_QPATH]; + char *src_skin; + image_t *skin; + int i, j; + + if( length < sizeof( header ) ) { + Com_WPrintf( "%s is too short\n", model->name ); + return qfalse; + } + + /* byte swap the header */ + header = *( dmd2header_t * )rawdata; + for( i = 0; i < sizeof( header )/4; i++ ) { + (( uint32_t * )&header)[i] = LittleLong( (( uint32_t * )&header)[i] ); + } + + if( !MOD_ValidateMD2( model, &header, length ) ) { + return qfalse; + } + + Hunk_Begin( &model->pool, 0x400000 ); + + // load triangle indices + model->tris = Model_Malloc( header.num_tris * sizeof( maliastri_t ) ); + model->numtris = header.num_tris; + + src_tri = ( dmd2triangle_t * )( ( byte * )rawdata + header.ofs_tris ); + dst_tri = model->tris; + for( i = 0; i < header.num_tris; i++, src_tri++, dst_tri++ ) { + for( j = 0; j < 3; j++ ) { + unsigned idx_xyz = LittleShort( src_tri->index_xyz[j] ); + unsigned idx_st = LittleShort( src_tri->index_st[j] ); + + if( idx_xyz >= header.num_xyz || idx_st >= header.num_st ) { + Com_WPrintf( "%s has bad triangle indices\n", model->name ); + goto fail; + } + + dst_tri->index_xyz[j] = idx_xyz; + dst_tri->index_st[j] = idx_st; + } + } + + // load base s and t vertices + model->sts = Model_Malloc( header.num_st * sizeof( maliasst_t ) ); + model->numsts = header.num_st; + + src_st = ( dmd2stvert_t * )( ( byte * )rawdata + header.ofs_st ); + dst_st = model->sts; + for( i = 0; i < header.num_st; i++, src_st++, dst_st++ ) { + dst_st->s = ( signed short )LittleShort( src_st->s ); + dst_st->t = ( signed short )LittleShort( src_st->t ); + } + + // load the frames + model->frames = Model_Malloc( header.num_frames * sizeof( maliasframe_t ) ); + model->numframes = header.num_frames; + model->numverts = header.num_xyz; + + src_frame = ( dmd2frame_t * )( ( byte * )rawdata + header.ofs_frames ); + dst_frame = model->frames; + for( i = 0; i < header.num_frames; i++, dst_frame++ ) { + for( j = 0; j < 3; j++ ) { + dst_frame->scale[j] = LittleFloat( src_frame->scale[j] ); + dst_frame->translate[j] = LittleFloat( src_frame->translate[j] ); } // verts are all 8 bit, so no swapping needed - memcpy (poutframe->verts, pinframe->verts, - pheader->num_xyz*sizeof(dtrivertx_t)); + dst_frame->verts = Model_Malloc( header.num_xyz * sizeof( maliasvert_t ) ); + + // TODO: check normal indices + memcpy( dst_frame->verts, src_frame->verts, header.num_xyz * sizeof( maliasvert_t ) ); + src_frame = ( dmd2frame_t * )( ( byte * )src_frame + header.framesize ); } - mod->type = mod_alias; - - // - // load the glcmds - // - pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds); - poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds); - for (i=0 ; i<pheader->num_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); - for (i=0 ; i<pheader->num_skins ; i++) - { - mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); + src_skin = ( char * )rawdata + header.ofs_skins; + for( i = 0; i < header.num_skins; i++ ) { + Q_strncpyz( skinname, src_skin, sizeof( skinname ) ); + skin = IMG_Find( skinname, it_skin ); + if( !skin ) { + skin = r_notexture; + } + model->skins[i] = skin; + src_skin += MD2_MAX_SKINNAME; } -} - -/* -============================================================================== + model->numskins = header.num_skins; -SPRITE MODELS + Hunk_End( &model->pool ); + return qtrue; -============================================================================== -*/ - -/* -================= -Mod_LoadSpriteModel -================= -*/ -void Mod_LoadSpriteModel (model_t *mod, void *buffer) -{ - dsprite_t *sprin, *sprout; - int i; - - sprin = (dsprite_t *)buffer; - sprout = sys.HunkAlloc(&mod->pool, modfilelen); - - sprout->ident = LittleLong (sprin->ident); - sprout->version = LittleLong (sprin->version); - sprout->numframes = LittleLong (sprin->numframes); - - if (sprout->version != SPRITE_VERSION) - Com_Error (ERR_DROP, "%s has wrong version number (%i should be %i)", - mod->name, sprout->version, SPRITE_VERSION); +fail: + Hunk_Free( &model->pool ); + return qfalse; +} - if (sprout->numframes > MAX_MD2SKINS) - Com_Error (ERR_DROP, "%s has too many frames (%i > %i)", - mod->name, sprout->numframes, MAX_MD2SKINS); +void MOD_Reference( model_t *model ) { + int i; - // byte swap everything - for (i=0 ; i<sprout->numframes ; i++) - { - sprout->frames[i].width = LittleLong (sprin->frames[i].width); - sprout->frames[i].height = LittleLong (sprin->frames[i].height); - sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x); - sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y); - memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME); - mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite); - } + model->registration_sequence = registration_sequence; - mod->type = mod_sprite; + // register any images used by the models + if( model->frames ) { + for( i = 0; i < model->numskins; i++ ) { + model->skins[i]->registration_sequence = registration_sequence; + } + } else if( model->spriteframes ) { + for( i = 0; i < model->numframes; i++ ) { + model->spriteframes[i].image->registration_sequence = registration_sequence; + } + } } -//============================================================================= - /* @@@@@@@@@@@@@@@@@@@@@ R_BeginRegistration @@ -1117,121 +281,43 @@ Specifies the model that will be used as the world */ void R_BeginRegistration( const char *model ) { char fullname[MAX_QPATH]; - cvar_t *flushmap; + bsp_t *bsp; registration_sequence++; r_oldviewcluster = -1; // force markleafs Q_concat( fullname, sizeof( fullname ), "maps/", model, ".bsp", NULL ); D_FlushCaches (); - // explicitly free the old map if different - // this guarantees that mod_known[0] is the world map - flushmap = cvar.Get ("flushmap", "0", 0); - if ( mod_known[0].name[0] && ( strcmp(mod_known[0].name, fullname) || flushmap->integer )) - Mod_Free (&mod_known[0]); - r_worldmodel = R_ModelForHandle ( R_RegisterModel( fullname ) ); + bsp = BSP_Load( fullname ); + if( bsp == r_worldmodel ) { + mtexinfo_t *tex = bsp->texinfo; + int i; + + for( i = 0; i < bsp->numtexinfo; i++, tex++ ) { + tex->image->registration_sequence = registration_sequence; + } + bsp->refcount--; + return; + } + BSP_Free( r_worldmodel ); + r_worldmodel = bsp; + + ProcessTexinfo( bsp ); + ProcessFaces( bsp ); + + // TODO R_NewMap (); } - -/* -@@@@@@@@@@@@@@@@@@@@@ -R_RegisterModel - -@@@@@@@@@@@@@@@@@@@@@ -*/ -qhandle_t R_RegisterModel( const char *name ) { - model_t *mod; - qhandle_t hModel; - int i; - dsprite_t *sprout; - dmdl_t *pheader; - - hModel = Mod_ForName (name, qfalse); - if( ( mod = R_ModelForHandle( hModel ) ) != NULL ) - { - mod->registration_sequence = registration_sequence; - - // register any images used by the models - if (mod->type == mod_sprite) - { - sprout = (dsprite_t *)mod->pool.base; - for (i=0 ; i<sprout->numframes ; i++) - mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite); - } - else if (mod->type == mod_alias) - { - pheader = (dmdl_t *)mod->pool.base; - for (i=0 ; i<pheader->num_skins ; i++) - mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin); -//PGM - mod->numframes = pheader->num_frames; -//PGM - } - else if (mod->type == mod_brush) - { - for (i=0 ; i<mod->numtexinfo ; i++) - mod->texinfo[i].image->registration_sequence = registration_sequence; - } - } - return hModel; -} - /* @@@@@@@@@@@@@@@@@@@@@ R_EndRegistration @@@@@@@@@@@@@@@@@@@@@ */ -void R_EndRegistration (void) -{ - int i; - model_t *mod; - - for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++) - { - if (!mod->name[0]) - continue; - if (mod->registration_sequence != registration_sequence) - { // don't need this model - Mod_Free( mod ); - } - else - { // make sure it is paged in - Com_PageInMemory (mod->pool.base, mod->pool.cursize); - } - } - - R_FreeUnusedImages (); +void R_EndRegistration (void) { + MOD_FreeUnused(); + IMG_FreeUnused(); } -//============================================================================= - -/* -================ -Mod_Free -================ -*/ -void Mod_Free (model_t *mod) -{ - sys.HunkFree (&mod->pool); - memset (mod, 0, sizeof(*mod)); -} - -/* -================ -Mod_FreeAll -================ -*/ -void Mod_FreeAll (void) -{ - int i; - model_t *mod; - - for (i=0, mod = mod_known ; i<mod_numknown ; i++, mod++) - { - if (mod->name[0]) - Mod_Free (mod); - } -} |