|
|
//========= Copyright � Valve Corporation, All rights reserved. ============//
#ifndef MATHLIB_AABB_HDR
#define MATHLIB_AABB_HDR
#include "mathlib/vector4d.h"
#include "mathlib/vector.h"
#include "mathlib/mathlib.h"
/// Axis-aligned 3d bounding box.
schema struct AABB_t { public: Vector m_vMinBounds; Vector m_vMaxBounds;
FORCEINLINE AABB_t() {}
FORCEINLINE AABB_t( const Vector &vMins, const Vector &vMaxs ) { m_vMinBounds = vMins; m_vMaxBounds = vMaxs; }
FORCEINLINE Vector GetCenter() const { return ( m_vMaxBounds + m_vMinBounds ) / 2.0f; }
/// radius of bounding sphere centered at GetCenter()
FORCEINLINE float GetBoundingRadius( void ) const { return ( m_vMinBounds - GetCenter() ).Length(); }
FORCEINLINE float GetSurfaceArea( void ) const { return BoxSurfaceArea( m_vMinBounds, m_vMaxBounds ); }
/// Calculate the volume. Does not contain special handling for inside-out volumes - if an odd
/// number of axes are inside-out, this will return a negative volume, but if an even number,
/// it will return a positive one.
FORCEINLINE float GetVolume( void ) const { return ComputeVolume( m_vMinBounds, m_vMaxBounds ); }
FORCEINLINE float GetMinDistToPoint( const Vector &vPoint ) const { return CalcDistanceToAABB( m_vMinBounds, m_vMaxBounds, vPoint ); }
FORCEINLINE float GetMinAxialDistanceToPoint( const Vector &vPoint ) const { float flXInterval = MAX( 0, MAX( vPoint.x - m_vMaxBounds.x, m_vMinBounds.x - vPoint.x ) ); float flYInterval = MAX( 0, MAX( vPoint.y - m_vMaxBounds.y, m_vMinBounds.y - vPoint.y ) ); float flZInterval = MAX( 0, MAX( vPoint.z - m_vMaxBounds.z, m_vMinBounds.z - vPoint.z ) ); return MAX( flXInterval, MAX( flYInterval, flZInterval ) ); }
/// expand the aabt_t to contain a point
FORCEINLINE void operator |=( const Vector &vPoint ) { AddPointToBounds( vPoint, m_vMinBounds, m_vMaxBounds ); }
/// expand the bounds to enclose another aabb_t
FORCEINLINE void operator |=( const AABB_t &other ) { VectorMin( other.m_vMinBounds, m_vMinBounds, m_vMinBounds ); VectorMax( other.m_vMaxBounds, m_vMaxBounds, m_vMaxBounds ); }
/// set the bounds to the bounds of the union of this and another aabb_t
FORCEINLINE void operator &=( const AABB_t &other ) { VectorMax( other.m_vMinBounds, m_vMinBounds, m_vMinBounds ); VectorMin( other.m_vMaxBounds, m_vMaxBounds, m_vMaxBounds ); }
void CreatePlanesFrom( Vector4D *pPlanes ) const { // X
pPlanes[0] = Vector4D( 1, 0, 0, -m_vMaxBounds.x ); pPlanes[1] = Vector4D( -1, 0, 0, m_vMinBounds.x );
// Y
pPlanes[2] = Vector4D( 0, 1, 0, -m_vMaxBounds.y ); pPlanes[3] = Vector4D( 0, -1, 0, m_vMinBounds.y );
// Z
pPlanes[4] = Vector4D( 0, 0, 1, -m_vMaxBounds.z ); pPlanes[5] = Vector4D( 0, 0, -1, m_vMinBounds.z ); }
/// Set the aabb to be invalid (max < min )
void MakeInvalid( void ) { m_vMinBounds.Init( FLT_MAX, FLT_MAX, FLT_MAX ); m_vMaxBounds.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); }
// Returns if the bounds are invalid (negative volume), this is different
// than empty, the bounds are still considered valid if min == max.
FORCEINLINE bool IsInvalid() const { return ( ( m_vMinBounds.x > m_vMaxBounds.x ) || ( m_vMinBounds.y > m_vMaxBounds.y ) || ( m_vMinBounds.z > m_vMaxBounds.z ) ); }
/// Return if the bounding box has either 0 or negative volume (i.e. if min >= max for any
/// coord ). Note that this treats bounds set to a single point as empty.
FORCEINLINE bool IsEmpty( void ) const { return ( ( m_vMinBounds.x >= m_vMaxBounds.x ) || ( m_vMinBounds.y >= m_vMaxBounds.y ) || ( m_vMinBounds.z >= m_vMaxBounds.z ) ); }
FORCEINLINE bool Overlaps( AABB_t bBox ) const { bBox &= *this; return (! bBox.IsEmpty() ); }
FORCEINLINE bool ContainsPoint( Vector const &vPnt ) const { return ( ( vPnt.x >= m_vMinBounds.x ) && ( vPnt.y >= m_vMinBounds.y ) && ( vPnt.z >= m_vMinBounds.z ) && ( vPnt.x <= m_vMaxBounds.x ) && ( vPnt.y <= m_vMaxBounds.y ) && ( vPnt.z <= m_vMaxBounds.z ) ); }
FORCEINLINE bool Contains( const AABB_t &box ) const { return ( ( box.m_vMinBounds.x >= m_vMinBounds.x ) && ( box.m_vMinBounds.y >= m_vMinBounds.y ) && ( box.m_vMinBounds.z >= m_vMinBounds.z ) && ( box.m_vMaxBounds.x <= m_vMaxBounds.x ) && ( box.m_vMaxBounds.y <= m_vMaxBounds.y ) && ( box.m_vMaxBounds.z <= m_vMaxBounds.z ) ); }
/// set the aabb_t to a zero volume point in space.
FORCEINLINE void SetToPoint( Vector const &vPnt ) { m_vMinBounds = vPnt; m_vMaxBounds = vPnt; }
FORCEINLINE float LengthOfSmallestDimension() const { Vector vDelta = m_vMaxBounds - m_vMinBounds; return vDelta.SmallestComponentValue(); }
FORCEINLINE const Vector GetSize() const { return m_vMaxBounds - m_vMinBounds; }
FORCEINLINE void EnsureMinSize( const Vector &vMinSize ) { Vector vHalfExpand = VectorMax( Vector( 0,0,0 ), vMinSize - GetSize() ) * 0.5f; m_vMaxBounds += vHalfExpand; m_vMinBounds -= vHalfExpand; }
FORCEINLINE void Move( const Vector &vDelta ) { m_vMinBounds += vDelta; m_vMaxBounds += vDelta; }
FORCEINLINE void Expand( float flRadius ) { m_vMinBounds -= Vector( flRadius, flRadius, flRadius ); m_vMaxBounds += Vector( flRadius, flRadius, flRadius ); } };
inline const AABB_t Snap( const AABB_t& aabb, float flSnap ) { return AABB_t( Snap( aabb.m_vMinBounds, flSnap ), Snap( aabb.m_vMaxBounds, flSnap ) ); }
inline AABB_t operator+( const AABB_t& aabb1, const AABB_t& aabb2 ) { Vector vMin = VectorMin( aabb1.m_vMinBounds, aabb2.m_vMinBounds ); Vector vMax = VectorMax( aabb1.m_vMaxBounds, aabb2.m_vMaxBounds ); return AABB_t( vMin, vMax ); }
FORCEINLINE void TransformAABB( const matrix3x4_t &matTransform, AABB_t const &boundsIn, AABB_t *pBoundsOut ) { TransformAABB( matTransform, boundsIn.m_vMinBounds, boundsIn.m_vMaxBounds, pBoundsOut->m_vMinBounds, pBoundsOut->m_vMaxBounds ); }
inline AABB_t GetAabb( const VectorAligned *pPos, int nCount ) { AABB_t aabb; aabb.MakeInvalid(); for ( int i = 0; i < nCount; ++i ) { aabb |= pPos[ i ]; } return aabb; };
#endif
|