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