summaryrefslogtreecommitdiff
path: root/source/sw_model.c
diff options
context:
space:
mode:
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);
- }
-}