2
===========================================================================
3
Copyright (C) 1999-2005 Id Software, Inc.
5
This file is part of Quake III Arena source code.
7
Quake III Arena source code is free software; you can redistribute it
8
and/or modify it under the terms of the GNU General Public License as
9
published by the Free Software Foundation; either version 2 of the License,
10
or (at your option) any later version.
12
Quake III Arena source code is distributed in the hope that it will be
13
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with Quake III Arena source code; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
===========================================================================
31
int CM_PointLeafnum_r( const vec3_t p, int num ) {
38
node = cm.nodes + num;
42
d = p[plane->type] - plane->dist;
44
d = DotProduct (plane->normal, p) - plane->dist;
46
num = node->children[1];
48
num = node->children[0];
51
c_pointcontents++; // optimize counter
56
int CM_PointLeafnum( const vec3_t p ) {
57
if ( !cm.numNodes ) { // map not loaded
60
return CM_PointLeafnum_r (p, 0);
65
======================================================================
69
======================================================================
73
void CM_StoreLeafs( leafList_t *ll, int nodenum ) {
76
leafNum = -1 - nodenum;
78
// store the lastLeaf even if the list is overflowed
79
if ( cm.leafs[ leafNum ].cluster != -1 ) {
80
ll->lastLeaf = leafNum;
83
if ( ll->count >= ll->maxcount) {
84
ll->overflowed = qtrue;
87
ll->list[ ll->count++ ] = leafNum;
90
void CM_StoreBrushes( leafList_t *ll, int nodenum ) {
97
leafnum = -1 - nodenum;
99
leaf = &cm.leafs[leafnum];
101
for ( k = 0 ; k < leaf->numLeafBrushes ; k++ ) {
102
brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
103
b = &cm.brushes[brushnum];
104
if ( b->checkcount == cm.checkcount ) {
105
continue; // already checked this brush in another leaf
107
b->checkcount = cm.checkcount;
108
for ( i = 0 ; i < 3 ; i++ ) {
109
if ( b->bounds[0][i] >= ll->bounds[1][i] || b->bounds[1][i] <= ll->bounds[0][i] ) {
116
if ( ll->count >= ll->maxcount) {
117
ll->overflowed = qtrue;
120
((cbrush_t **)ll->list)[ ll->count++ ] = b;
124
for ( k = 0 ; k < leaf->numLeafSurfaces ; k++ ) {
125
patch = cm.surfaces[ cm.leafsurfaces[ leaf->firstleafsurface + k ] ];
137
Fills in a list of all the leafs touched
140
void CM_BoxLeafnums_r( leafList_t *ll, int nodenum ) {
147
ll->storeLeafs( ll, nodenum );
151
node = &cm.nodes[nodenum];
153
s = BoxOnPlaneSide( ll->bounds[0], ll->bounds[1], plane );
155
nodenum = node->children[0];
157
nodenum = node->children[1];
160
CM_BoxLeafnums_r( ll, node->children[0] );
161
nodenum = node->children[1];
172
int CM_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *lastLeaf) {
177
VectorCopy( mins, ll.bounds[0] );
178
VectorCopy( maxs, ll.bounds[1] );
180
ll.maxcount = listsize;
182
ll.storeLeafs = CM_StoreLeafs;
184
ll.overflowed = qfalse;
186
CM_BoxLeafnums_r( &ll, 0 );
188
*lastLeaf = ll.lastLeaf;
197
int CM_BoxBrushes( const vec3_t mins, const vec3_t maxs, cbrush_t **list, int listsize ) {
202
VectorCopy( mins, ll.bounds[0] );
203
VectorCopy( maxs, ll.bounds[1] );
205
ll.maxcount = listsize;
206
ll.list = (void *)list;
207
ll.storeLeafs = CM_StoreBrushes;
209
ll.overflowed = qfalse;
211
CM_BoxLeafnums_r( &ll, 0 );
217
//====================================================================
226
int CM_PointContents( const vec3_t p, clipHandle_t model ) {
236
if (!cm.numNodes) { // map not loaded
241
clipm = CM_ClipHandleToModel( model );
244
leafnum = CM_PointLeafnum_r (p, 0);
245
leaf = &cm.leafs[leafnum];
249
for (k=0 ; k<leaf->numLeafBrushes ; k++) {
250
brushnum = cm.leafbrushes[leaf->firstLeafBrush+k];
251
b = &cm.brushes[brushnum];
253
// see if the point is in the brush
254
for ( i = 0 ; i < b->numsides ; i++ ) {
255
d = DotProduct( p, b->sides[i].plane->normal );
256
// FIXME test for Cash
257
// if ( d >= b->sides[i].plane->dist ) {
258
if ( d > b->sides[i].plane->dist ) {
263
if ( i == b->numsides ) {
264
contents |= b->contents;
273
CM_TransformedPointContents
275
Handles offseting and rotation of the end points for moving and
279
int CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles) {
282
vec3_t forward, right, up;
284
// subtract origin offset
285
VectorSubtract (p, origin, p_l);
287
// rotate start and end into the models frame of reference
288
if ( model != BOX_MODEL_HANDLE &&
289
(angles[0] || angles[1] || angles[2]) )
291
AngleVectors (angles, forward, right, up);
293
VectorCopy (p_l, temp);
294
p_l[0] = DotProduct (temp, forward);
295
p_l[1] = -DotProduct (temp, right);
296
p_l[2] = DotProduct (temp, up);
299
return CM_PointContents( p_l, model );
305
===============================================================================
309
===============================================================================
312
byte *CM_ClusterPVS (int cluster) {
313
if (cluster < 0 || cluster >= cm.numClusters || !cm.vised ) {
314
return cm.visibility;
317
return cm.visibility + cluster * cm.clusterBytes;
323
===============================================================================
327
===============================================================================
330
void CM_FloodArea_r( int areaNum, int floodnum) {
335
area = &cm.areas[ areaNum ];
337
if ( area->floodvalid == cm.floodvalid ) {
338
if (area->floodnum == floodnum)
340
Com_Error (ERR_DROP, "FloodArea_r: reflooded");
343
area->floodnum = floodnum;
344
area->floodvalid = cm.floodvalid;
345
con = cm.areaPortals + areaNum * cm.numAreas;
346
for ( i=0 ; i < cm.numAreas ; i++ ) {
348
CM_FloodArea_r( i, floodnum );
355
CM_FloodAreaConnections
359
void CM_FloodAreaConnections( void ) {
364
// all current floods are now invalid
368
for (i = 0 ; i < cm.numAreas ; i++) {
370
if (area->floodvalid == cm.floodvalid) {
371
continue; // already flooded into
374
CM_FloodArea_r (i, floodnum);
381
CM_AdjustAreaPortalState
385
void CM_AdjustAreaPortalState( int area1, int area2, qboolean open ) {
386
if ( area1 < 0 || area2 < 0 ) {
390
if ( area1 >= cm.numAreas || area2 >= cm.numAreas ) {
391
Com_Error (ERR_DROP, "CM_ChangeAreaPortalState: bad area number");
395
cm.areaPortals[ area1 * cm.numAreas + area2 ]++;
396
cm.areaPortals[ area2 * cm.numAreas + area1 ]++;
398
cm.areaPortals[ area1 * cm.numAreas + area2 ]--;
399
cm.areaPortals[ area2 * cm.numAreas + area1 ]--;
400
if ( cm.areaPortals[ area2 * cm.numAreas + area1 ] < 0 ) {
401
Com_Error (ERR_DROP, "CM_AdjustAreaPortalState: negative reference count");
405
CM_FloodAreaConnections ();
414
qboolean CM_AreasConnected( int area1, int area2 ) {
416
if ( cm_noAreas->integer ) {
421
if ( area1 < 0 || area2 < 0 ) {
425
if (area1 >= cm.numAreas || area2 >= cm.numAreas) {
426
Com_Error (ERR_DROP, "area >= cm.numAreas");
429
if (cm.areas[area1].floodnum == cm.areas[area2].floodnum) {
440
Writes a bit vector of all the areas
441
that are in the same flood as the area parameter
442
Returns the number of bytes needed to hold all the bits.
444
The bits are OR'd in, so you can CM_WriteAreaBits from multiple
445
viewpoints and get the union of all visible areas.
447
This is used to cull non-visible entities from snapshots
450
int CM_WriteAreaBits (byte *buffer, int area)
456
bytes = (cm.numAreas+7)>>3;
459
if (cm_noAreas->integer || area == -1)
463
{ // for debugging, send everything
464
Com_Memset (buffer, 255, bytes);
468
floodnum = cm.areas[area].floodnum;
469
for (i=0 ; i<cm.numAreas ; i++)
471
if (cm.areas[i].floodnum == floodnum || area == -1)
472
buffer[i>>3] |= 1<<(i&7);