Counter Strike : Global Offensive Source Code
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.3 KiB

//===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
//--------------------------------------------------------------------------------------------------
// Dynamic tree
//--------------------------------------------------------------------------------------------------
FORCEINLINE void* CDynamicTree::GetUserData( int32 nProxyId ) const
{
AssertDbg( m_NodePool[ nProxyId ].IsLeaf() );
return m_NodePool[ nProxyId ].m_pUserData;
}
//--------------------------------------------------------------------------------------------------
FORCEINLINE AABB_t CDynamicTree::GetBounds( int32 nProxyId ) const
{
AssertDbg( m_NodePool[ nProxyId ].IsLeaf() );
return m_NodePool[ nProxyId ].m_Bounds;
}
//-------------------------------------------------------------------------------------------------
FORCEINLINE AABB_t CDynamicTree::Inflate( const AABB_t& aabb, float flExtent ) const
{
AABB_t out;
Vector vExtent( flExtent, flExtent, flExtent );
out.m_vMinBounds = aabb.m_vMinBounds - vExtent;
out.m_vMaxBounds = aabb.m_vMaxBounds + vExtent;
return out;
}
//-------------------------------------------------------------------------------------------------
FORCEINLINE AABB_t CDynamicTree::Inflate( const AABB_t& aabb, const Vector& vExtent ) const
{
AABB_t out;
out.m_vMinBounds = aabb.m_vMinBounds - vExtent;
out.m_vMaxBounds = aabb.m_vMaxBounds + vExtent;
return out;
}
//--------------------------------------------------------------------------------------------------
FORCEINLINE void CDynamicTree::ClipRay( const Ray_t& ray, const AABB_t& aabb, float& flMinT, float& flMaxT ) const
{
for ( int nAxis = 0; nAxis < 3; ++nAxis )
{
float t1 = ( aabb.m_vMinBounds[ nAxis ] - ray.vOrigin[ nAxis ] ) * ray.vDeltaInv[ nAxis ];
float t2 = ( aabb.m_vMaxBounds[ nAxis ] - ray.vOrigin[ nAxis ] ) * ray.vDeltaInv[ nAxis ];
flMinT = fpmax( flMinT, fpmin( t1, t2 ) );
flMaxT = fpmin( flMaxT, fpmax( t1, t2 ) );
}
}
//--------------------------------------------------------------------------------------------------
template < typename Functor > void CDynamicTree::CastRay( const Vector& vRayStart, const Vector& vRayDelta, Functor& callback ) const
{
if ( m_nRoot < 0 )
{
AssertDbg( m_nRoot == NULL_NODE );
return;
}
// Setup the ray
Ray_t ray = Ray_t( vRayStart, vRayStart + vRayDelta );
float flBestT = 1.0f;
int nCount = 0;
int32 stack[ STACK_DEPTH ];
stack[ nCount++ ] = m_nRoot;
while ( nCount > 0 )
{
int32 nNode = stack[ --nCount ];
const Node_t& node = m_NodePool[ nNode ];
float flMinT = 0.0f, flMaxT = 1.0f;
ClipRay( ray, node.m_Bounds, flMinT, flMaxT );
if ( flMinT > flMaxT || flMinT > flBestT )
{
continue;
}
if ( !node.IsLeaf() )
{
AssertDbg( nCount + 2 <= STACK_DEPTH );
stack[ nCount++ ] = node.m_nChild2;
stack[ nCount++ ] = node.m_nChild1;
}
else
{
float T = callback( GetUserData( nNode ), vRayStart, vRayDelta, flBestT );
flBestT = fpmin( T, flBestT );
if ( T == 0.0f )
{
// The user terminated the query.
return;
}
}
}
}
//--------------------------------------------------------------------------------------------------
template< typename Functor > void CDynamicTree::CastSphere( const Vector& vRayStart, const Vector& vRayDelta, float flRadius, Functor& callback ) const
{
if ( m_nRoot < 0 )
{
AssertDbg( m_nRoot == NULL_NODE );
return;
}
// Setup the ray
Ray_t ray = Ray_t( vRayStart, vRayStart + vRayDelta );
float flBestT = 1.0f;
int nCount = 0;
int32 stack[ STACK_DEPTH ];
stack[ nCount++ ] = m_nRoot;
while ( nCount > 0 )
{
int32 nNode = stack[ --nCount ];
const Node_t& node = m_NodePool[ nNode ];
float flMinT = 0.0f, flMaxT = 1.0f;
ClipRay( ray, Inflate( node.m_Bounds, flRadius ), flMinT, flMaxT );
if ( flMinT > flMaxT || flMinT > flBestT )
{
continue;
}
if ( !node.IsLeaf() )
{
AssertDbg( nCount + 2 <= STACK_DEPTH );
stack[ nCount++ ] = node.m_nChild2;
stack[ nCount++ ] = node.m_nChild1;
}
else
{
float T = callback( GetUserData( nNode ), vRayStart, vRayDelta, flRadius, flBestT );
flBestT = fpmin( T, flBestT );
if ( T == 0.0f )
{
// The user terminated the query
return;
}
}
}
}
//--------------------------------------------------------------------------------------------------
template< typename Functor > void CDynamicTree::CastBox( const Vector& vRayStart, const Vector& vRayDelta, const Vector& vExtent, Functor& callback ) const
{
if ( m_nRoot < 0 )
{
AssertDbg( m_nRoot == NULL_NODE );
return;
}
// Setup the ray
Ray_t ray = Ray_t( vRayStart, vRayStart + vRayDelta );
float flBestT = 1.0f;
int nCount = 0;
int32 stack[ STACK_DEPTH ];
stack[ nCount++ ] = m_nRoot;
while ( nCount > 0 )
{
int32 nNode = stack[ --nCount ];
const Node_t& node = m_NodePool[ nNode ];
float flMinT = 0.0f, flMaxT = 1.0f;
ClipRay( ray, Inflate( node.m_Bounds, vExtent ), flMinT, flMaxT );
if ( flMinT > flMaxT || flMinT > flBestT )
{
continue;
}
if ( !node.IsLeaf() )
{
AssertDbg( nCount + 2 <= STACK_DEPTH );
stack[ nCount++ ] = node.m_nChild2;
stack[ nCount++ ] = node.m_nChild1;
}
else
{
float T = callback( GetUserData( nNode ), vRayStart, vRayDelta, vExtent, flBestT );
flBestT = fpmin( T, flBestT );
if ( T == 0.0f )
{
// The user terminated the query
return;
}
}
}
}