123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840 |
- /*
- ===========================================================================
- Copyright (C) 1999-2005 Id Software, Inc.
- This file is part of Quake III Arena source code.
- Quake III Arena source code is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the License,
- or (at your option) any later version.
- Quake III Arena source code is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Foobar; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- ===========================================================================
- */
- // cmodel.c -- model loading
- #include "cm_local.h"
- #ifdef BSPC
- #include "../bspc/l_qfiles.h"
- void SetPlaneSignbits (cplane_t *out) {
- int bits, j;
- // for fast box on planeside test
- bits = 0;
- for (j=0 ; j<3 ; j++) {
- if (out->normal[j] < 0) {
- bits |= 1<<j;
- }
- }
- out->signbits = bits;
- }
- #endif //BSPC
- // to allow boxes to be treated as brush models, we allocate
- // some extra indexes along with those needed by the map
- #define BOX_BRUSHES 1
- #define BOX_SIDES 6
- #define BOX_LEAFS 2
- #define BOX_PLANES 12
- #define LL(x) x=LittleLong(x)
- clipMap_t cm;
- int c_pointcontents;
- int c_traces, c_brush_traces, c_patch_traces;
- byte *cmod_base;
- #ifndef BSPC
- cvar_t *cm_noAreas;
- cvar_t *cm_noCurves;
- cvar_t *cm_playerCurveClip;
- #endif
- cmodel_t box_model;
- cplane_t *box_planes;
- cbrush_t *box_brush;
- void CM_InitBoxHull (void);
- void CM_FloodAreaConnections (void);
- /*
- ===============================================================================
- MAP LOADING
- ===============================================================================
- */
- /*
- =================
- CMod_LoadShaders
- =================
- */
- void CMod_LoadShaders( lump_t *l ) {
- dshader_t *in, *out;
- int i, count;
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in)) {
- Com_Error (ERR_DROP, "CMod_LoadShaders: funny lump size");
- }
- count = l->filelen / sizeof(*in);
- if (count < 1) {
- Com_Error (ERR_DROP, "Map with no shaders");
- }
- cm.shaders = Hunk_Alloc( count * sizeof( *cm.shaders ), h_high );
- cm.numShaders = count;
- Com_Memcpy( cm.shaders, in, count * sizeof( *cm.shaders ) );
- out = cm.shaders;
- for ( i=0 ; i<count ; i++, in++, out++ ) {
- out->contentFlags = LittleLong( out->contentFlags );
- out->surfaceFlags = LittleLong( out->surfaceFlags );
- }
- }
- /*
- =================
- CMod_LoadSubmodels
- =================
- */
- void CMod_LoadSubmodels( lump_t *l ) {
- dmodel_t *in;
- cmodel_t *out;
- int i, j, count;
- int *indexes;
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Com_Error (ERR_DROP, "CMod_LoadSubmodels: funny lump size");
- count = l->filelen / sizeof(*in);
- if (count < 1)
- Com_Error (ERR_DROP, "Map with no models");
- cm.cmodels = Hunk_Alloc( count * sizeof( *cm.cmodels ), h_high );
- cm.numSubModels = count;
- if ( count > MAX_SUBMODELS ) {
- Com_Error( ERR_DROP, "MAX_SUBMODELS exceeded" );
- }
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- out = &cm.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;
- }
- if ( i == 0 ) {
- continue; // world model doesn't need other info
- }
- // make a "leaf" just to hold the model's brushes and surfaces
- out->leaf.numLeafBrushes = LittleLong( in->numBrushes );
- indexes = Hunk_Alloc( out->leaf.numLeafBrushes * 4, h_high );
- out->leaf.firstLeafBrush = indexes - cm.leafbrushes;
- for ( j = 0 ; j < out->leaf.numLeafBrushes ; j++ ) {
- indexes[j] = LittleLong( in->firstBrush ) + j;
- }
- out->leaf.numLeafSurfaces = LittleLong( in->numSurfaces );
- indexes = Hunk_Alloc( out->leaf.numLeafSurfaces * 4, h_high );
- out->leaf.firstLeafSurface = indexes - cm.leafsurfaces;
- for ( j = 0 ; j < out->leaf.numLeafSurfaces ; j++ ) {
- indexes[j] = LittleLong( in->firstSurface ) + j;
- }
- }
- }
- /*
- =================
- CMod_LoadNodes
- =================
- */
- void CMod_LoadNodes( lump_t *l ) {
- dnode_t *in;
- int child;
- cNode_t *out;
- int i, j, count;
-
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
- count = l->filelen / sizeof(*in);
- if (count < 1)
- Com_Error (ERR_DROP, "Map has no nodes");
- cm.nodes = Hunk_Alloc( count * sizeof( *cm.nodes ), h_high );
- cm.numNodes = count;
- out = cm.nodes;
- for (i=0 ; i<count ; i++, out++, in++)
- {
- out->plane = cm.planes + LittleLong( in->planeNum );
- for (j=0 ; j<2 ; j++)
- {
- child = LittleLong (in->children[j]);
- out->children[j] = child;
- }
- }
- }
- /*
- =================
- CM_BoundBrush
- =================
- */
- void CM_BoundBrush( cbrush_t *b ) {
- b->bounds[0][0] = -b->sides[0].plane->dist;
- b->bounds[1][0] = b->sides[1].plane->dist;
- b->bounds[0][1] = -b->sides[2].plane->dist;
- b->bounds[1][1] = b->sides[3].plane->dist;
- b->bounds[0][2] = -b->sides[4].plane->dist;
- b->bounds[1][2] = b->sides[5].plane->dist;
- }
- /*
- =================
- CMod_LoadBrushes
- =================
- */
- void CMod_LoadBrushes( lump_t *l ) {
- dbrush_t *in;
- cbrush_t *out;
- int i, count;
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in)) {
- Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
- }
- count = l->filelen / sizeof(*in);
- cm.brushes = Hunk_Alloc( ( BOX_BRUSHES + count ) * sizeof( *cm.brushes ), h_high );
- cm.numBrushes = count;
- out = cm.brushes;
- for ( i=0 ; i<count ; i++, out++, in++ ) {
- out->sides = cm.brushsides + LittleLong(in->firstSide);
- out->numsides = LittleLong(in->numSides);
- out->shaderNum = LittleLong( in->shaderNum );
- if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) {
- Com_Error( ERR_DROP, "CMod_LoadBrushes: bad shaderNum: %i", out->shaderNum );
- }
- out->contents = cm.shaders[out->shaderNum].contentFlags;
- CM_BoundBrush( out );
- }
- }
- /*
- =================
- CMod_LoadLeafs
- =================
- */
- void CMod_LoadLeafs (lump_t *l)
- {
- int i;
- cLeaf_t *out;
- dleaf_t *in;
- int count;
-
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
- count = l->filelen / sizeof(*in);
- if (count < 1)
- Com_Error (ERR_DROP, "Map with no leafs");
- cm.leafs = Hunk_Alloc( ( BOX_LEAFS + count ) * sizeof( *cm.leafs ), h_high );
- cm.numLeafs = count;
- out = cm.leafs;
- for ( i=0 ; i<count ; i++, in++, out++)
- {
- out->cluster = LittleLong (in->cluster);
- out->area = LittleLong (in->area);
- out->firstLeafBrush = LittleLong (in->firstLeafBrush);
- out->numLeafBrushes = LittleLong (in->numLeafBrushes);
- out->firstLeafSurface = LittleLong (in->firstLeafSurface);
- out->numLeafSurfaces = LittleLong (in->numLeafSurfaces);
- if (out->cluster >= cm.numClusters)
- cm.numClusters = out->cluster + 1;
- if (out->area >= cm.numAreas)
- cm.numAreas = out->area + 1;
- }
- cm.areas = Hunk_Alloc( cm.numAreas * sizeof( *cm.areas ), h_high );
- cm.areaPortals = Hunk_Alloc( cm.numAreas * cm.numAreas * sizeof( *cm.areaPortals ), h_high );
- }
- /*
- =================
- CMod_LoadPlanes
- =================
- */
- void CMod_LoadPlanes (lump_t *l)
- {
- int i, j;
- cplane_t *out;
- dplane_t *in;
- int count;
- int bits;
-
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
- count = l->filelen / sizeof(*in);
- if (count < 1)
- Com_Error (ERR_DROP, "Map with no planes");
- cm.planes = Hunk_Alloc( ( BOX_PLANES + count ) * sizeof( *cm.planes ), h_high );
- cm.numPlanes = count;
- out = cm.planes;
- 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 = PlaneTypeForNormal( out->normal );
- out->signbits = bits;
- }
- }
- /*
- =================
- CMod_LoadLeafBrushes
- =================
- */
- void CMod_LoadLeafBrushes (lump_t *l)
- {
- int i;
- int *out;
- int *in;
- int count;
-
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
- count = l->filelen / sizeof(*in);
- cm.leafbrushes = Hunk_Alloc( (count + BOX_BRUSHES) * sizeof( *cm.leafbrushes ), h_high );
- cm.numLeafBrushes = count;
- out = cm.leafbrushes;
- for ( i=0 ; i<count ; i++, in++, out++) {
- *out = LittleLong (*in);
- }
- }
- /*
- =================
- CMod_LoadLeafSurfaces
- =================
- */
- void CMod_LoadLeafSurfaces( lump_t *l )
- {
- int i;
- int *out;
- int *in;
- int count;
-
- in = (void *)(cmod_base + l->fileofs);
- if (l->filelen % sizeof(*in))
- Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
- count = l->filelen / sizeof(*in);
- cm.leafsurfaces = Hunk_Alloc( count * sizeof( *cm.leafsurfaces ), h_high );
- cm.numLeafSurfaces = count;
- out = cm.leafsurfaces;
- for ( i=0 ; i<count ; i++, in++, out++) {
- *out = LittleLong (*in);
- }
- }
- /*
- =================
- CMod_LoadBrushSides
- =================
- */
- void CMod_LoadBrushSides (lump_t *l)
- {
- int i;
- cbrushside_t *out;
- dbrushside_t *in;
- int count;
- int num;
- in = (void *)(cmod_base + l->fileofs);
- if ( l->filelen % sizeof(*in) ) {
- Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
- }
- count = l->filelen / sizeof(*in);
- 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 );
- }
|