mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-12-02 17:02:17 +00:00
490 lines
13 KiB
C++
490 lines
13 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#ifndef __BV_BOUNDS_H__
|
|
#define __BV_BOUNDS_H__
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
Axis Aligned Bounding Box
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
class idBounds
|
|
{
|
|
public:
|
|
idBounds();
|
|
explicit idBounds( const idVec3& mins, const idVec3& maxs );
|
|
explicit idBounds( const idVec3& point );
|
|
|
|
const idVec3& operator[]( const int index ) const;
|
|
idVec3& operator[]( const int index );
|
|
idBounds operator+( const idVec3& t ) const; // returns translated bounds
|
|
idBounds& operator+=( const idVec3& t ); // translate the bounds
|
|
idBounds operator*( const idMat3& r ) const; // returns rotated bounds
|
|
idBounds& operator*=( const idMat3& r ); // rotate the bounds
|
|
idBounds operator+( const idBounds& a ) const;
|
|
idBounds& operator+=( const idBounds& a );
|
|
idBounds operator-( const idBounds& a ) const;
|
|
idBounds& operator-=( const idBounds& a );
|
|
|
|
bool Compare( const idBounds& a ) const; // exact compare, no epsilon
|
|
bool Compare( const idBounds& a, const float epsilon ) const; // compare with epsilon
|
|
bool operator==( const idBounds& a ) const; // exact compare, no epsilon
|
|
bool operator!=( const idBounds& a ) const; // exact compare, no epsilon
|
|
|
|
void Clear(); // inside out bounds
|
|
void Zero(); // single point at origin
|
|
|
|
idVec3 GetCenter() const; // returns center of bounds
|
|
float GetRadius() const; // returns the radius relative to the bounds origin
|
|
float GetRadius( const idVec3& center ) const; // returns the radius relative to the given center
|
|
float GetVolume() const; // returns the volume of the bounds
|
|
bool IsCleared() const; // returns true if bounds are inside out
|
|
|
|
bool AddPoint( const idVec3& v ); // add the point, returns true if the bounds expanded
|
|
bool AddBounds( const idBounds& a ); // add the bounds, returns true if the bounds expanded
|
|
idBounds Intersect( const idBounds& a ) const; // return intersection of this bounds with the given bounds
|
|
idBounds& IntersectSelf( const idBounds& a ); // intersect this bounds with the given bounds
|
|
idBounds Expand( const float d ) const; // return bounds expanded in all directions with the given value
|
|
idBounds& ExpandSelf( const float d ); // expand bounds in all directions with the given value
|
|
idBounds Translate( const idVec3& translation ) const; // return translated bounds
|
|
idBounds& TranslateSelf( const idVec3& translation ); // translate this bounds
|
|
idBounds Rotate( const idMat3& rotation ) const; // return rotated bounds
|
|
idBounds& RotateSelf( const idMat3& rotation ); // rotate this bounds
|
|
|
|
float PlaneDistance( const idPlane& plane ) const;
|
|
int PlaneSide( const idPlane& plane, const float epsilon = ON_EPSILON ) const;
|
|
|
|
bool ContainsPoint( const idVec3& p ) const; // includes touching
|
|
bool IntersectsBounds( const idBounds& a ) const; // includes touching
|
|
bool LineIntersection( const idVec3& start, const idVec3& end ) const;
|
|
// intersection point is start + dir * scale
|
|
bool RayIntersection( const idVec3& start, const idVec3& dir, float& scale ) const;
|
|
|
|
// most tight bounds for the given transformed bounds
|
|
void FromTransformedBounds( const idBounds& bounds, const idVec3& origin, const idMat3& axis );
|
|
// most tight bounds for a point set
|
|
void FromPoints( const idVec3* points, const int numPoints );
|
|
// most tight bounds for a translation
|
|
void FromPointTranslation( const idVec3& point, const idVec3& translation );
|
|
void FromBoundsTranslation( const idBounds& bounds, const idVec3& origin, const idMat3& axis, const idVec3& translation );
|
|
// most tight bounds for a rotation
|
|
void FromPointRotation( const idVec3& point, const idRotation& rotation );
|
|
void FromBoundsRotation( const idBounds& bounds, const idVec3& origin, const idMat3& axis, const idRotation& rotation );
|
|
|
|
void ToPoints( idVec3 points[8] ) const;
|
|
idSphere ToSphere() const;
|
|
|
|
void AxisProjection( const idVec3& dir, float& min, float& max ) const;
|
|
void AxisProjection( const idVec3& origin, const idMat3& axis, const idVec3& dir, float& min, float& max ) const;
|
|
|
|
int GetDimension() const;
|
|
|
|
const float* ToFloatPtr() const;
|
|
float* ToFloatPtr();
|
|
|
|
private:
|
|
idVec3 b[2];
|
|
};
|
|
|
|
extern idBounds bounds_zero;
|
|
extern idBounds bounds_zeroOneCube;
|
|
extern idBounds bounds_unitCube;
|
|
|
|
ID_INLINE idBounds::idBounds()
|
|
{
|
|
}
|
|
|
|
ID_INLINE idBounds::idBounds( const idVec3& mins, const idVec3& maxs )
|
|
{
|
|
b[0] = mins;
|
|
b[1] = maxs;
|
|
}
|
|
|
|
ID_INLINE idBounds::idBounds( const idVec3& point )
|
|
{
|
|
b[0] = point;
|
|
b[1] = point;
|
|
}
|
|
|
|
ID_INLINE const idVec3& idBounds::operator[]( const int index ) const
|
|
{
|
|
return b[index];
|
|
}
|
|
|
|
ID_INLINE idVec3& idBounds::operator[]( const int index )
|
|
{
|
|
return b[index];
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::operator+( const idVec3& t ) const
|
|
{
|
|
return idBounds( b[0] + t, b[1] + t );
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::operator+=( const idVec3& t )
|
|
{
|
|
b[0] += t;
|
|
b[1] += t;
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::operator*( const idMat3& r ) const
|
|
{
|
|
idBounds bounds;
|
|
bounds.FromTransformedBounds( *this, vec3_origin, r );
|
|
return bounds;
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::operator*=( const idMat3& r )
|
|
{
|
|
this->FromTransformedBounds( *this, vec3_origin, r );
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::operator+( const idBounds& a ) const
|
|
{
|
|
idBounds newBounds;
|
|
newBounds = *this;
|
|
newBounds.AddBounds( a );
|
|
return newBounds;
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::operator+=( const idBounds& a )
|
|
{
|
|
idBounds::AddBounds( a );
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::operator-( const idBounds& a ) const
|
|
{
|
|
assert( b[1][0] - b[0][0] > a.b[1][0] - a.b[0][0] &&
|
|
b[1][1] - b[0][1] > a.b[1][1] - a.b[0][1] &&
|
|
b[1][2] - b[0][2] > a.b[1][2] - a.b[0][2] );
|
|
return idBounds( idVec3( b[0][0] + a.b[1][0], b[0][1] + a.b[1][1], b[0][2] + a.b[1][2] ),
|
|
idVec3( b[1][0] + a.b[0][0], b[1][1] + a.b[0][1], b[1][2] + a.b[0][2] ) );
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::operator-=( const idBounds& a )
|
|
{
|
|
assert( b[1][0] - b[0][0] > a.b[1][0] - a.b[0][0] &&
|
|
b[1][1] - b[0][1] > a.b[1][1] - a.b[0][1] &&
|
|
b[1][2] - b[0][2] > a.b[1][2] - a.b[0][2] );
|
|
b[0] += a.b[1];
|
|
b[1] += a.b[0];
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE bool idBounds::Compare( const idBounds& a ) const
|
|
{
|
|
return ( b[0].Compare( a.b[0] ) && b[1].Compare( a.b[1] ) );
|
|
}
|
|
|
|
ID_INLINE bool idBounds::Compare( const idBounds& a, const float epsilon ) const
|
|
{
|
|
return ( b[0].Compare( a.b[0], epsilon ) && b[1].Compare( a.b[1], epsilon ) );
|
|
}
|
|
|
|
ID_INLINE bool idBounds::operator==( const idBounds& a ) const
|
|
{
|
|
return Compare( a );
|
|
}
|
|
|
|
ID_INLINE bool idBounds::operator!=( const idBounds& a ) const
|
|
{
|
|
return !Compare( a );
|
|
}
|
|
|
|
ID_INLINE void idBounds::Clear()
|
|
{
|
|
b[0][0] = b[0][1] = b[0][2] = idMath::INFINITY;
|
|
b[1][0] = b[1][1] = b[1][2] = -idMath::INFINITY;
|
|
}
|
|
|
|
ID_INLINE void idBounds::Zero()
|
|
{
|
|
b[0][0] = b[0][1] = b[0][2] =
|
|
b[1][0] = b[1][1] = b[1][2] = 0;
|
|
}
|
|
|
|
ID_INLINE idVec3 idBounds::GetCenter() const
|
|
{
|
|
return idVec3( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
|
|
}
|
|
|
|
ID_INLINE float idBounds::GetVolume() const
|
|
{
|
|
if( b[0][0] >= b[1][0] || b[0][1] >= b[1][1] || b[0][2] >= b[1][2] )
|
|
{
|
|
return 0.0f;
|
|
}
|
|
return ( ( b[1][0] - b[0][0] ) * ( b[1][1] - b[0][1] ) * ( b[1][2] - b[0][2] ) );
|
|
}
|
|
|
|
ID_INLINE bool idBounds::IsCleared() const
|
|
{
|
|
return b[0][0] > b[1][0];
|
|
}
|
|
|
|
ID_INLINE bool idBounds::AddPoint( const idVec3& v )
|
|
{
|
|
bool expanded = false;
|
|
if( v[0] < b[0][0] )
|
|
{
|
|
b[0][0] = v[0];
|
|
expanded = true;
|
|
}
|
|
if( v[0] > b[1][0] )
|
|
{
|
|
b[1][0] = v[0];
|
|
expanded = true;
|
|
}
|
|
if( v[1] < b[0][1] )
|
|
{
|
|
b[0][1] = v[1];
|
|
expanded = true;
|
|
}
|
|
if( v[1] > b[1][1] )
|
|
{
|
|
b[1][1] = v[1];
|
|
expanded = true;
|
|
}
|
|
if( v[2] < b[0][2] )
|
|
{
|
|
b[0][2] = v[2];
|
|
expanded = true;
|
|
}
|
|
if( v[2] > b[1][2] )
|
|
{
|
|
b[1][2] = v[2];
|
|
expanded = true;
|
|
}
|
|
return expanded;
|
|
}
|
|
|
|
ID_INLINE bool idBounds::AddBounds( const idBounds& a )
|
|
{
|
|
bool expanded = false;
|
|
if( a.b[0][0] < b[0][0] )
|
|
{
|
|
b[0][0] = a.b[0][0];
|
|
expanded = true;
|
|
}
|
|
if( a.b[0][1] < b[0][1] )
|
|
{
|
|
b[0][1] = a.b[0][1];
|
|
expanded = true;
|
|
}
|
|
if( a.b[0][2] < b[0][2] )
|
|
{
|
|
b[0][2] = a.b[0][2];
|
|
expanded = true;
|
|
}
|
|
if( a.b[1][0] > b[1][0] )
|
|
{
|
|
b[1][0] = a.b[1][0];
|
|
expanded = true;
|
|
}
|
|
if( a.b[1][1] > b[1][1] )
|
|
{
|
|
b[1][1] = a.b[1][1];
|
|
expanded = true;
|
|
}
|
|
if( a.b[1][2] > b[1][2] )
|
|
{
|
|
b[1][2] = a.b[1][2];
|
|
expanded = true;
|
|
}
|
|
return expanded;
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::Intersect( const idBounds& a ) const
|
|
{
|
|
idBounds n;
|
|
n.b[0][0] = ( a.b[0][0] > b[0][0] ) ? a.b[0][0] : b[0][0];
|
|
n.b[0][1] = ( a.b[0][1] > b[0][1] ) ? a.b[0][1] : b[0][1];
|
|
n.b[0][2] = ( a.b[0][2] > b[0][2] ) ? a.b[0][2] : b[0][2];
|
|
n.b[1][0] = ( a.b[1][0] < b[1][0] ) ? a.b[1][0] : b[1][0];
|
|
n.b[1][1] = ( a.b[1][1] < b[1][1] ) ? a.b[1][1] : b[1][1];
|
|
n.b[1][2] = ( a.b[1][2] < b[1][2] ) ? a.b[1][2] : b[1][2];
|
|
return n;
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::IntersectSelf( const idBounds& a )
|
|
{
|
|
if( a.b[0][0] > b[0][0] )
|
|
{
|
|
b[0][0] = a.b[0][0];
|
|
}
|
|
if( a.b[0][1] > b[0][1] )
|
|
{
|
|
b[0][1] = a.b[0][1];
|
|
}
|
|
if( a.b[0][2] > b[0][2] )
|
|
{
|
|
b[0][2] = a.b[0][2];
|
|
}
|
|
if( a.b[1][0] < b[1][0] )
|
|
{
|
|
b[1][0] = a.b[1][0];
|
|
}
|
|
if( a.b[1][1] < b[1][1] )
|
|
{
|
|
b[1][1] = a.b[1][1];
|
|
}
|
|
if( a.b[1][2] < b[1][2] )
|
|
{
|
|
b[1][2] = a.b[1][2];
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::Expand( const float d ) const
|
|
{
|
|
return idBounds( idVec3( b[0][0] - d, b[0][1] - d, b[0][2] - d ),
|
|
idVec3( b[1][0] + d, b[1][1] + d, b[1][2] + d ) );
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::ExpandSelf( const float d )
|
|
{
|
|
b[0][0] -= d;
|
|
b[0][1] -= d;
|
|
b[0][2] -= d;
|
|
b[1][0] += d;
|
|
b[1][1] += d;
|
|
b[1][2] += d;
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::Translate( const idVec3& translation ) const
|
|
{
|
|
return idBounds( b[0] + translation, b[1] + translation );
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::TranslateSelf( const idVec3& translation )
|
|
{
|
|
b[0] += translation;
|
|
b[1] += translation;
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE idBounds idBounds::Rotate( const idMat3& rotation ) const
|
|
{
|
|
idBounds bounds;
|
|
bounds.FromTransformedBounds( *this, vec3_origin, rotation );
|
|
return bounds;
|
|
}
|
|
|
|
ID_INLINE idBounds& idBounds::RotateSelf( const idMat3& rotation )
|
|
{
|
|
FromTransformedBounds( *this, vec3_origin, rotation );
|
|
return *this;
|
|
}
|
|
|
|
ID_INLINE bool idBounds::ContainsPoint( const idVec3& p ) const
|
|
{
|
|
if( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
|
|
|| p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
ID_INLINE bool idBounds::IntersectsBounds( const idBounds& a ) const
|
|
{
|
|
if( a.b[1][0] < b[0][0] || a.b[1][1] < b[0][1] || a.b[1][2] < b[0][2]
|
|
|| a.b[0][0] > b[1][0] || a.b[0][1] > b[1][1] || a.b[0][2] > b[1][2] )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
ID_INLINE idSphere idBounds::ToSphere() const
|
|
{
|
|
idSphere sphere;
|
|
sphere.SetOrigin( ( b[0] + b[1] ) * 0.5f );
|
|
sphere.SetRadius( ( b[1] - sphere.GetOrigin() ).Length() );
|
|
return sphere;
|
|
}
|
|
|
|
ID_INLINE void idBounds::AxisProjection( const idVec3& dir, float& min, float& max ) const
|
|
{
|
|
float d1, d2;
|
|
idVec3 center, extents;
|
|
|
|
center = ( b[0] + b[1] ) * 0.5f;
|
|
extents = b[1] - center;
|
|
|
|
d1 = dir * center;
|
|
d2 = idMath::Fabs( extents[0] * dir[0] ) +
|
|
idMath::Fabs( extents[1] * dir[1] ) +
|
|
idMath::Fabs( extents[2] * dir[2] );
|
|
|
|
min = d1 - d2;
|
|
max = d1 + d2;
|
|
}
|
|
|
|
ID_INLINE void idBounds::AxisProjection( const idVec3& origin, const idMat3& axis, const idVec3& dir, float& min, float& max ) const
|
|
{
|
|
float d1, d2;
|
|
idVec3 center, extents;
|
|
|
|
center = ( b[0] + b[1] ) * 0.5f;
|
|
extents = b[1] - center;
|
|
center = origin + center * axis;
|
|
|
|
d1 = dir * center;
|
|
d2 = idMath::Fabs( extents[0] * ( dir * axis[0] ) ) +
|
|
idMath::Fabs( extents[1] * ( dir * axis[1] ) ) +
|
|
idMath::Fabs( extents[2] * ( dir * axis[2] ) );
|
|
|
|
min = d1 - d2;
|
|
max = d1 + d2;
|
|
}
|
|
|
|
ID_INLINE int idBounds::GetDimension() const
|
|
{
|
|
return 6;
|
|
}
|
|
|
|
ID_INLINE const float* idBounds::ToFloatPtr() const
|
|
{
|
|
return &b[0].x;
|
|
}
|
|
|
|
ID_INLINE float* idBounds::ToFloatPtr()
|
|
{
|
|
return &b[0].x;
|
|
}
|
|
|
|
#endif /* !__BV_BOUNDS_H__ */
|