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.
367 lines
10 KiB
367 lines
10 KiB
#include "fow_viewer.h"
|
|
#include "fow_radiusoccluder.h"
|
|
#include "fow_lineoccluder.h"
|
|
#include "fow_horizontalslice.h"
|
|
#include "fow.h"
|
|
#include "engine/IVDebugOverlay.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
|
|
extern IVDebugOverlay *debugoverlay;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: constructor to init this viewer with the id and temp
|
|
// Input : nID - the id of this viewer
|
|
// nViewerTeam - the team this viewer is on
|
|
//-----------------------------------------------------------------------------
|
|
CFoW_Viewer::CFoW_Viewer( int nID, unsigned nViewerTeam )
|
|
{
|
|
m_nID = nID;
|
|
m_nViewerTeam = nViewerTeam;
|
|
m_vLocation.Init();
|
|
m_flRadius = 0.0f;
|
|
m_pVisibility = NULL;
|
|
|
|
m_pVisibilityRadius = NULL;
|
|
m_nRadiusUnits = 0;
|
|
m_nHeightGroup = 0;
|
|
|
|
m_nAllocatedMemory = 0;
|
|
|
|
m_bDirty = true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: destructor to free up the local vis grids
|
|
//-----------------------------------------------------------------------------
|
|
CFoW_Viewer::~CFoW_Viewer( void )
|
|
{
|
|
if ( m_pVisibility )
|
|
{
|
|
free( m_pVisibility );
|
|
m_pVisibility = NULL;
|
|
}
|
|
|
|
if ( m_pVisibilityRadius )
|
|
{
|
|
free( m_pVisibilityRadius );
|
|
m_pVisibilityRadius = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: update the radius of the viewer. this will realloc the local vis grids
|
|
// Input : pFoW - the main FoW object
|
|
// flRadius - the new radius
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::UpdateSize( CFoW *pFoW, float flRadius )
|
|
{
|
|
m_flRadius = flRadius;
|
|
|
|
if ( m_pVisibility )
|
|
{
|
|
free( m_pVisibility );
|
|
}
|
|
|
|
if ( m_pVisibilityRadius )
|
|
{
|
|
free( m_pVisibilityRadius );
|
|
}
|
|
|
|
m_nAllocatedMemory = 0;
|
|
|
|
int nGridSize = pFoW->GetHorizontalGridSize();
|
|
|
|
m_nGridUnits = ( ( m_flRadius * 2 ) + nGridSize - 1 ) / nGridSize;
|
|
m_nGridUnits |= 1; // always make it odd, so that we have a true center
|
|
m_pVisibility = ( byte * )malloc( sizeof( m_pVisibility[ 0 ] ) * m_nGridUnits * m_nGridUnits );
|
|
m_nAllocatedMemory += sizeof( m_pVisibility[ 0 ] ) * m_nGridUnits * m_nGridUnits;
|
|
|
|
m_nRadiusUnits = ( ( 2 * M_PI * m_flRadius ) + nGridSize - 1 ) / nGridSize;
|
|
// m_nRadiusUnits = 360;
|
|
m_pVisibilityRadius = ( int * )malloc( sizeof( m_pVisibilityRadius[ 0 ] ) * m_nRadiusUnits );
|
|
m_nAllocatedMemory += sizeof( m_pVisibilityRadius[ 0 ] ) * m_nRadiusUnits;
|
|
|
|
m_pVisibilityTable = pFoW->FindRadiusTable( flRadius );
|
|
|
|
m_bDirty = true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: update the location of the viewer
|
|
// Input : vLocation - the new location
|
|
//-----------------------------------------------------------------------------
|
|
bool CFoW_Viewer::UpdateLocation( CFoW *pFoW, const Vector &vLocation, Vector *pvOldLocation )
|
|
{
|
|
Vector vNewLocation = vLocation;
|
|
|
|
m_vRealLocation = vLocation;
|
|
|
|
pFoW->CenterCoordToGrid( vNewLocation );
|
|
|
|
if ( vNewLocation.x != m_vLocation.x || vNewLocation.y != m_vLocation.y )
|
|
{ // we've moved to a new grid center
|
|
m_bDirty = true;
|
|
if ( pvOldLocation != NULL )
|
|
{
|
|
*pvOldLocation = m_vLocation;
|
|
}
|
|
m_vLocation = vNewLocation;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: update the height group of this viewer
|
|
// Input : nHeightGroup - the new height group
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::UpdateHeightGroup( uint8 nHeightGroup )
|
|
{
|
|
if ( m_nHeightGroup != nHeightGroup )
|
|
{
|
|
m_bDirty = true;
|
|
}
|
|
|
|
m_nHeightGroup = nHeightGroup;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: get the upper left coords of this viewer
|
|
// Output : vResults - the upper left location of this viewer
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::GetStartPosition( Vector2D &vResults )
|
|
{
|
|
vResults.x = m_vLocation.x - m_flRadius;
|
|
vResults.y = m_vLocation.y - m_flRadius;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: get the lower right coords of this viewer
|
|
// Output : vResults - the lower right of this viewer
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::GetEndPosition( Vector2D &vResults )
|
|
{
|
|
vResults.x = m_vLocation.x + m_flRadius;
|
|
vResults.y = m_vLocation.y + m_flRadius;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: calculate the localized visibility against all occluders.
|
|
// Input : pFoW - the main FoW object
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::CalcLocalizedVisibility( CFoW *pFoW )
|
|
{
|
|
if ( m_bDirty == false )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// DefaultViewingArea( pFoW );
|
|
DefaultViewingRadius( pFoW );
|
|
|
|
pFoW->ObstructOccludersNearViewer( m_nID );
|
|
|
|
#if 0
|
|
int NumOccluders = FoW->GetNumOccluders();
|
|
|
|
for ( int i = 0; i < NumOccluders; i++ )
|
|
{
|
|
CFoW_RadiusOccluder *Occluder = FoW->GetOccluder( i );
|
|
|
|
if ( !Occluder )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if ( !Occluder->IsInRange( this ) )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Occluder->ObstructViewer( FoW, this );
|
|
}
|
|
#endif
|
|
|
|
int nSliceIndex = pFoW->GetHorizontalSlice( m_vLocation.z );
|
|
if ( nSliceIndex != -1 )
|
|
{
|
|
pFoW->GetSlice( nSliceIndex )->ObstructViewer( pFoW, this );
|
|
}
|
|
|
|
ResolveRadius( pFoW );
|
|
|
|
m_bDirty = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: clear the localized visibility grid to just the raw radius
|
|
// Input : pFoW - the main FoW object
|
|
//-----------------------------------------------------------------------------
|
|
// use this FOW_VG_DEFAULT_VISIBLE
|
|
void CFoW_Viewer::DefaultViewingArea( CFoW *pFoW )
|
|
{
|
|
memset( m_pVisibility, 0, sizeof( m_pVisibility[ 0 ] ) * m_nGridUnits * m_nGridUnits );
|
|
|
|
int nGridSize = pFoW->GetHorizontalGridSize();
|
|
int nOffset = ( m_nGridUnits / 2 ) * nGridSize;
|
|
byte *pVisibility = m_pVisibility;
|
|
int nRadius2 = m_flRadius * m_flRadius;
|
|
|
|
for ( int x = 0, xPos = -nOffset; x < m_nGridUnits; x++, xPos += nGridSize )
|
|
{
|
|
for ( int y = 0, yPos = -nOffset; y < m_nGridUnits; y++, yPos += nGridSize, pVisibility++ )
|
|
{
|
|
if ( ( ( xPos * xPos ) + ( yPos * yPos ) ) <= nRadius2 )
|
|
{
|
|
*pVisibility = FOW_VG_IS_VISIBLE | FOW_VG_DEFAULT_VISIBLE;
|
|
}
|
|
else
|
|
{
|
|
*pVisibility = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: clear the localized radius grid to the maximum distance
|
|
// Input : pFoW - the main FoW object
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::DefaultViewingRadius( CFoW *pFoW )
|
|
{
|
|
int nRadius2 = m_flRadius * m_flRadius;
|
|
|
|
for ( int i = 0; i < m_nRadiusUnits; i++ )
|
|
{
|
|
m_pVisibilityRadius[ i ] = nRadius2;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input :
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::DrawDebugInfo( Vector &vLocation, float flViewRadius, unsigned nFlags )
|
|
{
|
|
if ( ( nFlags & ( FOW_DEBUG_SHOW_VIEWERS_TEAM_0 | FOW_DEBUG_SHOW_VIEWERS_TEAM_1 ) ) == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
Vector vDiff = vLocation - m_vLocation;
|
|
|
|
if ( vDiff.Length2D() > flViewRadius + m_flRadius )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( ( nFlags & FOW_DEBUG_SHOW_VIEWERS_TEAM_0 ) != 0 )
|
|
{
|
|
debugoverlay->AddSphereOverlay( m_vLocation, m_flRadius, 10, 10, 0, 255, 0, 127, FOW_DEBUG_VIEW_TIME );
|
|
debugoverlay->AddBoxOverlay( m_vLocation, Vector( -16.0f, -16.0f, -16.0f ), Vector( 16.0f, 16.0f, 16.0f ), QAngle( 0, 0, 0 ), 0, 255, 0, 127, FOW_DEBUG_VIEW_TIME );
|
|
}
|
|
|
|
if ( ( nFlags & FOW_DEBUG_SHOW_VIEWERS_TEAM_1 ) != 0 )
|
|
{
|
|
debugoverlay->AddSphereOverlay( m_vLocation, m_flRadius, 10, 10, 0, 0, 255, 127, FOW_DEBUG_VIEW_TIME );
|
|
debugoverlay->AddBoxOverlay( m_vLocation, Vector( -16.0f, -16.0f, -16.0f ), Vector( 16.0f, 16.0f, 16.0f ), QAngle( 0, 0, 0 ), 0, 0, 255, 127, FOW_DEBUG_VIEW_TIME );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: turn the radius grid into the localized visibility grid
|
|
// Input : pFoW - the main FoW object
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_Viewer::ResolveRadius( CFoW *pFoW )
|
|
{
|
|
#if 0
|
|
int nGridSize = pFoW->GetHorizontalGridSize();
|
|
int nHalfGridSize = nGridSize / 2;
|
|
byte *pVisibility = m_pVisibility;
|
|
|
|
// int Radius2 = m_flRadius * m_flRadius;
|
|
|
|
for ( int x = 0, xPos = -m_flRadius + nHalfGridSize; x < m_nGridUnits; x++, xPos += nGridSize )
|
|
{
|
|
for ( int y = 0, yPos = -m_flRadius + nHalfGridSize; y < m_nGridUnits; y++, yPos += nGridSize, pVisibility++ )
|
|
{
|
|
float flDist = sqrt( ( float )( ( xPos * xPos ) + ( yPos * yPos ) ) );
|
|
if ( flDist > m_flRadius )
|
|
{
|
|
*pVisibility = 0;
|
|
continue;
|
|
}
|
|
|
|
float nx = xPos / flDist;
|
|
float ny = yPos / flDist;
|
|
|
|
float flAngle = ( 0 * nx ) + ( 1 * ny );
|
|
float flRealAngle = RAD2DEG( acos( flAngle ) );
|
|
|
|
flAngle = -flAngle + 1;
|
|
if ( nx < 0.0f )
|
|
{
|
|
flAngle = 4 - flAngle;
|
|
flRealAngle = 360 - flRealAngle;
|
|
}
|
|
flAngle /= 4.0f;
|
|
flAngle *= m_nRadiusUnits;
|
|
flRealAngle = ( flRealAngle / 360.0f ) * m_nRadiusUnits;
|
|
|
|
if ( flDist <= m_pVisibilityRadius[ ( int )flRealAngle ] )
|
|
{
|
|
*pVisibility = FOW_VG_IS_VISIBLE;
|
|
}
|
|
else
|
|
{
|
|
*pVisibility = 0;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
int nGridSize = pFoW->GetHorizontalGridSize();
|
|
int nOffset = ( m_nGridUnits / 2 ) * nGridSize;
|
|
byte *pVisibility = m_pVisibility;
|
|
int *pVisibilityTable = m_pVisibilityTable;
|
|
|
|
for ( int x = 0, xPos = -nOffset; x < m_nGridUnits; x++, xPos += nGridSize )
|
|
{
|
|
for ( int y = 0, yPos = -nOffset; y < m_nGridUnits; y++, yPos += nGridSize, pVisibility++, pVisibilityTable++ )
|
|
{
|
|
if ( ( *pVisibilityTable ) == -1 )
|
|
{
|
|
*pVisibility = 0;
|
|
continue;
|
|
}
|
|
|
|
float flDist = ( ( xPos * xPos ) + ( yPos * yPos ) );
|
|
if ( flDist <= m_pVisibilityRadius[ *pVisibilityTable ] )
|
|
{
|
|
*pVisibility = FOW_VG_IS_VISIBLE;
|
|
}
|
|
else
|
|
{
|
|
*pVisibility = 0;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#include <tier0/memdbgoff.h>
|