This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/common/cm_portals.c

294 lines
6.1 KiB
C
Raw Normal View History

2010-05-22 22:00:00 +02:00
//=======================================================================
// Copyright XashXT Group 2007 <20>
// cm_portals.c - server visibility
//=======================================================================
#include "cm_local.h"
2010-05-25 22:00:00 +02:00
#include "mathlib.h"
2010-05-22 22:00:00 +02:00
static byte fatpvs[MAX_MAP_LEAFS/8];
static byte fatphs[MAX_MAP_LEAFS/8];
2010-05-25 22:00:00 +02:00
static byte *bitvector;
static int fatbytes;
2010-05-22 22:00:00 +02:00
/*
===================
CM_DecompressVis
===================
*/
static byte *CM_DecompressVis( const byte *in )
{
2010-05-24 22:00:00 +02:00
static byte decompressed[MAX_MAP_LEAFS/8];
int c, row;
byte *out;
2010-05-22 22:00:00 +02:00
if( !worldmodel )
{
Host_Error( "CM_DecompressVis: no worldmodel\n" );
return NULL;
}
row = (worldmodel->numleafs + 7)>>3;
2010-05-24 22:00:00 +02:00
out = decompressed;
2010-05-22 22:00:00 +02:00
if( !in )
{
// no vis info, so make all visible
while( row )
{
*out++ = 0xff;
row--;
}
2010-05-24 22:00:00 +02:00
return decompressed;
2010-05-22 22:00:00 +02:00
}
do
{
if( *in )
{
*out++ = *in++;
continue;
}
c = in[1];
in += 2;
while( c )
{
*out++ = 0;
c--;
}
2010-05-24 22:00:00 +02:00
} while( out - decompressed < row );
2010-05-22 22:00:00 +02:00
2010-05-24 22:00:00 +02:00
return decompressed;
2010-05-22 22:00:00 +02:00
}
/*
===============================================================================
PVS / PHS
===============================================================================
*/
/*
=================
CM_CalcPHS
=================
*/
void CM_CalcPHS( void )
{
int i, j, k, l, index, num;
int rowbytes, rowwords;
2010-05-27 22:00:00 +02:00
byte *scan, *visdata;
2010-05-22 22:00:00 +02:00
uint *dest, *src;
int hcount, vcount;
2010-06-17 22:00:00 +02:00
double timestart;
2010-05-27 22:00:00 +02:00
int bitbyte;
2010-05-22 22:00:00 +02:00
2010-05-27 22:00:00 +02:00
if( !worldmodel || !cm.pvs )
2010-05-24 22:00:00 +02:00
return;
2010-06-16 22:00:00 +02:00
MsgDev( D_NOTE, "Building PAS...\n" );
2010-06-17 22:00:00 +02:00
timestart = Sys_DoubleTime();
2010-05-22 22:00:00 +02:00
num = worldmodel->numleafs;
rowwords = (num + 31)>>5;
rowbytes = rowwords * 4;
2010-05-27 22:00:00 +02:00
// store off pointer to compressed visdata
// for right freeing after building pas
visdata = cm.pvs;
// allocate pvs and phs data single array
cm.pvs = Mem_Alloc( worldmodel->mempool, rowbytes * num * 2 );
cm.phs = cm.pvs + rowbytes * num;
2010-05-22 22:00:00 +02:00
scan = cm.pvs;
vcount = 0;
// uncompress pvs first
for( i = 0; i < num; i++, scan += rowbytes )
{
2010-05-27 22:00:00 +02:00
byte *visblock;
2010-05-22 22:00:00 +02:00
2010-05-27 22:00:00 +02:00
visblock = CM_DecompressVis( worldmodel->leafs[i].visdata );
Mem_Copy( scan, visblock, rowbytes );
2010-05-22 22:00:00 +02:00
if( i == 0 ) continue;
for( j = 0; j < num; j++ )
{
if( scan[j>>3] & (1<<( j & 7 )))
vcount++;
}
}
2010-05-27 22:00:00 +02:00
// free compressed pvsdata
Mem_Free( visdata );
2010-05-22 22:00:00 +02:00
scan = cm.pvs;
hcount = 0;
dest = (uint *)cm.phs;
for( i = 0; i < num; i++, dest += rowwords, scan += rowbytes )
{
Mem_Copy( dest, scan, rowbytes );
for( j = 0; j < rowbytes; j++ )
{
bitbyte = scan[j];
if( !bitbyte ) continue;
for( k = 0; k < 8; k++ )
{
if(!( bitbyte & ( 1<<k )))
continue;
// or this pvs row into the phs
// +1 because pvs is 1 based
index = ((j<<3) + k + 1);
if( index >= num ) continue;
src = (uint *)cm.pvs + index * rowwords;
for( l = 0; l < rowwords; l++ )
dest[l] |= src[l];
}
}
2010-05-27 22:00:00 +02:00
// store new leaf pointers for pvs and pas data
worldmodel->leafs[i].visdata = scan;
worldmodel->leafs[i].pasdata = (byte *)dest;
2010-05-22 22:00:00 +02:00
if( i == 0 ) continue;
for( j = 0; j < num; j++ )
{
if(((byte *)dest)[j>>3] & (1<<( j & 7 )))
hcount++;
}
}
2010-06-16 22:00:00 +02:00
MsgDev( D_NOTE, "Average leaves visible / audible / total: %i / %i / %i\n", vcount / num, hcount / num, num );
2010-06-17 22:00:00 +02:00
MsgDev( D_NOTE, "PAS building time: %g secs\n", Sys_DoubleTime() - timestart );
2010-05-22 22:00:00 +02:00
}
/*
=================
CM_LeafPVS
=================
*/
byte *CM_LeafPVS( int leafnum )
{
2010-06-06 22:00:00 +02:00
if( !worldmodel || leafnum <= 0 || leafnum >= worldmodel->numleafs || !cm.pvs || cm_novis->integer )
2010-05-22 22:00:00 +02:00
return cm.nullrow;
2010-05-27 22:00:00 +02:00
2010-05-31 22:00:00 +02:00
return worldmodel->leafs[leafnum+1].visdata;
2010-05-22 22:00:00 +02:00
}
/*
=================
CM_LeafPHS
=================
*/
byte *CM_LeafPHS( int leafnum )
{
2010-06-06 22:00:00 +02:00
if( !worldmodel || leafnum <= 0 || leafnum >= worldmodel->numleafs || !cm.phs || cm_novis->integer )
2010-05-22 22:00:00 +02:00
return cm.nullrow;
2010-05-27 22:00:00 +02:00
2010-05-31 22:00:00 +02:00
return worldmodel->leafs[leafnum+1].pasdata;
2010-05-22 22:00:00 +02:00
}
/*
2010-05-25 22:00:00 +02:00
=============================================================================
2010-05-22 22:00:00 +02:00
2010-05-25 22:00:00 +02:00
The PVS must include a small area around the client to allow head bobbing
or other small motion on the client side. Otherwise, a bob might cause an
entity that should be visible to not show up, especially when the bob
crosses a waterline.
=============================================================================
2010-05-22 22:00:00 +02:00
*/
2010-08-12 22:00:00 +02:00
static void CM_AddToFatPVS( const vec3_t org, int type, mnode_t *node )
2010-05-22 22:00:00 +02:00
{
2010-05-27 22:00:00 +02:00
byte *vis;
2010-08-12 22:00:00 +02:00
mplane_t *plane;
2010-05-25 22:00:00 +02:00
float d;
2010-05-22 22:00:00 +02:00
2010-05-25 22:00:00 +02:00
while( 1 )
{
// if this is a leaf, accumulate the pvs bits
if( node->contents < 0 )
{
if( node->contents != CONTENTS_SOLID )
{
2010-08-12 22:00:00 +02:00
mleaf_t *leaf;
2010-05-25 22:00:00 +02:00
int i;
2010-05-22 22:00:00 +02:00
2010-08-12 22:00:00 +02:00
leaf = (mleaf_t *)node;
2010-05-27 22:00:00 +02:00
if( type == DVIS_PVS )
vis = leaf->visdata;
else if( type == DVIS_PHS )
vis = leaf->pasdata;
else vis = cm.nullrow;
2010-05-22 22:00:00 +02:00
2010-05-25 22:00:00 +02:00
for( i = 0; i < fatbytes; i++ )
2010-05-27 22:00:00 +02:00
bitvector[i] |= vis[i];
2010-05-25 22:00:00 +02:00
}
return;
}
plane = node->plane;
d = DotProduct( org, plane->normal ) - plane->dist;
2010-05-27 22:00:00 +02:00
if( d > 8 ) node = node->children[0];
else if( d < -8 ) node = node->children[1];
2010-05-25 22:00:00 +02:00
else
2010-05-22 22:00:00 +02:00
{
2010-05-25 22:00:00 +02:00
// go down both
2010-05-27 22:00:00 +02:00
CM_AddToFatPVS( org, type, node->children[0] );
2010-05-25 22:00:00 +02:00
node = node->children[1];
2010-05-22 22:00:00 +02:00
}
2010-05-25 22:00:00 +02:00
}
}
2010-05-22 22:00:00 +02:00
2010-05-25 22:00:00 +02:00
/*
============
CM_FatPVS
2010-05-22 22:00:00 +02:00
2010-05-25 22:00:00 +02:00
The client will interpolate the view position,
so we can't use a single PVS point
===========
*/
2010-10-26 22:00:00 +02:00
byte *CM_FatPVS( const vec3_t org, qboolean portal )
2010-05-25 22:00:00 +02:00
{
2010-06-06 22:00:00 +02:00
if( !cm.pvs || cm_novis->integer )
return cm.nullrow;
2010-06-01 22:00:00 +02:00
2010-05-25 22:00:00 +02:00
bitvector = fatpvs;
fatbytes = (worldmodel->numleafs+31)>>3;
if( !portal ) Mem_Set( bitvector, 0, fatbytes );
2010-05-27 22:00:00 +02:00
CM_AddToFatPVS( org, DVIS_PVS, worldmodel->nodes );
2010-05-25 22:00:00 +02:00
return bitvector;
2010-05-22 22:00:00 +02:00
}
/*
============
CM_FatPHS
The client will interpolate the hear position,
so we can't use a single PHS point
===========
*/
2010-10-26 22:00:00 +02:00
byte *CM_FatPHS( const vec3_t org, qboolean portal )
2010-05-22 22:00:00 +02:00
{
2010-06-06 22:00:00 +02:00
if( !cm.pvs || cm_novis->integer )
return cm.nullrow;
2010-06-01 22:00:00 +02:00
2010-05-25 22:00:00 +02:00
bitvector = fatphs;
fatbytes = (worldmodel->numleafs+31)>>3;
if( !portal ) Mem_Set( bitvector, 0, fatbytes );
2010-05-27 22:00:00 +02:00
CM_AddToFatPVS( org, DVIS_PHS, worldmodel->nodes );
2010-05-25 22:00:00 +02:00
return bitvector;
2010-05-22 22:00:00 +02:00
}