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

239 lines
6.6 KiB
C++

#include "fow.h"
#include "fow_lineoccluder.h"
#include "fow_viewer.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
//-----------------------------------------------------------------------------
// Purpose: construct a line accluder from the given points. the normal is supplied, though if it doesn't match up with the points, then the points are swapped.
// Input : bx - starting x coord
// by - starting y coord
// ex - ending x coord
// ey - ending y coord
// vNormal - the normal coming from a pre-existing plane from which the line was formed
// nSlinceNum - the slice this occluder belongs to
//-----------------------------------------------------------------------------
CFoW_LineOccluder::CFoW_LineOccluder( float bx, float by, float ex, float ey, Vector2D &vNormal, int nSliceNum )
{
m_vStart.Init( bx, by );
m_vEnd.Init( ex, ey );
m_Plane.Init( bx, by, ex, ey );
if ( fabs( m_Plane.GetNormal().x - vNormal.x ) < 0.1f && fabs( m_Plane.GetNormal().y - vNormal.y ) < 0.1f )
{
m_vStart.Init( ex, ey );
m_vEnd.Init( bx, by );
m_Plane.Init( ex, ey, bx, by );
}
m_nSliceNum = nSliceNum;
}
CFoW_LineOccluder::CFoW_LineOccluder( Vector2D &vStart, Vector2D &vEnd, CFOW_2DPlane &Plane, int nSliceNum )
{
m_vStart = vStart;
m_vEnd = vEnd;
m_Plane = Plane;
m_nSliceNum = nSliceNum;
}
// #define SLOW_PATH 1
//-----------------------------------------------------------------------------
// Purpose: determine the occlusion of this line for the viewer
// Input : pFoW - the main FoW object
// pViewer - the viewer to obstruct
//-----------------------------------------------------------------------------
void CFoW_LineOccluder::ObstructViewer( CFoW *pFoW, CFoW_Viewer *pViewer )
{
int nUnits = pViewer->GetRadiusUnits();
int *pVisibility = pViewer->GetVisibilityRadius();
Vector vCenterLocation = pViewer->GetRealLocation(); // we don't want to use the grid centered location, as the z is not centered
float distance = m_Plane.DistanceFrom( vCenterLocation.x, vCenterLocation.y );
if ( distance < 0.0f )
{
return;
}
#ifdef SLOW_PATH
float flDegreeAmount = 360.0 / pViewer->GetRadiusUnits();
CFOW_2DPlane Edge1, Edge2;
Edge1.Init( vCenterLocation.x, vCenterLocation.y, m_vStart.x, m_vStart.y );
Edge2.Init( m_vEnd.x, m_vEnd.y, vCenterLocation.x, vCenterLocation.y );
float flCurrentDegree = 0.0f;
for ( int i = 0; i < nUnits; i++, flCurrentDegree += flDegreeAmount )
{
Vector Location = pViewer->GetLocation();
Location.x += cos( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
Location.y += sin( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
float flDistance = m_Plane.DistanceFromLineStart( vCenterLocation.x, vCenterLocation.y, Location.x, Location.y );
// flDistance *= pViewer->GetSize();
if ( flDistance >= 0.0f )
{
// distance += Viewer->GetSize();
flDistance *= flDistance;
if ( flDistance >= 0.0f && flDistance < pVisibility[ i ] )
{
if ( Edge1.PointInFront( Location.x, Location.y ) && Edge2.PointInFront( Location.x, Location.y ) )
{
pVisibility[ i ] = flDistance;
}
}
}
}
#else
const Vector2D vStraight( 0.0f, 1.0f );
Vector2D P1( m_vStart.x - vCenterLocation.x, m_vStart.y - vCenterLocation.y );
P1.NormalizeInPlace();
Vector2D P2( m_vEnd.x - vCenterLocation.x, m_vEnd.y - vCenterLocation.y );
P2.NormalizeInPlace();
#if 0
float flCurrentDegree = 0.0f;
for ( int i = 0; i < nUnits; i++, flCurrentDegree += flDegreeAmount )
{
Vector Location = pViewer->GetLocation();
Location.x += cos( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
Location.y += sin( DEG2RAD( flCurrentDegree ) ) * pViewer->GetSize();
float flDistance = m_Plane.DistanceFromLineStart( vCenterLocation.x, vCenterLocation.y, Location.x, Location.y );
// flDistance *= pViewer->GetSize();
if ( flDistance >= 0.0f )
{
// distance += Viewer->GetSize();
flDistance *= flDistance;
if ( flDistance >= 0.0f && flDistance < pVisibility[ i ] )
{
if ( Edge1.PointInFront( Location.x, Location.y ) && Edge2.PointInFront( Location.x, Location.y ) )
{
pVisibility[ i ] = flDistance;
}
}
}
}
#endif
if ( fabs( P1.Dot( P2 ) ) > 0.99995f )
{
return;
}
float flDot1 = vStraight.Dot( P1 );
float flPos = acos( flDot1 );
if ( P1.x < 0.0f )
{
flPos = 2.0f * M_PI_F - flPos;
}
float flDot2 = vStraight.Dot( P2 );
float flNeg = acos( flDot2 );
if ( P2.x < 0.0f )
{
flNeg = 2.0f * M_PI_F - flNeg;
}
if ( fabs( flPos - flNeg ) > M_PI_F )
{
if ( flPos < flNeg )
{
flPos += M_PI_F * 2.0f;
}
else
{
flNeg += M_PI_F * 2.0f;
}
}
// float flAng1 = RAD2DEG( flPos );
// float flAng2 = RAD2DEG( flNeg );
float flCurrentDegree, flFinishDegree;
int nStartIndex;
if ( flPos < flNeg )
{
flCurrentDegree = flPos;
flFinishDegree = flNeg;
}
else
{
flCurrentDegree = flNeg;
flFinishDegree = flPos;
}
/* if ( ( flFinishDegree - flCurrentDegree ) > M_PI_F )
{
float flTemp = flCurrentDegree;
flCurrentDegree = flFinishDegree;
flFinishDegree = flTemp + ( 2.0f * M_PI_F );
}
*/
nUnits = pViewer->GetRadiusUnits();
float flDegreeAmount = 2.0f * M_PI_F / nUnits;
nStartIndex = ( int )( flCurrentDegree / flDegreeAmount ) % nUnits;
if ( nStartIndex < 0 )
{
nStartIndex += nUnits;
}
// Vector vViewerLoc = pViewer->GetLocation();
// float flViewerRadius = pViewer->GetSize();
// float flMaxDistance = ( m_vStart - m_vEnd ).LengthSqr() + ( 60.0f * 60.0f );
#if 1
for ( int i = nStartIndex; flCurrentDegree < flFinishDegree; i++, flCurrentDegree += flDegreeAmount )
{
Vector2D vDelta;
if ( i >= nUnits )
{
i = 0;
}
vDelta.x = TableSin( flCurrentDegree );
vDelta.y = TableCos( flCurrentDegree );
#if 0
float flDistance = m_Plane.DistanceFromRay( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
Vector2D vFinal = vCenterLocation.AsVector2D() + ( vDelta * flDistance );
float flDist1 = ( vFinal - m_vStart ).LengthSqr();
float flDist2 = ( vFinal - m_vEnd ).LengthSqr();
if ( flDistance >= 0.0f && ( flDist1 + flDist2 ) < flMaxDistance )
#else
// vDelta = ( vDelta * pViewer->GetSize() ) + vCenterLocation.AsVector2D();
// float flDistance = m_Plane.DistanceFromLineStart( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
float flDistance = m_Plane.DistanceFromRay( vCenterLocation.x, vCenterLocation.y, vDelta.x, vDelta.y );
if ( flDistance >= 0.0f )
#endif
{
flDistance *= flDistance;
if ( flDistance < pVisibility[ i ] )
{
pVisibility[ i ] = flDistance;
}
}
}
#else
int nStart = ( 0.0f / 4.0f ) * nUnits;
int nEnd = ( 1.0f / 4.0f ) * nUnits;
for( ; nStart < nEnd; nStart++ )
{
pVisibility[ nStart ] /= 5.0f;
}
#endif
#endif
}
#include <tier0/memdbgoff.h>