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
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;
|
|
}
|
|
}
|
|
}
|
|
}
|