Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

cm_load.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 // cmodel.c -- model loading
00023 
00024 #include "cm_local.h"
00025 
00026 #ifdef BSPC
00027 
00028 #include "../bspc/l_qfiles.h"
00029 
00030 void SetPlaneSignbits (cplane_t *out) {
00031     int bits, j;
00032 
00033     // for fast box on planeside test
00034     bits = 0;
00035     for (j=0 ; j<3 ; j++) {
00036         if (out->normal[j] < 0) {
00037             bits |= 1<<j;
00038         }
00039     }
00040     out->signbits = bits;
00041 }
00042 #endif //BSPC
00043 
00044 // to allow boxes to be treated as brush models, we allocate
00045 // some extra indexes along with those needed by the map
00046 #define BOX_BRUSHES     1
00047 #define BOX_SIDES       6
00048 #define BOX_LEAFS       2
00049 #define BOX_PLANES      12
00050 
00051 #define LL(x) x=LittleLong(x)
00052 
00053 
00054 clipMap_t   cm;
00055 int         c_pointcontents;
00056 int         c_traces, c_brush_traces, c_patch_traces;
00057 
00058 
00059 byte        *cmod_base;
00060 
00061 #ifndef BSPC
00062 cvar_t      *cm_noAreas;
00063 cvar_t      *cm_noCurves;
00064 cvar_t      *cm_playerCurveClip;
00065 #endif
00066 
00067 cmodel_t    box_model;
00068 cplane_t    *box_planes;
00069 cbrush_t    *box_brush;
00070 
00071 
00072 
00073 void    CM_InitBoxHull (void);
00074 void    CM_FloodAreaConnections (void);
00075 
00076 
00077 /*
00078 ===============================================================================
00079 
00080                     MAP LOADING
00081 
00082 ===============================================================================
00083 */
00084 
00085 /*
00086 =================
00087 CMod_LoadShaders
00088 =================
00089 */
00090 void CMod_LoadShaders( lump_t *l ) {
00091     dshader_t   *in, *out;
00092     int         i, count;
00093 
00094     in = (void *)(cmod_base + l->fileofs);
00095     if (l->filelen % sizeof(*in)) {
00096         Com_Error (ERR_DROP, "CMod_LoadShaders: funny lump size");
00097     }
00098     count = l->filelen / sizeof(*in);
00099 
00100     if (count < 1) {
00101         Com_Error (ERR_DROP, "Map with no shaders");
00102     }
00103     cm.shaders = Hunk_Alloc( count * sizeof( *cm.shaders ), h_high );
00104     cm.numShaders = count;
00105 
00106     Com_Memcpy( cm.shaders, in, count * sizeof( *cm.shaders ) );
00107 
00108     out = cm.shaders;
00109     for ( i=0 ; i<count ; i++, in++, out++ ) {
00110         out->contentFlags = LittleLong( out->contentFlags );
00111         out->surfaceFlags = LittleLong( out->surfaceFlags );
00112     }
00113 }
00114 
00115 
00116 /*
00117 =================
00118 CMod_LoadSubmodels
00119 =================
00120 */
00121 void CMod_LoadSubmodels( lump_t *l ) {
00122     dmodel_t    *in;
00123     cmodel_t    *out;
00124     int         i, j, count;
00125     int         *indexes;
00126 
00127     in = (void *)(cmod_base + l->fileofs);
00128     if (l->filelen % sizeof(*in))
00129         Com_Error (ERR_DROP, "CMod_LoadSubmodels: funny lump size");
00130     count = l->filelen / sizeof(*in);
00131 
00132     if (count < 1)
00133         Com_Error (ERR_DROP, "Map with no models");
00134     cm.cmodels = Hunk_Alloc( count * sizeof( *cm.cmodels ), h_high );
00135     cm.numSubModels = count;
00136 
00137     if ( count > MAX_SUBMODELS ) {
00138         Com_Error( ERR_DROP, "MAX_SUBMODELS exceeded" );
00139     }
00140 
00141     for ( i=0 ; i<count ; i++, in++, out++)
00142     {
00143         out = &cm.cmodels[i];
00144 
00145         for (j=0 ; j<3 ; j++)
00146         {   // spread the mins / maxs by a pixel
00147             out->mins[j] = LittleFloat (in->mins[j]) - 1;
00148             out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
00149         }
00150 
00151         if ( i == 0 ) {
00152             continue;   // world model doesn't need other info
00153         }
00154 
00155         // make a "leaf" just to hold the model's brushes and surfaces
00156         out->leaf.numLeafBrushes = LittleLong( in->numBrushes );
00157         indexes = Hunk_Alloc( out->leaf.numLeafBrushes * 4, h_high );
00158         out->leaf.firstLeafBrush = indexes - cm.leafbrushes;
00159         for ( j = 0 ; j < out->leaf.numLeafBrushes ; j++ ) {
00160             indexes[j] = LittleLong( in->firstBrush ) + j;
00161         }
00162 
00163         out->leaf.numLeafSurfaces = LittleLong( in->numSurfaces );
00164         indexes = Hunk_Alloc( out->leaf.numLeafSurfaces * 4, h_high );
00165         out->leaf.firstLeafSurface = indexes - cm.leafsurfaces;
00166         for ( j = 0 ; j < out->leaf.numLeafSurfaces ; j++ ) {
00167             indexes[j] = LittleLong( in->firstSurface ) + j;
00168         }
00169     }
00170 }
00171 
00172 
00173 /*
00174 =================
00175 CMod_LoadNodes
00176 
00177 =================
00178 */
00179 void CMod_LoadNodes( lump_t *l ) {
00180     dnode_t     *in;
00181     int         child;
00182     cNode_t     *out;
00183     int         i, j, count;
00184     
00185     in = (void *)(cmod_base + l->fileofs);
00186     if (l->filelen % sizeof(*in))
00187         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00188     count = l->filelen / sizeof(*in);
00189 
00190     if (count < 1)
00191         Com_Error (ERR_DROP, "Map has no nodes");
00192     cm.nodes = Hunk_Alloc( count * sizeof( *cm.nodes ), h_high );
00193     cm.numNodes = count;
00194 
00195     out = cm.nodes;
00196 
00197     for (i=0 ; i<count ; i++, out++, in++)
00198     {
00199         out->plane = cm.planes + LittleLong( in->planeNum );
00200         for (j=0 ; j<2 ; j++)
00201         {
00202             child = LittleLong (in->children[j]);
00203             out->children[j] = child;
00204         }
00205     }
00206 
00207 }
00208 
00209 /*
00210 =================
00211 CM_BoundBrush
00212 
00213 =================
00214 */
00215 void CM_BoundBrush( cbrush_t *b ) {
00216     b->bounds[0][0] = -b->sides[0].plane->dist;
00217     b->bounds[1][0] = b->sides[1].plane->dist;
00218 
00219     b->bounds[0][1] = -b->sides[2].plane->dist;
00220     b->bounds[1][1] = b->sides[3].plane->dist;
00221 
00222     b->bounds[0][2] = -b->sides[4].plane->dist;
00223     b->bounds[1][2] = b->sides[5].plane->dist;
00224 }
00225 
00226 
00227 /*
00228 =================
00229 CMod_LoadBrushes
00230 
00231 =================
00232 */
00233 void CMod_LoadBrushes( lump_t *l ) {
00234     dbrush_t    *in;
00235     cbrush_t    *out;
00236     int         i, count;
00237 
00238     in = (void *)(cmod_base + l->fileofs);
00239     if (l->filelen % sizeof(*in)) {
00240         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00241     }
00242     count = l->filelen / sizeof(*in);
00243 
00244     cm.brushes = Hunk_Alloc( ( BOX_BRUSHES + count ) * sizeof( *cm.brushes ), h_high );
00245     cm.numBrushes = count;
00246 
00247     out = cm.brushes;
00248 
00249     for ( i=0 ; i<count ; i++, out++, in++ ) {
00250         out->sides = cm.brushsides + LittleLong(in->firstSide);
00251         out->numsides = LittleLong(in->numSides);
00252 
00253         out->shaderNum = LittleLong( in->shaderNum );
00254         if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) {
00255             Com_Error( ERR_DROP, "CMod_LoadBrushes: bad shaderNum: %i", out->shaderNum );
00256         }
00257         out->contents = cm.shaders[out->shaderNum].contentFlags;
00258 
00259         CM_BoundBrush( out );
00260     }
00261 
00262 }
00263 
00264 /*
00265 =================
00266 CMod_LoadLeafs
00267 =================
00268 */
00269 void CMod_LoadLeafs (lump_t *l)
00270 {
00271     int         i;
00272     cLeaf_t     *out;
00273     dleaf_t     *in;
00274     int         count;
00275     
00276     in = (void *)(cmod_base + l->fileofs);
00277     if (l->filelen % sizeof(*in))
00278         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00279     count = l->filelen / sizeof(*in);
00280 
00281     if (count < 1)
00282         Com_Error (ERR_DROP, "Map with no leafs");
00283 
00284     cm.leafs = Hunk_Alloc( ( BOX_LEAFS + count ) * sizeof( *cm.leafs ), h_high );
00285     cm.numLeafs = count;
00286 
00287     out = cm.leafs; 
00288     for ( i=0 ; i<count ; i++, in++, out++)
00289     {
00290         out->cluster = LittleLong (in->cluster);
00291         out->area = LittleLong (in->area);
00292         out->firstLeafBrush = LittleLong (in->firstLeafBrush);
00293         out->numLeafBrushes = LittleLong (in->numLeafBrushes);
00294         out->firstLeafSurface = LittleLong (in->firstLeafSurface);
00295         out->numLeafSurfaces = LittleLong (in->numLeafSurfaces);
00296 
00297         if (out->cluster >= cm.numClusters)
00298             cm.numClusters = out->cluster + 1;
00299         if (out->area >= cm.numAreas)
00300             cm.numAreas = out->area + 1;
00301     }
00302 
00303     cm.areas = Hunk_Alloc( cm.numAreas * sizeof( *cm.areas ), h_high );
00304     cm.areaPortals = Hunk_Alloc( cm.numAreas * cm.numAreas * sizeof( *cm.areaPortals ), h_high );
00305 }
00306 
00307 /*
00308 =================
00309 CMod_LoadPlanes
00310 =================
00311 */
00312 void CMod_LoadPlanes (lump_t *l)
00313 {
00314     int         i, j;
00315     cplane_t    *out;
00316     dplane_t    *in;
00317     int         count;
00318     int         bits;
00319     
00320     in = (void *)(cmod_base + l->fileofs);
00321     if (l->filelen % sizeof(*in))
00322         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00323     count = l->filelen / sizeof(*in);
00324 
00325     if (count < 1)
00326         Com_Error (ERR_DROP, "Map with no planes");
00327     cm.planes = Hunk_Alloc( ( BOX_PLANES + count ) * sizeof( *cm.planes ), h_high );
00328     cm.numPlanes = count;
00329 
00330     out = cm.planes;    
00331 
00332     for ( i=0 ; i<count ; i++, in++, out++)
00333     {
00334         bits = 0;
00335         for (j=0 ; j<3 ; j++)
00336         {
00337             out->normal[j] = LittleFloat (in->normal[j]);
00338             if (out->normal[j] < 0)
00339                 bits |= 1<<j;
00340         }
00341 
00342         out->dist = LittleFloat (in->dist);
00343         out->type = PlaneTypeForNormal( out->normal );
00344         out->signbits = bits;
00345     }
00346 }
00347 
00348 /*
00349 =================
00350 CMod_LoadLeafBrushes
00351 =================
00352 */
00353 void CMod_LoadLeafBrushes (lump_t *l)
00354 {
00355     int         i;
00356     int         *out;
00357     int         *in;
00358     int         count;
00359     
00360     in = (void *)(cmod_base + l->fileofs);
00361     if (l->filelen % sizeof(*in))
00362         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00363     count = l->filelen / sizeof(*in);
00364 
00365     cm.leafbrushes = Hunk_Alloc( (count + BOX_BRUSHES) * sizeof( *cm.leafbrushes ), h_high );
00366     cm.numLeafBrushes = count;
00367 
00368     out = cm.leafbrushes;
00369 
00370     for ( i=0 ; i<count ; i++, in++, out++) {
00371         *out = LittleLong (*in);
00372     }
00373 }
00374 
00375 /*
00376 =================
00377 CMod_LoadLeafSurfaces
00378 =================
00379 */
00380 void CMod_LoadLeafSurfaces( lump_t *l )
00381 {
00382     int         i;
00383     int         *out;
00384     int         *in;
00385     int         count;
00386     
00387     in = (void *)(cmod_base + l->fileofs);
00388     if (l->filelen % sizeof(*in))
00389         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00390     count = l->filelen / sizeof(*in);
00391 
00392     cm.leafsurfaces = Hunk_Alloc( count * sizeof( *cm.leafsurfaces ), h_high );
00393     cm.numLeafSurfaces = count;
00394 
00395     out = cm.leafsurfaces;
00396 
00397     for ( i=0 ; i<count ; i++, in++, out++) {
00398         *out = LittleLong (*in);
00399     }
00400 }
00401 
00402 /*
00403 =================
00404 CMod_LoadBrushSides
00405 =================
00406 */
00407 void CMod_LoadBrushSides (lump_t *l)
00408 {
00409     int             i;
00410     cbrushside_t    *out;
00411     dbrushside_t    *in;
00412     int             count;
00413     int             num;
00414 
00415     in = (void *)(cmod_base + l->fileofs);
00416     if ( l->filelen % sizeof(*in) ) {
00417         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00418     }
00419     count = l->filelen / sizeof(*in);
00420 
00421     cm.brushsides = Hunk_Alloc( ( BOX_SIDES + count ) * sizeof( *cm.brushsides ), h_high );
00422     cm.numBrushSides = count;
00423 
00424     out = cm.brushsides;    
00425 
00426     for ( i=0 ; i<count ; i++, in++, out++) {
00427         num = LittleLong( in->planeNum );
00428         out->plane = &cm.planes[num];
00429         out->shaderNum = LittleLong( in->shaderNum );
00430         if ( out->shaderNum < 0 || out->shaderNum >= cm.numShaders ) {
00431             Com_Error( ERR_DROP, "CMod_LoadBrushSides: bad shaderNum: %i", out->shaderNum );
00432         }
00433         out->surfaceFlags = cm.shaders[out->shaderNum].surfaceFlags;
00434     }
00435 }
00436 
00437 
00438 /*
00439 =================
00440 CMod_LoadEntityString
00441 =================
00442 */
00443 void CMod_LoadEntityString( lump_t *l ) {
00444     cm.entityString = Hunk_Alloc( l->filelen, h_high );
00445     cm.numEntityChars = l->filelen;
00446     Com_Memcpy (cm.entityString, cmod_base + l->fileofs, l->filelen);
00447 }
00448 
00449 /*
00450 =================
00451 CMod_LoadVisibility
00452 =================
00453 */
00454 #define VIS_HEADER  8
00455 void CMod_LoadVisibility( lump_t *l ) {
00456     int     len;
00457     byte    *buf;
00458 
00459     len = l->filelen;
00460     if ( !len ) {
00461         cm.clusterBytes = ( cm.numClusters + 31 ) & ~31;
00462         cm.visibility = Hunk_Alloc( cm.clusterBytes, h_high );
00463         Com_Memset( cm.visibility, 255, cm.clusterBytes );
00464         return;
00465     }
00466     buf = cmod_base + l->fileofs;
00467 
00468     cm.vised = qtrue;
00469     cm.visibility = Hunk_Alloc( len, h_high );
00470     cm.numClusters = LittleLong( ((int *)buf)[0] );
00471     cm.clusterBytes = LittleLong( ((int *)buf)[1] );
00472     Com_Memcpy (cm.visibility, buf + VIS_HEADER, len - VIS_HEADER );
00473 }
00474 
00475 //==================================================================
00476 
00477 
00478 /*
00479 =================
00480 CMod_LoadPatches
00481 =================
00482 */
00483 #define MAX_PATCH_VERTS     1024
00484 void CMod_LoadPatches( lump_t *surfs, lump_t *verts ) {
00485     drawVert_t  *dv, *dv_p;
00486     dsurface_t  *in;
00487     int         count;
00488     int         i, j;
00489     int         c;
00490     cPatch_t    *patch;
00491     vec3_t      points[MAX_PATCH_VERTS];
00492     int         width, height;
00493     int         shaderNum;
00494 
00495     in = (void *)(cmod_base + surfs->fileofs);
00496     if (surfs->filelen % sizeof(*in))
00497         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00498     cm.numSurfaces = count = surfs->filelen / sizeof(*in);
00499     cm.surfaces = Hunk_Alloc( cm.numSurfaces * sizeof( cm.surfaces[0] ), h_high );
00500 
00501     dv = (void *)(cmod_base + verts->fileofs);
00502     if (verts->filelen % sizeof(*dv))
00503         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
00504 
00505     // scan through all the surfaces, but only load patches,
00506     // not planar faces
00507     for ( i = 0 ; i < count ; i++, in++ ) {
00508         if ( LittleLong( in->surfaceType ) != MST_PATCH ) {
00509             continue;       // ignore other surfaces
00510         }
00511         // FIXME: check for non-colliding patches
00512 
00513         cm.surfaces[ i ] = patch = Hunk_Alloc( sizeof( *patch ), h_high );
00514 
00515         // load the full drawverts onto the stack
00516         width = LittleLong( in->patchWidth );
00517         height = LittleLong( in->patchHeight );
00518         c = width * height;
00519         if ( c > MAX_PATCH_VERTS ) {
00520             Com_Error( ERR_DROP, "ParseMesh: MAX_PATCH_VERTS" );
00521         }
00522 
00523         dv_p = dv + LittleLong( in->firstVert );
00524         for ( j = 0 ; j < c ; j++, dv_p++ ) {
00525             points[j][0] = LittleFloat( dv_p->xyz[0] );
00526             points[j][1] = LittleFloat( dv_p->xyz[1] );
00527             points[j][2] = LittleFloat( dv_p->xyz[2] );
00528         }
00529 
00530         shaderNum = LittleLong( in->shaderNum );
00531         patch->contents = cm.shaders[shaderNum].contentFlags;
00532         patch->surfaceFlags = cm.shaders[shaderNum].surfaceFlags;
00533 
00534         // create the internal facet structure
00535         patch->pc = CM_GeneratePatchCollide( width, height, points );
00536     }
00537 }
00538 
00539 //==================================================================
00540 
00541 unsigned CM_LumpChecksum(lump_t *lump) {
00542     return LittleLong (Com_BlockChecksum (cmod_base + lump->fileofs, lump->filelen));
00543 }
00544 
00545 unsigned CM_Checksum(dheader_t *header) {
00546     unsigned checksums[16];
00547     checksums[0] = CM_LumpChecksum(&header->lumps[LUMP_SHADERS]);
00548     checksums[1] = CM_LumpChecksum(&header->lumps[LUMP_LEAFS]);
00549     checksums[2] = CM_LumpChecksum(&header->lumps[LUMP_LEAFBRUSHES]);
00550     checksums[3] = CM_LumpChecksum(&header->lumps[LUMP_LEAFSURFACES]);
00551     checksums[4] = CM_LumpChecksum(&header->lumps[LUMP_PLANES]);
00552     checksums[5] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHSIDES]);
00553     checksums[6] = CM_LumpChecksum(&header->lumps[LUMP_BRUSHES]);
00554     checksums[7] = CM_LumpChecksum(&header->lumps[LUMP_MODELS]);
00555     checksums[8] = CM_LumpChecksum(&header->lumps[LUMP_NODES]);
00556     checksums[9] = CM_LumpChecksum(&header->lumps[LUMP_SURFACES]);
00557     checksums[10] = CM_LumpChecksum(&header->lumps[LUMP_DRAWVERTS]);
00558 
00559     return LittleLong(Com_BlockChecksum(checksums, 11 * 4));
00560 }
00561 
00562 /*
00563 ==================
00564 CM_LoadMap
00565 
00566 Loads in the map and all submodels
00567 ==================
00568 */
00569 void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) {
00570     int             *buf;
00571     int             i;
00572     dheader_t       header;
00573     int             length;
00574     static unsigned last_checksum;
00575 
00576     if ( !name || !name[0] ) {
00577         Com_Error( ERR_DROP, "CM_LoadMap: NULL name" );
00578     }
00579 
00580 #ifndef BSPC
00581     cm_noAreas = Cvar_Get ("cm_noAreas", "0", CVAR_CHEAT);
00582     cm_noCurves = Cvar_Get ("cm_noCurves", "0", CVAR_CHEAT);
00583     cm_playerCurveClip = Cvar_Get ("cm_playerCurveClip", "1", CVAR_ARCHIVE|CVAR_CHEAT );
00584 #endif
00585     Com_DPrintf( "CM_LoadMap( %s, %i )\n", name, clientload );
00586 
00587     if ( !strcmp( cm.name, name ) && clientload ) {
00588         *checksum = last_checksum;
00589         return;
00590     }
00591 
00592     // free old stuff
00593     Com_Memset( &cm, 0, sizeof( cm ) );
00594     CM_ClearLevelPatches();
00595 
00596     if ( !name[0] ) {
00597         cm.numLeafs = 1;
00598         cm.numClusters = 1;
00599         cm.numAreas = 1;
00600         cm.cmodels = Hunk_Alloc( sizeof( *cm.cmodels ), h_high );
00601         *checksum = 0;
00602         return;
00603     }
00604 
00605     //
00606     // load the file
00607     //
00608 #ifndef BSPC
00609     length = FS_ReadFile( name, (void **)&buf );
00610 #else
00611     length = LoadQuakeFile((quakefile_t *) name, (void **)&buf);
00612 #endif
00613 
00614     if ( !buf ) {
00615         Com_Error (ERR_DROP, "Couldn't load %s", name);
00616     }
00617 
00618     last_checksum = LittleLong (Com_BlockChecksum (buf, length));
00619     *checksum = last_checksum;
00620 
00621     header = *(dheader_t *)buf;
00622     for (i=0 ; i<sizeof(dheader_t)/4 ; i++) {
00623         ((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
00624     }
00625 
00626     if ( header.version != BSP_VERSION ) {
00627         Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be %i)"
00628         , name, header.version, BSP_VERSION );
00629     }
00630 
00631     cmod_base = (byte *)buf;
00632 
00633     // load into heap
00634     CMod_LoadShaders( &header.lumps[LUMP_SHADERS] );
00635     CMod_LoadLeafs (&header.lumps[LUMP_LEAFS]);
00636     CMod_LoadLeafBrushes (&header.lumps[LUMP_LEAFBRUSHES]);
00637     CMod_LoadLeafSurfaces (&header.lumps[LUMP_LEAFSURFACES]);
00638     CMod_LoadPlanes (&header.lumps[LUMP_PLANES]);
00639     CMod_LoadBrushSides (&header.lumps[LUMP_BRUSHSIDES]);
00640     CMod_LoadBrushes (&header.lumps[LUMP_BRUSHES]);
00641     CMod_LoadSubmodels (&header.lumps[LUMP_MODELS]);
00642     CMod_LoadNodes (&header.lumps[LUMP_NODES]);
00643     CMod_LoadEntityString (&header.lumps[LUMP_ENTITIES]);
00644     CMod_LoadVisibility( &header.lumps[LUMP_VISIBILITY] );
00645     CMod_LoadPatches( &header.lumps[LUMP_SURFACES], &header.lumps[LUMP_DRAWVERTS] );
00646 
00647     // we are NOT freeing the file, because it is cached for the ref
00648     FS_FreeFile (buf);
00649 
00650     CM_InitBoxHull ();
00651 
00652     CM_FloodAreaConnections ();
00653 
00654     // allow this to be cached if it is loaded by the server
00655     if ( !clientload ) {
00656         Q_strncpyz( cm.name, name, sizeof( cm.name ) );
00657     }
00658 }
00659 
00660 /*
00661 ==================
00662 CM_ClearMap
00663 ==================
00664 */
00665 void CM_ClearMap( void ) {
00666     Com_Memset( &cm, 0, sizeof( cm ) );
00667     CM_ClearLevelPatches();
00668 }
00669 
00670 /*
00671 ==================
00672 CM_ClipHandleToModel
00673 ==================
00674 */
00675 cmodel_t    *CM_ClipHandleToModel( clipHandle_t handle ) {
00676     if ( handle < 0 ) {
00677         Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i", handle );
00678     }
00679     if ( handle < cm.numSubModels ) {
00680         return &cm.cmodels[handle];
00681     }
00682     if ( handle == BOX_MODEL_HANDLE ) {
00683         return &box_model;
00684     }
00685     if ( handle < MAX_SUBMODELS ) {
00686         Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i < %i < %i", 
00687             cm.numSubModels, handle, MAX_SUBMODELS );
00688     }
00689     Com_Error( ERR_DROP, "CM_ClipHandleToModel: bad handle %i", handle + MAX_SUBMODELS );
00690 
00691     return NULL;
00692 
00693 }
00694 
00695 /*
00696 ==================
00697 CM_InlineModel
00698 ==================
00699 */
00700 clipHandle_t    CM_InlineModel( int index ) {
00701     if ( index < 0 || index >= cm.numSubModels ) {
00702         Com_Error (ERR_DROP, "CM_InlineModel: bad number");
00703     }
00704     return index;
00705 }
00706 
00707 int     CM_NumClusters( void ) {
00708     return cm.numClusters;
00709 }
00710 
00711 int     CM_NumInlineModels( void ) {
00712     return cm.numSubModels;
00713 }
00714 
00715 char    *CM_EntityString( void ) {
00716     return cm.entityString;
00717 }
00718 
00719 int     CM_LeafCluster( int leafnum ) {
00720     if (leafnum < 0 || leafnum >= cm.numLeafs) {
00721         Com_Error (ERR_DROP, "CM_LeafCluster: bad number");
00722     }
00723     return cm.leafs[leafnum].cluster;
00724 }
00725 
00726 int     CM_LeafArea( int leafnum ) {
00727     if ( leafnum < 0 || leafnum >= cm.numLeafs ) {
00728         Com_Error (ERR_DROP, "CM_LeafArea: bad number");
00729     }
00730     return cm.leafs[leafnum].area;
00731 }
00732 
00733 //=======================================================================
00734 
00735 
00736 /*
00737 ===================
00738 CM_InitBoxHull
00739 
00740 Set up the planes and nodes so that the six floats of a bounding box
00741 can just be stored out and get a proper clipping hull structure.
00742 ===================
00743 */
00744 void CM_InitBoxHull (void)
00745 {
00746     int         i;
00747     int         side;
00748     cplane_t    *p;
00749     cbrushside_t    *s;
00750 
00751     box_planes = &cm.planes[cm.numPlanes];
00752 
00753     box_brush = &cm.brushes[cm.numBrushes];
00754     box_brush->numsides = 6;
00755     box_brush->sides = cm.brushsides + cm.numBrushSides;
00756     box_brush->contents = CONTENTS_BODY;
00757 
00758     box_model.leaf.numLeafBrushes = 1;
00759 //  box_model.leaf.firstLeafBrush = cm.numBrushes;
00760     box_model.leaf.firstLeafBrush = cm.numLeafBrushes;
00761     cm.leafbrushes[cm.numLeafBrushes] = cm.numBrushes;
00762 
00763     for (i=0 ; i<6 ; i++)
00764     {
00765         side = i&1;
00766 
00767         // brush sides
00768         s = &cm.brushsides[cm.numBrushSides+i];
00769         s->plane =  cm.planes + (cm.numPlanes+i*2+side);
00770         s->surfaceFlags = 0;
00771 
00772         // planes
00773         p = &box_planes[i*2];
00774         p->type = i>>1;
00775         p->signbits = 0;
00776         VectorClear (p->normal);
00777         p->normal[i>>1] = 1;
00778 
00779         p = &box_planes[i*2+1];
00780         p->type = 3 + (i>>1);
00781         p->signbits = 0;
00782         VectorClear (p->normal);
00783         p->normal[i>>1] = -1;
00784 
00785         SetPlaneSignbits( p );
00786     }   
00787 }
00788 
00789 /*
00790 ===================
00791 CM_TempBoxModel
00792 
00793 To keep everything totally uniform, bounding boxes are turned into small
00794 BSP trees instead of being compared directly.
00795 Capsules are handled differently though.
00796 ===================
00797 */
00798 clipHandle_t CM_TempBoxModel( const vec3_t mins, const vec3_t maxs, int capsule ) {
00799 
00800     VectorCopy( mins, box_model.mins );
00801     VectorCopy( maxs, box_model.maxs );
00802 
00803     if ( capsule ) {
00804         return CAPSULE_MODEL_HANDLE;
00805     }
00806 
00807     box_planes[0].dist = maxs[0];
00808     box_planes[1].dist = -maxs[0];
00809     box_planes[2].dist = mins[0];
00810     box_planes[3].dist = -mins[0];
00811     box_planes[4].dist = maxs[1];
00812     box_planes[5].dist = -maxs[1];
00813     box_planes[6].dist = mins[1];
00814     box_planes[7].dist = -mins[1];
00815     box_planes[8].dist = maxs[2];
00816     box_planes[9].dist = -maxs[2];
00817     box_planes[10].dist = mins[2];
00818     box_planes[11].dist = -mins[2];
00819 
00820     VectorCopy( mins, box_brush->bounds[0] );
00821     VectorCopy( maxs, box_brush->bounds[1] );
00822 
00823     return BOX_MODEL_HANDLE;
00824 }
00825 
00826 /*
00827 ===================
00828 CM_ModelBounds
00829 ===================
00830 */
00831 void CM_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ) {
00832     cmodel_t    *cmod;
00833 
00834     cmod = CM_ClipHandleToModel( model );
00835     VectorCopy( cmod->mins, mins );
00836     VectorCopy( cmod->maxs, maxs );
00837 }
00838 
00839 

Generated on Thu Aug 25 12:37:45 2005 for Quake III Arena by  doxygen 1.3.9.1