239 lines
6.6 KiB
C++
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>
|