📄 cm_load.c
字号:
cm.brushsides = Hunk_Alloc( ( BOX_SIDES + count ) * sizeof( *cm.brushsides ), h_high );
cm.numBrushSides = count;
out = cm.brushsides;
for ( i=0 ; i<count ; i++, in++, out++) {
num = LittleLong( in->planeNum );
out->plane = &cm.planes[num];
out->shaderNum = LittleLong( in->shaderNum );
if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) {
Com_Error( ERR_DROP, "CMod_LoadBrushSides: bad shaderNum: %i", out->shaderNum );
}
out->surfaceFlags = cm.shaders[out->shaderNum].surfaceFlags;
}
}
/*
=================
CMod_LoadEntityString
=================
*/
void CMod_LoadEntityString( lump_t *l ) {
cm.entityString = Hunk_Alloc( l->filelen, h_high );
cm.numEntityChars = l->filelen;
Com_Memcpy (cm.entityString, cmod_base + l->fileofs, l->filelen);
}
/*
=================
CMod_LoadVisibility
=================
*/
#define VIS_HEADER 8
void CMod_LoadVisibility( lump_t *l ) {
int len;
byte *buf;
len = l->filelen;
if ( !len ) {
cm.clusterBytes = ( cm.numClusters + 31 ) & ~31;
cm.visibility = Hunk_Alloc( cm.clusterBytes, h_high );
Com_Memset( cm.visibility, 255, cm.clusterBytes );
return;
}
buf = cmod_base + l->fileofs;
cm.vised = qtrue;
cm.visibility = Hunk_Alloc( len, h_high );
cm.numClusters = LittleLong( ((int *)buf)[0] );
cm.clusterBytes = LittleLong( ((int *)buf)[1] );
Com_Memcpy (cm.visibility, buf + VIS_HEADER, len - VIS_HEADER );
}
//==================================================================
/*
=================
CMod_LoadPatches
=================
*/
#define MAX_PATCH_VERTS 1024
void CMod_LoadPatches( lump_t *surfs, lump_t *verts ) {
drawVert_t *dv, *dv_p;
dsurface_t *in;
int count;
int i, j;
int c;
cPatch_t *patch;
vec3_t points[MAX_PATCH_VERTS];
int width, height;
int shaderNum;
in = (void *)(cmod_base + surfs->fileofs);
if (surfs->filelen % sizeof(*in))
Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
cm.numSurfaces = count = surfs->filelen / sizeof(*in);
cm.surfaces = Hunk_Alloc( cm.numSurfaces * sizeof( cm.surfaces[0] ), h_high );
dv = (void *)(cmod_base + verts->fileofs);
if (verts->filelen % sizeof(*dv))
Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
// scan through all the surfaces, but only load patches,
// not planar faces
for ( i = 0 ; i < count ; i++, in++ ) {
if ( LittleLong( in->surfaceType ) != MST_PATCH ) {
continue; // ignore other surfaces
}
// FIXME: check for non-colliding patches
cm.surfaces[ i ] = patch = Hunk_Alloc( sizeof( *patch ), h_high );
// load the full drawverts onto the stack
width = LittleLong( in->patchWidth );
height = LittleLong( in->patchHeight );
c = width * height;
if ( c > MAX_PATCH_VERTS ) {
Com_Error( ERR_DROP, "ParseMesh: MAX_PATCH_VERTS" );
}
dv_p = dv + LittleLong( in->firstVert );
for ( j = 0 ; j < c ; j++, dv_p++ ) {
points[j][0] = LittleFloat( dv_p->xyz[0] );
points[j][1] = LittleFloat( dv_p->xyz[1] );
points[j][2] = LittleFloat( dv_p->xyz[2] );
}
shaderNum = LittleLong( in->shaderNum );
patch->contents = cm.shaders[shaderNum].contentFlags;
patch->surfaceFlags = cm.shaders[shaderNum].surfaceFlags;
// create the internal facet structure
patch->pc = CM_GeneratePatchCollide( width, height, points );
}
}
//==================================================================
unsigned CM_LumpChecksum(lump_t *lump) {
return LittleLong (Com_BlockChecksum (cmod_base + lump->fileofs, lump->filelen));
}
unsigned CM_Checksum(dheader_t *header) {
unsigned checksums[16];
checksums[0] = CM_LumpChecksum(&header->lumps[LUMP_SHADERS]);
checksums[1] = CM_LumpChecksum(&header->lumps[LUMP_LEAFS]);
checksums[2] = CM_LumpChecksum(&header->lumps[LUMP_LEAFBRUSHES]);
checksums[3] = CM_LumpChecksum(&header->lumps[LUMP_LEAFSURFACES]);
checksums[4] = CM_LumpChecksum(&header->lumps[LUMP_PLANES]);
checksums[5] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHSIDES]);
checksums[6] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHES]);
checksums[7] = CM_LumpChecksum(&header->lumps[LUMP_MODELS]);
checksums[8] = CM_LumpChecksum(&header->lumps[LUMP_NODES]);
checksums[9] = CM_LumpChecksum(&header->lumps[LUMP_SURFACES]);
checksums[10] = CM_LumpChecksum(&header->lumps[LUMP_DRAWVERTS]);
return LittleLong(Com_BlockChecksum(checksums, 11 * 4));
}
/*
==================
CM_LoadMap
Loads in the map and all submodels
==================
*/
void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) {
int *buf;
int i;
dheader_t header;
int length;
static unsigned last_checksum;
if ( !name || !name[0] ) {
Com_Error( ERR_DROP, "CM_LoadMap: NULL name" );
}
#ifndef BSPC
cm_noAreas = Cvar_Get ("cm_noAreas", "0", CVAR_CHEAT);
cm_noCurves = Cvar_Get ("cm_noCurves", "0", CVAR_CHEAT);
cm_playerCurveClip = Cvar_Get ("cm_playerCurveClip", "1", CVAR_ARCHIVE|CVAR_CHEAT );
#endif
Com_DPrintf( "CM_LoadMap( %s, %i )\n", name, clientload );
if ( !strcmp( cm.name, name ) && clientload ) {
*checksum = last_checksum;
return;
}
// free old stuff
Com_Memset( &cm, 0, sizeof( cm ) );
CM_ClearLevelPatches();
if ( !name[0] ) {
cm.numLeafs = 1;
cm.numClusters = 1;
cm.numAreas = 1;
cm.cmodels = Hunk_Alloc( sizeof( *cm.cmodels ), h_high );
*checksum = 0;
return;
}
//
// load the file
//
#ifndef BSPC
length = FS_ReadFile( name, (void **)&buf );
#else
length = LoadQuakeFile((quakefile_t *) name, (void **)&buf);
#endif
if ( !buf ) {
Com_Error (ERR_DROP, "Couldn't load %s", name);
}
last_checksum = LittleLong (Com_BlockChecksum (buf, length));
*checksum = last_checksum;
header = *(dheader_t *)buf;
for (i=0 ; i<sizeof(dheader_t)/4 ; i++) {
((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
}
if ( header.version != BSP_VERSION ) {
Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be %i)"
, name, header.version, BSP_VERSION );
}
cmod_base = (byte *)buf;
// load into heap
CMod_LoadShaders( &header.lumps[LUMP_SHADERS] );
CMod_LoadLeafs (&header.lumps[LUMP_LEAFS]);
CMod_LoadLeafBrushes (&header.lumps[LUMP_LEAFBRUSHES]);
CMod_LoadLeafSurfaces (&header.lumps[LUMP_LEAFSURFACES]);
CMod_LoadPlanes (&header.lumps[LUMP_PLANES]);
CMod_LoadBrushSides (&header.lumps[LUMP_BRUSHSIDES]);
CMod_LoadBrushes (&header.lumps[LUMP_BRUSHES]);
CMod_LoadSubmodels (&header.lumps[LUMP_MODELS]);
CMod_LoadNodes (&header.lumps[LUMP_NODES]);
CMod_LoadEntityString (&header.lumps[LUMP_ENTITIES]);
CMod_LoadVisibility( &header.lumps[LUMP_VISIBILITY] );
CMod_LoadPatches( &header.lumps[LUMP_SURFACES], &header.lumps[LUMP_DRAWVERTS] );
// we are NOT freeing the file, because it is cached for the ref
FS_FreeFile (buf);
CM_InitBoxHull ();
CM_FloodAreaConnections ();
// allow this to be cached if it is loaded by the server
if ( !clientload ) {
Q_strncpyz( cm.name, name, sizeof( cm.name ) );
}
}
/*
==================
CM_ClearMap
==================
*/
void CM_ClearMap( void ) {
Com_Memset( &cm, 0, sizeof( cm ) );
CM_ClearLevelPatches();
}
/*
==================
CM_ClipHandleToModel
==================
*/
cmodel_t *CM_ClipHandleToModel( clipHandle_t handle ) {
if ( handle < 0 ) {
Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i", handle );
}
if ( handle < cm.numSubModels ) {
return &cm.cmodels[handle];
}
if ( handle == BOX_MODEL_HANDLE ) {
return &box_model;
}
if ( handle < MAX_SUBMODELS ) {
Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i < %i < %i",
cm.numSubModels, handle, MAX_SUBMODELS );
}
Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i", handle + MAX_SUBMODELS );
return NULL;
}
/*
==================
CM_InlineModel
==================
*/
clipHandle_t CM_InlineModel( int index ) {
if ( index < 0 || index >= cm.numSubModels ) {
Com_Error (ERR_DROP, "CM_InlineModel: bad number");
}
return index;
}
int CM_NumClusters( void ) {
return cm.numClusters;
}
int CM_NumInlineModels( void ) {
return cm.numSubModels;
}
char *CM_EntityString( void ) {
return cm.entityString;
}
int CM_LeafCluster( int leafnum ) {
if (leafnum < 0 || leafnum >= cm.numLeafs) {
Com_Error (ERR_DROP, "CM_LeafCluster: bad number");
}
return cm.leafs[leafnum].cluster;
}
int CM_LeafArea( int leafnum ) {
if ( leafnum < 0 || leafnum >= cm.numLeafs ) {
Com_Error (ERR_DROP, "CM_LeafArea: bad number");
}
return cm.leafs[leafnum].area;
}
//=======================================================================
/*
===================
CM_InitBoxHull
Set up the planes and nodes so that the six floats of a bounding box
can just be stored out and get a proper clipping hull structure.
===================
*/
void CM_InitBoxHull (void)
{
int i;
int side;
cplane_t *p;
cbrushside_t *s;
box_planes = &cm.planes[cm.numPlanes];
box_brush = &cm.brushes[cm.numBrushes];
box_brush->numsides = 6;
box_brush->sides = cm.brushsides + cm.numBrushSides;
box_brush->contents = CONTENTS_BODY;
box_model.leaf.numLeafBrushes = 1;
// box_model.leaf.firstLeafBrush = cm.numBrushes;
box_model.leaf.firstLeafBrush = cm.numLeafBrushes;
cm.leafbrushes[cm.numLeafBrushes] = cm.numBrushes;
for (i=0 ; i<6 ; i++)
{
side = i&1;
// brush sides
s = &cm.brushsides[cm.numBrushSides+i];
s->plane = cm.planes + (cm.numPlanes+i*2+side);
s->surfaceFlags = 0;
// planes
p = &box_planes[i*2];
p->type = i>>1;
p->signbits = 0;
VectorClear (p->normal);
p->normal[i>>1] = 1;
p = &box_planes[i*2+1];
p->type = 3 + (i>>1);
p->signbits = 0;
VectorClear (p->normal);
p->normal[i>>1] = -1;
SetPlaneSignbits( p );
}
}
/*
===================
CM_TempBoxModel
To keep everything totally uniform, bounding boxes are turned into small
BSP trees instead of being compared directly.
Capsules are handled differently though.
===================
*/
clipHandle_t CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, int capsule ) {
VectorCopy( mins, box_model.mins );
VectorCopy( maxs, box_model.maxs );
if ( capsule ) {
return CAPSULE_MODEL_HANDLE;
}
box_planes[0].dist = maxs[0];
box_planes[1].dist = -maxs[0];
box_planes[2].dist = mins[0];
box_planes[3].dist = -mins[0];
box_planes[4].dist = maxs[1];
box_planes[5].dist = -maxs[1];
box_planes[6].dist = mins[1];
box_planes[7].dist = -mins[1];
box_planes[8].dist = maxs[2];
box_planes[9].dist = -maxs[2];
box_planes[10].dist = mins[2];
box_planes[11].dist = -mins[2];
VectorCopy( mins, box_brush->bounds[0] );
VectorCopy( maxs, box_brush->bounds[1] );
return BOX_MODEL_HANDLE;
}
/*
===================
CM_ModelBounds
===================
*/
void CM_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ) {
cmodel_t *cmod;
cmod = CM_ClipHandleToModel( model );
VectorCopy( cmod->mins, mins );
VectorCopy( cmod->maxs, maxs );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -