cmodel.cpp
来自「hl2 source code. Do not use it illegal.」· C++ 代码 · 共 1,817 行 · 第 1/3 页
CPP
1,817 行
// cmodel.cpp -- model loading
#include "qfiles.h"
#include "cmdlib.h"
#include "mathlib.h"
#include "cmodel_engine.h"
#include "engine.h"
typedef struct
{
cplane_t *plane;
int children[2]; // negative numbers are leafs
} cnode_t;
typedef struct
{
cplane_t *plane;
csurface_t *surface;
} cbrushside_t;
typedef struct cleaf_s
{
int contents;
int cluster;
int area;
unsigned short firstleafbrush;
unsigned short numleafbrushes;
} cleaf_t;
typedef struct cbrush_s
{
int contents;
int numsides;
int firstbrushside;
int checkcount; // to avoid repeated testings
} cbrush_t;
typedef struct carea_s
{
int numareaportals;
int firstareaportal;
int floodnum; // if two areas have equal floodnums, they are connected
int floodvalid;
} carea_t;
static int checkcount;
static char map_name[MAX_QPATH];
static int numbrushsides;
static cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES];
static int numtexinfo;
static csurface_t map_surfaces[MAX_MAP_TEXINFO];
static int numplanes;
static cplane_t map_planes[MAX_MAP_PLANES+6]; // extra for box hull
static int numnodes;
static cnode_t map_nodes[MAX_MAP_NODES+6]; // extra for box hull
static int numleafs = 1; // allow leaf funcs to be called without a map
static cleaf_t map_leafs[MAX_MAP_LEAFS];
static int emptyleaf, solidleaf;
static int numleafbrushes;
static unsigned short map_leafbrushes[MAX_MAP_LEAFBRUSHES];
static int numcmodels;
static cmodel_t map_cmodels[MAX_MAP_MODELS];
static int numbrushes;
static cbrush_t map_brushes[MAX_MAP_BRUSHES];
static int numvisibility;
static byte map_visibility[MAX_MAP_VISIBILITY];
static dvis_t *map_vis = (dvis_t *)map_visibility;
static int numentitychars;
static char map_entitystring[MAX_MAP_ENTSTRING];
static int numareas = 1;
static carea_t map_areas[MAX_MAP_AREAS];
static int numareaportals;
static dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS];
static int numclusters = 1;
static csurface_t nullsurface;
static int floodvalid;
static qboolean portalopen[MAX_MAP_AREAPORTALS];
static cvar_t map_noareas;
void CM_InitBoxHull (void);
void FloodAreaConnections (void);
static int c_pointcontents;
static int c_traces, c_brush_traces;
typedef struct cmodel_collision_s
{
cmodel_t *pmodels;
int modelCount;
cplane_t *pplanes;
int planeCount;
cnode_t *pnodes;
int nodeCount;
cleaf_t *pleafs;
int leafCount;
} cmodel_collision_t;
void CM_GetCollisionModel( cmodel_collision_t *pcollide )
{
pcollide->pmodels = map_cmodels;
pcollide->modelCount = numcmodels;
pcollide->pplanes = map_planes;
pcollide->planeCount = numplanes;
pcollide->pnodes = map_nodes;
pcollide->nodeCount = numnodes;
pcollide->pleafs = map_leafs;
pcollide->leafCount = numleafs;
}
/*
===============================================================================
MAP LOADING
===============================================================================
*/
static byte *cmod_base;
/*
=================
CMod_LoadSubmodels
=================
*/
void CMod_LoadSubmodels (lump_t *l)
{
dmodel_t *in;
cmodel_t *out;
int i, j, count;
in = (dmodel_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error("MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count < 1)
engine.Error( "Map with no models" );
if (count > MAX_MAP_MODELS)
engine.Error( "Map has too many models" );
numcmodels = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out = &map_cmodels[i];
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);
}
}
/*
=================
CMod_LoadSurfaces
=================
*/
void CMod_LoadSurfaces( lump_t *l, dtexdata_t *pTexData, int texDataCount,
char* pStringData, const int* pStringTable )
{
texinfo_t *in;
csurface_t *out;
int i, count;
in = (texinfo_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count < 1)
engine.Error( "Map with no surfaces");
if (count > MAX_MAP_TEXINFO)
engine.Error( "Map has too many surfaces");
numtexinfo = count;
out = map_surfaces;
for ( i=0 ; i<count ; i++, in++, out++)
{
if ( in->texdata < texDataCount )
{
int texNameId = pTexData[in->texdata].nameStringTableID;
strncpy( out->name, &pStringData[pStringTable[texNameId]], sizeof(out->name)-1);
}
out->flags = LittleLong (in->flags);
}
}
/*
=================
CMod_LoadNodes
=================
*/
void CMod_LoadNodes (lump_t *l)
{
dnode_t *in;
int child;
cnode_t *out;
int i, j, count;
in = (dnode_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count < 1)
engine.Error( "Map has no nodes");
if (count > MAX_MAP_NODES)
engine.Error( "Map has too many nodes");
out = map_nodes;
numnodes = count;
for (i=0 ; i<count ; i++, out++, in++)
{
out->plane = map_planes + LittleLong(in->planenum);
for (j=0 ; j<2 ; j++)
{
child = LittleLong (in->children[j]);
out->children[j] = child;
}
}
}
/*
=================
CMod_LoadBrushes
=================
*/
void CMod_LoadBrushes (lump_t *l)
{
dbrush_t *in;
cbrush_t *out;
int i, count;
in = (dbrush_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count > MAX_MAP_BRUSHES)
engine.Error( "Map has too many brushes");
out = map_brushes;
numbrushes = count;
for (i=0 ; i<count ; i++, out++, in++)
{
out->firstbrushside = LittleLong(in->firstside);
out->numsides = LittleLong(in->numsides);
out->contents = LittleLong(in->contents);
}
}
/*
=================
CMod_LoadLeafs
=================
*/
void CMod_LoadLeafs (lump_t *l)
{
int i;
cleaf_t *out;
dleaf_t *in;
int count;
in = (dleaf_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count < 1)
engine.Error( "Map with no leafs");
// need to save space for box planes
if (count > MAX_MAP_PLANES)
engine.Error( "Map has too many planes");
out = map_leafs;
numleafs = count;
numclusters = 0;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->contents = LittleLong (in->contents);
out->cluster = LittleShort (in->cluster);
out->area = LittleShort (in->area);
out->firstleafbrush = (unsigned short)LittleShort (in->firstleafbrush);
out->numleafbrushes = (unsigned short)LittleShort (in->numleafbrushes);
if (out->cluster >= numclusters)
numclusters = out->cluster + 1;
}
if (map_leafs[0].contents != CONTENTS_SOLID)
engine.Error( "Map leaf 0 is not CONTENTS_SOLID");
solidleaf = 0;
emptyleaf = -1;
for (i=1 ; i<numleafs ; i++)
{
if (!map_leafs[i].contents)
{
emptyleaf = i;
break;
}
}
if (emptyleaf == -1)
engine.Error( "Map does not have an empty leaf");
}
/*
=================
CMod_LoadPlanes
=================
*/
void CMod_LoadPlanes (lump_t *l)
{
int i, j;
cplane_t *out;
dplane_t *in;
int count;
int bits;
in = (dplane_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count < 1)
engine.Error( "Map with no planes");
// need to save space for box planes
if (count > MAX_MAP_PLANES)
engine.Error( "Map has too many planes");
out = map_planes;
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;
}
}
/*
=================
CMod_LoadLeafBrushes
=================
*/
void CMod_LoadLeafBrushes (lump_t *l)
{
int i;
unsigned short *out;
unsigned short *in;
int count;
in = (unsigned short *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count < 1)
engine.Error( "Map with no planes");
// need to save space for box planes
if (count > MAX_MAP_LEAFBRUSHES)
engine.Error( "Map has too many leafbrushes");
out = map_leafbrushes;
numleafbrushes = count;
for ( i=0 ; i<count ; i++, in++, out++)
*out = (unsigned short)LittleShort (*in);
}
/*
=================
CMod_LoadBrushSides
=================
*/
void CMod_LoadBrushSides (lump_t *l)
{
int i, j;
cbrushside_t *out;
dbrushside_t *in;
int count;
int num;
in = (dbrushside_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
// need to save space for box planes
if (count > MAX_MAP_BRUSHSIDES)
engine.Error( "Map has too many planes");
out = map_brushsides;
numbrushsides = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
num = (unsigned short)LittleShort (in->planenum);
out->plane = &map_planes[num];
j = LittleShort (in->texinfo);
if (j >= numtexinfo)
engine.Error( "Bad brushside texinfo");
out->surface = &map_surfaces[j];
}
}
/*
=================
CMod_LoadAreas
=================
*/
void CMod_LoadAreas (lump_t *l)
{
int i;
carea_t *out;
darea_t *in;
int count;
in = (darea_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count > MAX_MAP_AREAS)
engine.Error( "Map has too many areas");
out = map_areas;
numareas = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->numareaportals = LittleLong (in->numareaportals);
out->firstareaportal = LittleLong (in->firstareaportal);
out->floodvalid = 0;
out->floodnum = 0;
}
}
/*
=================
CMod_LoadAreaPortals
=================
*/
void CMod_LoadAreaPortals (lump_t *l)
{
int i;
dareaportal_t *out;
dareaportal_t *in;
int count;
in = (dareaportal_t *)(cmod_base + l->fileofs);
if (l->filelen % sizeof(*in))
engine.Error( "MOD_LoadBmodel: funny lump size");
count = l->filelen / sizeof(*in);
if (count > MAX_MAP_AREAS)
engine.Error( "Map has too many areas");
out = map_areaportals;
numareaportals = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->portalnum = LittleLong (in->portalnum);
out->otherarea = LittleLong (in->otherarea);
}
}
/*
=================
CMod_LoadVisibility
=================
*/
void CMod_LoadVisibility (lump_t *l)
{
int i;
numvisibility = l->filelen;
if (l->filelen > MAX_MAP_VISIBILITY)
engine.Error( "Map has too large visibility lump");
memcpy (map_visibility, cmod_base + l->fileofs, l->filelen);
map_vis->numclusters = LittleLong (map_vis->numclusters);
for (i=0 ; i<map_vis->numclusters ; i++)
{
map_vis->bitofs[i][0] = LittleLong (map_vis->bitofs[i][0]);
map_vis->bitofs[i][1] = LittleLong (map_vis->bitofs[i][1]);
}
}
/*
=================
CMod_LoadEntityString
=================
*/
void CMod_LoadEntityString (lump_t *l)
{
numentitychars = l->filelen;
if (l->filelen > MAX_MAP_ENTSTRING)
engine.Error( "Map has too large entity lump");
memcpy( map_entitystring, cmod_base + l->fileofs, l->filelen );
}
/*
==================
CM_LoadMap
Loads in the map and all submodels
==================
*/
cmodel_t *CM_LoadMap( char *name, qboolean clientload, unsigned *checksum )
{
unsigned *buf;
int i;
dheader_t header;
int length;
static unsigned last_checksum;
// UNDONE: Don't load the map twice - call this from a function that loads once,
// parses this part first, then parses/copies the renderer data
// JAY: Later
// map_noareas = Cvar_Get ("map_noareas", "0", 0);
if ( !strcmp (map_name, name) && (clientload /*|| !Cvar_VariableValue ("flushmap")*/) )
{
*checksum = last_checksum;
if (!clientload)
{
memset (portalopen, 0, sizeof(portalopen));
FloodAreaConnections ();
}
return &map_cmodels[0]; // still have the right version
}
// free old stuff
numplanes = 0;
numnodes = 0;
numleafs = 0;
numcmodels = 0;
numvisibility = 0;
numentitychars = 0;
map_entitystring[0] = 0;
map_name[0] = 0;
if (!name || !name[0])
{
numleafs = 1;
numclusters = 1;
numareas = 1;
*checksum = 0;
return &map_cmodels[0]; // cinematic servers won't have anything at all
}
//
// load the file
//
length = engine.LoadFile( name, (void **)&buf );
if (!buf)
engine.Error( "Couldn't load %s", name);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?