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

cm_test.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 #include "cm_local.h"
00023 
00024 
00025 /*
00026 ==================
00027 CM_PointLeafnum_r
00028 
00029 ==================
00030 */
00031 int CM_PointLeafnum_r( const vec3_t p, int num ) {
00032     float       d;
00033     cNode_t     *node;
00034     cplane_t    *plane;
00035 
00036     while (num >= 0)
00037     {
00038         node = cm.nodes + num;
00039         plane = node->plane;
00040         
00041         if (plane->type < 3)
00042             d = p[plane->type] - plane->dist;
00043         else
00044             d = DotProduct (plane->normal, p) - plane->dist;
00045         if (d < 0)
00046             num = node->children[1];
00047         else
00048             num = node->children[0];
00049     }
00050 
00051     c_pointcontents++;      // optimize counter
00052 
00053     return -1 - num;
00054 }
00055 
00056 int CM_PointLeafnum( const vec3_t p ) {
00057     if ( !cm.numNodes ) {   // map not loaded
00058         return 0;
00059     }
00060     return CM_PointLeafnum_r (p, 0);
00061 }
00062 
00063 
00064 /*
00065 ======================================================================
00066 
00067 LEAF LISTING
00068 
00069 ======================================================================
00070 */
00071 
00072 
00073 void CM_StoreLeafs( leafList_t *ll, int nodenum ) {
00074     int     leafNum;
00075 
00076     leafNum = -1 - nodenum;
00077 
00078     // store the lastLeaf even if the list is overflowed
00079     if ( cm.leafs[ leafNum ].cluster != -1 ) {
00080         ll->lastLeaf = leafNum;
00081     }
00082 
00083     if ( ll->count >= ll->maxcount) {
00084         ll->overflowed = qtrue;
00085         return;
00086     }
00087     ll->list[ ll->count++ ] = leafNum;
00088 }
00089 
00090 void CM_StoreBrushes( leafList_t *ll, int nodenum ) {
00091     int         i, k;
00092     int         leafnum;
00093     int         brushnum;
00094     cLeaf_t     *leaf;
00095     cbrush_t    *b;
00096 
00097     leafnum = -1 - nodenum;
00098 
00099     leaf = &cm.leafs[leafnum];
00100 
00101     for ( k = 0 ; k < leaf->numLeafBrushes ; k++ ) {
00102         brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
00103         b = &cm.brushes[brushnum];
00104         if ( b->checkcount == cm.checkcount ) {
00105             continue;   // already checked this brush in another leaf
00106         }
00107         b->checkcount = cm.checkcount;
00108         for ( i = 0 ; i < 3 ; i++ ) {
00109             if ( b->bounds[0][i] >= ll->bounds[1][i] || b->bounds[1][i] <= ll->bounds[0][i] ) {
00110                 break;
00111             }
00112         }
00113         if ( i != 3 ) {
00114             continue;
00115         }
00116         if ( ll->count >= ll->maxcount) {
00117             ll->overflowed = qtrue;
00118             return;
00119         }
00120         ((cbrush_t **)ll->list)[ ll->count++ ] = b;
00121     }
00122 #if 0
00123     // store patches?
00124     for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) {
00125         patch = cm.surfaces[ cm.leafsurfaces[ leaf->firstleafsurface + k ] ];
00126         if ( !patch ) {
00127             continue;
00128         }
00129     }
00130 #endif
00131 }
00132 
00133 /*
00134 =============
00135 CM_BoxLeafnums
00136 
00137 Fills in a list of all the leafs touched
00138 =============
00139 */
00140 void CM_BoxLeafnums_r( leafList_t *ll, int nodenum ) {
00141     cplane_t    *plane;
00142     cNode_t     *node;
00143     int         s;
00144 
00145     while (1) {
00146         if (nodenum < 0) {
00147             ll->storeLeafs( ll, nodenum );
00148             return;
00149         }
00150     
00151         node = &cm.nodes[nodenum];
00152         plane = node->plane;
00153         s = BoxOnPlaneSide( ll->bounds[0], ll->bounds[1], plane );
00154         if (s == 1) {
00155             nodenum = node->children[0];
00156         } else if (s == 2) {
00157             nodenum = node->children[1];
00158         } else {
00159             // go down both
00160             CM_BoxLeafnums_r( ll, node->children[0] );
00161             nodenum = node->children[1];
00162         }
00163 
00164     }
00165 }
00166 
00167 /*
00168 ==================
00169 CM_BoxLeafnums
00170 ==================
00171 */
00172 int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *lastLeaf) {
00173     leafList_t  ll;
00174 
00175     cm.checkcount++;
00176 
00177     VectorCopy( mins, ll.bounds[0] );
00178     VectorCopy( maxs, ll.bounds[1] );
00179     ll.count = 0;
00180     ll.maxcount = listsize;
00181     ll.list = list;
00182     ll.storeLeafs = CM_StoreLeafs;
00183     ll.lastLeaf = 0;
00184     ll.overflowed = qfalse;
00185 
00186     CM_BoxLeafnums_r( &ll, 0 );
00187 
00188     *lastLeaf = ll.lastLeaf;
00189     return ll.count;
00190 }
00191 
00192 /*
00193 ==================
00194 CM_BoxBrushes
00195 ==================
00196 */
00197 int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize ) {
00198     leafList_t  ll;
00199 
00200     cm.checkcount++;
00201 
00202     VectorCopy( mins, ll.bounds[0] );
00203     VectorCopy( maxs, ll.bounds[1] );
00204     ll.count = 0;
00205     ll.maxcount = listsize;
00206     ll.list = (void *)list;
00207     ll.storeLeafs = CM_StoreBrushes;
00208     ll.lastLeaf = 0;
00209     ll.overflowed = qfalse;
00210     
00211     CM_BoxLeafnums_r( &ll, 0 );
00212 
00213     return ll.count;
00214 }
00215 
00216 
00217 //====================================================================
00218 
00219 
00220 /*
00221 ==================
00222 CM_PointContents
00223 
00224 ==================
00225 */
00226 int CM_PointContents( const vec3_t p, clipHandle_t model ) {
00227     int         leafnum;
00228     int         i, k;
00229     int         brushnum;
00230     cLeaf_t     *leaf;
00231     cbrush_t    *b;
00232     int         contents;
00233     float       d;
00234     cmodel_t    *clipm;
00235 
00236     if (!cm.numNodes) { // map not loaded
00237         return 0;
00238     }
00239 
00240     if ( model ) {
00241         clipm = CM_ClipHandleToModel( model );
00242         leaf = &clipm->leaf;
00243     } else {
00244         leafnum = CM_PointLeafnum_r (p, 0);
00245         leaf = &cm.leafs[leafnum];
00246     }
00247 
00248     contents = 0;
00249     for (k=0 ; k<leaf->numLeafBrushes ; k++) {
00250         brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
00251         b = &cm.brushes[brushnum];
00252 
00253         // see if the point is in the brush
00254         for ( i = 0 ; i < b->numsides ; i++ ) {
00255             d = DotProduct( p, b->sides[i].plane->normal );
00256 // FIXME test for Cash
00257 //          if ( d >= b->sides[i].plane->dist ) {
00258             if ( d > b->sides[i].plane->dist ) {
00259                 break;
00260             }
00261         }
00262 
00263         if ( i == b->numsides ) {
00264             contents |= b->contents;
00265         }
00266     }
00267 
00268     return contents;
00269 }
00270 
00271 /*
00272 ==================
00273 CM_TransformedPointContents
00274 
00275 Handles offseting and rotation of the end points for moving and
00276 rotating entities
00277 ==================
00278 */
00279 int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles) {
00280     vec3_t      p_l;
00281     vec3_t      temp;
00282     vec3_t      forward, right, up;
00283 
00284     // subtract origin offset
00285     VectorSubtract (p, origin, p_l);
00286 
00287     // rotate start and end into the models frame of reference
00288     if ( model != BOX_MODEL_HANDLE && 
00289     (angles[0] || angles[1] || angles[2]) )
00290     {
00291         AngleVectors (angles, forward, right, up);
00292 
00293         VectorCopy (p_l, temp);
00294         p_l[0] = DotProduct (temp, forward);
00295         p_l[1] = -DotProduct (temp, right);
00296         p_l[2] = DotProduct (temp, up);
00297     }
00298 
00299     return CM_PointContents( p_l, model );
00300 }
00301 
00302 
00303 
00304 /*
00305 ===============================================================================
00306 
00307 PVS
00308 
00309 ===============================================================================
00310 */
00311 
00312 byte    *CM_ClusterPVS (int cluster) {
00313     if (cluster < 0 || cluster >= cm.numClusters || !cm.vised ) {
00314         return cm.visibility;
00315     }
00316 
00317     return cm.visibility + cluster * cm.clusterBytes;
00318 }
00319 
00320 
00321 
00322 /*
00323 ===============================================================================
00324 
00325 AREAPORTALS
00326 
00327 ===============================================================================
00328 */
00329 
00330 void CM_FloodArea_r( int areaNum, int floodnum) {
00331     int     i;
00332     cArea_t *area;
00333     int     *con;
00334 
00335     area = &cm.areas[ areaNum ];
00336 
00337     if ( area->floodvalid == cm.floodvalid ) {
00338         if (area->floodnum == floodnum)
00339             return;
00340         Com_Error (ERR_DROP, "FloodArea_r: reflooded");
00341     }
00342 
00343     area->floodnum = floodnum;
00344     area->floodvalid = cm.floodvalid;
00345     con = cm.areaPortals + areaNum * cm.numAreas;
00346     for ( i=0 ; i < cm.numAreas  ; i++ ) {
00347         if ( con[i] > 0 ) {
00348             CM_FloodArea_r( i, floodnum );
00349         }
00350     }
00351 }
00352 
00353 /*
00354 ====================
00355 CM_FloodAreaConnections
00356 
00357 ====================
00358 */
00359 void    CM_FloodAreaConnections( void ) {
00360     int     i;
00361     cArea_t *area;
00362     int     floodnum;
00363 
00364     // all current floods are now invalid
00365     cm.floodvalid++;
00366     floodnum = 0;
00367 
00368     for (i = 0 ; i < cm.numAreas ; i++) {
00369         area = &cm.areas[i];
00370         if (area->floodvalid == cm.floodvalid) {
00371             continue;       // already flooded into
00372         }
00373         floodnum++;
00374         CM_FloodArea_r (i, floodnum);
00375     }
00376 
00377 }
00378 
00379 /*
00380 ====================
00381 CM_AdjustAreaPortalState
00382 
00383 ====================
00384 */
00385 void    CM_AdjustAreaPortalState( int area1, int area2, qboolean open ) {
00386     if ( area1 < 0 || area2 < 0 ) {
00387         return;
00388     }
00389 
00390     if ( area1 >= cm.numAreas || area2 >= cm.numAreas ) {
00391         Com_Error (ERR_DROP, "CM_ChangeAreaPortalState: bad area number");
00392     }
00393 
00394     if ( open ) {
00395         cm.areaPortals[ area1 * cm.numAreas + area2 ]++;
00396         cm.areaPortals[ area2 * cm.numAreas + area1 ]++;
00397     } else {
00398         cm.areaPortals[ area1 * cm.numAreas + area2 ]--;
00399         cm.areaPortals[ area2 * cm.numAreas + area1 ]--;
00400         if ( cm.areaPortals[ area2 * cm.numAreas + area1 ] < 0 ) {
00401             Com_Error (ERR_DROP, "CM_AdjustAreaPortalState: negative reference count");
00402         }
00403     }
00404 
00405     CM_FloodAreaConnections ();
00406 }
00407 
00408 /*
00409 ====================
00410 CM_AreasConnected
00411 
00412 ====================
00413 */
00414 qboolean    CM_AreasConnected( int area1, int area2 ) {
00415 #ifndef BSPC
00416     if ( cm_noAreas->integer ) {
00417         return qtrue;
00418     }
00419 #endif
00420 
00421     if ( area1 < 0 || area2 < 0 ) {
00422         return qfalse;
00423     }
00424 
00425     if (area1 >= cm.numAreas || area2 >= cm.numAreas) {
00426         Com_Error (ERR_DROP, "area >= cm.numAreas");
00427     }
00428 
00429     if (cm.areas[area1].floodnum == cm.areas[area2].floodnum) {
00430         return qtrue;
00431     }
00432     return qfalse;
00433 }
00434 
00435 
00436 /*
00437 =================
00438 CM_WriteAreaBits
00439 
00440 Writes a bit vector of all the areas
00441 that are in the same flood as the area parameter
00442 Returns the number of bytes needed to hold all the bits.
00443 
00444 The bits are OR'd in, so you can CM_WriteAreaBits from multiple
00445 viewpoints and get the union of all visible areas.
00446 
00447 This is used to cull non-visible entities from snapshots
00448 =================
00449 */
00450 int CM_WriteAreaBits (byte *buffer, int area)
00451 {
00452     int     i;
00453     int     floodnum;
00454     int     bytes;
00455 
00456     bytes = (cm.numAreas+7)>>3;
00457 
00458 #ifndef BSPC
00459     if (cm_noAreas->integer || area == -1)
00460 #else
00461     if ( area == -1)
00462 #endif
00463     {   // for debugging, send everything
00464         Com_Memset (buffer, 255, bytes);
00465     }
00466     else
00467     {
00468         floodnum = cm.areas[area].floodnum;
00469         for (i=0 ; i<cm.numAreas ; i++)
00470         {
00471             if (cm.areas[i].floodnum == floodnum || area == -1)
00472                 buffer[i>>3] |= 1<<(i&7);
00473         }
00474     }
00475 
00476     return bytes;
00477 }
00478 

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