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.
206 lines
5.8 KiB
206 lines
5.8 KiB
#include "fow.h"
|
|
#include "fow_trisoup.h"
|
|
#include "fow_lineoccluder.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include <tier0/memdbgon.h>
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: constructor to init this collection with the id
|
|
// Input : nID - unused
|
|
//-----------------------------------------------------------------------------
|
|
CFoW_TriSoupCollection::CFoW_TriSoupCollection( unsigned nID )
|
|
{
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: destructor to dealloc the occluders
|
|
//-----------------------------------------------------------------------------
|
|
CFoW_TriSoupCollection::~CFoW_TriSoupCollection( void )
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: clears all entries from the collection ( useful for hammer editing only )
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_TriSoupCollection::Clear( void )
|
|
{
|
|
m_Occluders.PurgeAndDeleteElements();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: adds a tri to the collection. this is immediately split up into the horizontal slices. very slow!
|
|
// Input : pFoW - the main FoW object
|
|
// vPointA - a point on the tri
|
|
// vPointB - a point on the tri
|
|
// vPointC - a point on the tri
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_TriSoupCollection::AddTri( CFoW *pFoW, Vector &vPointA, Vector &vPointB, Vector &vPointC )
|
|
{
|
|
Vector vVerts[ 3 ], vOutVerts[ 8 ];
|
|
int nBottomZ;
|
|
int nGridSize;
|
|
int nGridUnits;
|
|
Vector vNormal, vTestNormal;
|
|
float flIntercept;
|
|
float *pflVerticalLevels;
|
|
|
|
vVerts[ 0 ] = vPointA;
|
|
vVerts[ 1 ] = vPointB;
|
|
vVerts[ 2 ] = vPointC;
|
|
|
|
pFoW->GetVerticalGridInfo( nBottomZ, nGridSize, nGridUnits, &pflVerticalLevels );
|
|
|
|
ComputeTrianglePlane( vPointA, vPointB, vPointC, vNormal, flIntercept );
|
|
vTestNormal = vNormal;
|
|
vTestNormal.z = 0.0f;
|
|
vTestNormal.NormalizeInPlace();
|
|
Vector2D vTestNormal2( vTestNormal.x, vTestNormal.y );
|
|
|
|
for ( int i = 0; i < nGridUnits; i++ )
|
|
{
|
|
nBottomZ = pflVerticalLevels[ i ] + 16.0f;
|
|
|
|
int nCount = HorizontalSplitTri( vVerts, 3, vOutVerts, nBottomZ, 0.0f );
|
|
if ( nCount == 2 )
|
|
{
|
|
CFoW_LineOccluder *pOccluder = new CFoW_LineOccluder( vOutVerts[ 0 ].x, vOutVerts[ 0 ].y, vOutVerts[ 1 ].x, vOutVerts[ 1 ].y, vTestNormal2, i );
|
|
m_Occluders.AddToTail( pOccluder );
|
|
pFoW->AddTriSoupOccluder( pOccluder, i );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: adds all occluders back into the visibility tree
|
|
// Input : pFoW - the main FoW object
|
|
//-----------------------------------------------------------------------------
|
|
void CFoW_TriSoupCollection::RepopulateOccluders( CFoW *pFoW )
|
|
{
|
|
for ( int i = 0; i < m_Occluders.Count(); i++ )
|
|
{
|
|
pFoW->AddTriSoupOccluder( m_Occluders[ i ], m_Occluders[ i ]->GetSliceNum() );
|
|
}
|
|
}
|
|
|
|
|
|
#if 0
|
|
void CFoW_TriSoupCollection::ObstructViewer( CFoW *FoW, CFoW_Viewer *Viewer )
|
|
{
|
|
for ( int i = 0; i < m_Occluders.Count(); i++ )
|
|
{
|
|
m_Occluders[ i ].ObstructViewer( FoW, Viewer );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: clip a poly to the horizontal plane and return the poly on the front side of the plane
|
|
// Input : *pInVerts - input polygon
|
|
// nVertCount - # verts in input poly
|
|
// *pOutVerts - destination poly
|
|
// flDist - plane constant
|
|
// flOnPlaneEpsilon - the fudge factor for determining if a point is within the plane edge
|
|
// Output : int - # verts in output poly
|
|
//-----------------------------------------------------------------------------
|
|
int CFoW_TriSoupCollection::HorizontalSplitTri( Vector *pInVerts, int nVertCount, Vector *pOutVerts, float flDist, float flOnPlaneEpsilon )
|
|
{
|
|
vec_t *pDists = ( vec_t * )stackalloc( sizeof( vec_t ) * nVertCount * 4 ); //4x vertcount should cover all cases
|
|
int *pSides = ( int * )stackalloc( sizeof( vec_t ) * nVertCount * 4 );
|
|
int nCounts[ 3 ];
|
|
vec_t flDot;
|
|
int i, j;
|
|
Vector vMid = vec3_origin;
|
|
int nOutCount;
|
|
Vector vNormal( 0.0f, 0.0f, 1.0f );
|
|
|
|
nCounts[ 0 ] = nCounts[ 1 ] = nCounts[ 2 ] = 0;
|
|
|
|
// determine sides for each point
|
|
for ( i = 0; i < nVertCount; i++ )
|
|
{
|
|
flDot = DotProduct( pInVerts[ i ], vNormal ) - flDist;
|
|
pDists[ i ] = flDot;
|
|
if ( flDot > flOnPlaneEpsilon )
|
|
{
|
|
pSides[ i ] = SIDE_FRONT;
|
|
}
|
|
else if ( flDot < -flOnPlaneEpsilon )
|
|
{
|
|
pSides[ i ] = SIDE_BACK;
|
|
}
|
|
else
|
|
{
|
|
pSides[ i ] = SIDE_ON;
|
|
}
|
|
nCounts[ pSides[ i ] ]++;
|
|
}
|
|
pSides[ i ] = pSides[ 0 ];
|
|
pDists[ i ] = pDists[ 0 ];
|
|
|
|
if ( !nCounts[ SIDE_FRONT ] )
|
|
{ // if this has 2 sides that are side_on, then this should be a tri coming soon with the same two sides that are on, but with one on side_back
|
|
return 0;
|
|
}
|
|
|
|
nOutCount = 0;
|
|
for ( i = 0; i < nVertCount; i++ )
|
|
{
|
|
int nCurrent = ( i + 0 ) % nVertCount;
|
|
int nNext = ( i + 1 ) % nVertCount;
|
|
|
|
Vector &p1 = pInVerts[ nCurrent ];
|
|
|
|
if ( pSides[ nCurrent ] == SIDE_ON )
|
|
{
|
|
VectorCopy( p1, pOutVerts[ nOutCount ] );
|
|
nOutCount++;
|
|
continue;
|
|
}
|
|
|
|
if ( pSides[ nCurrent ] == SIDE_FRONT )
|
|
{
|
|
// VectorCopy( p1, outVerts[outCount]);
|
|
// outCount++;
|
|
}
|
|
|
|
if ( pSides[ nNext ] == SIDE_ON || pSides[ nNext ] == pSides[ nCurrent ] )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// generate a split point
|
|
Vector &p2 = pInVerts[ nNext ];
|
|
|
|
flDot = pDists[ nCurrent ] / ( pDists[ nCurrent ] - pDists[ nNext ] );
|
|
for ( j = 0; j < 3; j++ )
|
|
{ // avoid round off error when possible
|
|
if ( vNormal[ j ] == 1 )
|
|
{
|
|
vMid[ j ] = flDist;
|
|
}
|
|
else if ( vNormal[ j ] == -1 )
|
|
{
|
|
vMid[ j ] = -flDist;
|
|
}
|
|
else
|
|
{
|
|
vMid[ j ] = p1[ j ] + flDot * ( p2[ j ] - p1[ j ] );
|
|
}
|
|
}
|
|
|
|
VectorCopy ( vMid, pOutVerts[ nOutCount ] );
|
|
nOutCount++;
|
|
}
|
|
|
|
return nOutCount;
|
|
}
|
|
|
|
#include <tier0/memdbgoff.h>
|
|
|