#include "fow.h" #include "fow_lineoccluder.h" #include "fow_viewer.h" // memdbgon must be the last include file in a .cpp file!!! #include //----------------------------------------------------------------------------- // 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