summaryrefslogtreecommitdiff
path: root/source/sw_model.c
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2008-08-16 10:19:42 +0000
committerAndrey Nazarov <skuller@skuller.net>2008-08-16 10:19:42 +0000
commit1526e22e4ff29153e9c127081e8ea8d9e2f33b8c (patch)
treeb361766433d4a7b4a111865afd52803e2bbf7754 /source/sw_model.c
parente826e5f176f21cd18b3bbc22887a266835ada57c (diff)
Split some monolithic include files into smaller ones.
Use single BSP models cache for refresh and collision subsystems. Refresh libraries may not longer be dynamically loaded. Made gi.TagMalloc use separate tag namespace to avoid conflicts with engine reserverd tags. Fixed listing order of MVD channels in chooser menu. A lot of misc changes... MSVC build is definitely broken now.
Diffstat (limited to 'source/sw_model.c')
-rw-r--r--source/sw_model.c1292
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);
- }
-}