csgo-2018-source/fow/fow_viewer.cpp
2021-07-24 21:11:47 -07:00

368 lines
10 KiB
C++

#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>