You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.7 KiB
158 lines
4.7 KiB
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//===========================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "pvs_extender.h"
|
|
#include "util_shared.h"
|
|
#include "tier1/utlvector.h"
|
|
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
static CUtlVector<CPVS_Extender *> s_AllExtenders;
|
|
CPVS_Extender::CPVS_Extender( void )
|
|
{
|
|
s_AllExtenders.AddToTail( this );
|
|
}
|
|
|
|
CPVS_Extender::~CPVS_Extender( void )
|
|
{
|
|
s_AllExtenders.FindAndFastRemove( this );
|
|
}
|
|
|
|
|
|
void CPVS_Extender::ComputeExtendedPVS( const CBaseEntity *pViewEntity, const Vector &vVisOrigin, unsigned char *outputPVS, int pvssize, int iMaxRecursions )
|
|
{
|
|
int iAllExtenderCount = s_AllExtenders.Count();
|
|
if( iAllExtenderCount == 0 )
|
|
return;
|
|
|
|
static CThreadFastMutex s_PVSExtenderMutex;
|
|
AUTO_LOCK_FM( s_PVSExtenderMutex );
|
|
|
|
CPVS_Extender **pAllExtenders = s_AllExtenders.Base();
|
|
|
|
int iExtenderCount = 0;
|
|
CPVS_Extender **pExtenders = (CPVS_Extender **)stackalloc( sizeof( CPVS_Extender * ) * iAllExtenderCount );
|
|
|
|
//filter out portals that can't possibly extend visibility up-front. So we don't have to do so in our recursions
|
|
for( int i = 0; i != iAllExtenderCount; ++i )
|
|
{
|
|
CPVS_Extender *pExtender = pAllExtenders[i];
|
|
Assert( pExtender );
|
|
|
|
if ( pExtender->IsExtenderValid() )
|
|
{
|
|
if ( pExtender->GetExtenderNetworkProp()->AreaNum() < 0 )
|
|
{
|
|
Assert( false );
|
|
continue;
|
|
}
|
|
|
|
pExtenders[iExtenderCount] = pExtender;
|
|
++iExtenderCount;
|
|
}
|
|
}
|
|
|
|
if( iExtenderCount == 0 )
|
|
return;
|
|
|
|
int iAreasNetworked[MAX_MAP_AREAS];
|
|
iAreasNetworked[0] = pViewEntity->NetworkProp()->AreaNum(); //safe assumption?
|
|
for( int i = 1; i != MAX_MAP_AREAS; ++i )
|
|
{
|
|
iAreasNetworked[i] = -1;
|
|
}
|
|
|
|
//unsigned char *viewEntPVS = (unsigned char *)stackalloc( sizeof( unsigned char ) * pvssize );
|
|
//memcpy( viewEntPVS, outputPVS, sizeof( unsigned char ) * pvssize );
|
|
|
|
unsigned char viewEntPVS[MAX_MAP_LEAFS/8];
|
|
engine->GetPVSForCluster( engine->GetClusterForOrigin( vVisOrigin ), sizeof( viewEntPVS ), viewEntPVS );
|
|
//do we OR that into the output PVS?
|
|
|
|
//grab the local pvs of every extender up front to avoid repeating it in recursions
|
|
//unsigned char *pExtenderPVSs = (unsigned char *)stackalloc( sizeof( unsigned char ) * (MAX_MAP_LEAFS/8) * iPortalCount );
|
|
ExtenderInstanceData_t *pExtenderData = (ExtenderInstanceData_t *)stackalloc( sizeof( ExtenderInstanceData_t ) * iExtenderCount );
|
|
for( int i = 0; i != iExtenderCount; ++i )
|
|
{
|
|
pExtenders[i]->m_pExtenderData = &pExtenderData[i];
|
|
engine->GetPVSForCluster( engine->GetClusterForOrigin( pExtenders[i]->GetExtensionPVSOrigin() ), sizeof( unsigned char ) * (MAX_MAP_LEAFS/8), pExtenderData[i].iPVSBits );
|
|
pExtenders[i]->m_pExtenderData->bAddedToPVSAlready = false;
|
|
}
|
|
|
|
VisExtensionChain_t chainRoot;
|
|
chainRoot.m_nArea = iAreasNetworked[0];
|
|
chainRoot.pParentChain = NULL;
|
|
|
|
const edict_t *viewEdict = pViewEntity->edict();
|
|
|
|
for( int i = 0; i != iExtenderCount; ++i )
|
|
{
|
|
CPVS_Extender *pExtender = pExtenders[i];
|
|
|
|
if ( pExtender->GetExtenderEdict() == viewEdict )
|
|
continue;
|
|
|
|
if ( pExtender->GetExtenderNetworkProp()->IsInPVS( viewEdict, viewEntPVS, pvssize ) ) //test against pViewEntity PVS, not aggregate PVS
|
|
{
|
|
chainRoot.pExtender = pExtender;
|
|
pExtender->ComputeSubVisibility( pExtenders, iExtenderCount, outputPVS, pvssize, vVisOrigin, NULL, 0, &chainRoot, iAreasNetworked, iMaxRecursions );
|
|
}
|
|
}
|
|
|
|
for( int i = 0; i != iExtenderCount; ++i )
|
|
{
|
|
pExtenders[i]->m_pExtenderData = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//does the grunt work of checking if the data has already been added, and if not, adding it
|
|
/*void CPVS_Extender::AddToPVS( unsigned char *outputPVS, int pvssize, int iAreasNetworked[MAX_MAP_AREAS] )
|
|
{
|
|
|
|
|
|
if( !m_pExtenderData->bAddedToPVSAlready )
|
|
{
|
|
bool bFound = false;
|
|
for( int i = 0; i != MAX_MAP_AREAS; ++i )
|
|
{
|
|
if( iAreasNetworked[i] == iLinkedArea )
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
|
|
if( iAreasNetworked[i] == -1 )
|
|
{
|
|
bFound = true; //we found it by adding it
|
|
iAreasNetworked[i] = iLinkedArea;
|
|
int iOutputPVSIntSize = pvssize / sizeof( unsigned int );
|
|
for( int j = 0; j != iOutputPVSIntSize; ++j )
|
|
{
|
|
((unsigned int *)outputPVS)[j] |= ((unsigned int *)pLinkedPVS)[j];
|
|
}
|
|
for( int j = iOutputPVSIntSize * sizeof( unsigned int ); j != pvssize; ++j )
|
|
{
|
|
outputPVS[j] |= pLinkedPVS[j];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( !bFound )
|
|
return;
|
|
|
|
AddPortalCornersToEnginePVS( pLinkedPortal );
|
|
m_pExtenderData->bAddedToPVSAlready = true;
|
|
}
|
|
}*/
|
|
|
|
|
|
|