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.
 
 
 
 
 
 

218 lines
6.0 KiB

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