dhewm3/neo/idlib/bv/Box.h
dhewg 736ec20d4d Untangle the epic precompiled.h mess
Don't include the lazy precompiled.h everywhere, only what's
required for the compilation unit.
platform.h needs to be included instead to provide all essential
defines and types.
All includes use the relative path to the neo or the game
specific root.
Move all idlib related includes from idlib/Lib.h to precompiled.h.
precompiled.h still exists for the MFC stuff in tools/.
Add some missing header guards.
2011-12-19 23:21:47 +01:00

300 lines
10 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
Doom 3 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 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 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 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 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_BOX_H__
#define __BV_BOX_H__
#include "idlib/math/Vector.h"
#include "idlib/bv/Bounds.h"
/*
===============================================================================
Oriented Bounding Box
===============================================================================
*/
class idBox {
public:
idBox( void );
explicit idBox( const idVec3 &center, const idVec3 &extents, const idMat3 &axis );
explicit idBox( const idVec3 &point );
explicit idBox( const idBounds &bounds );
explicit idBox( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis );
idBox operator+( const idVec3 &t ) const; // returns translated box
idBox & operator+=( const idVec3 &t ); // translate the box
idBox operator*( const idMat3 &r ) const; // returns rotated box
idBox & operator*=( const idMat3 &r ); // rotate the box
idBox operator+( const idBox &a ) const;
idBox & operator+=( const idBox &a );
idBox operator-( const idBox &a ) const;
idBox & operator-=( const idBox &a );
bool Compare( const idBox &a ) const; // exact compare, no epsilon
bool Compare( const idBox &a, const float epsilon ) const; // compare with epsilon
bool operator==( const idBox &a ) const; // exact compare, no epsilon
bool operator!=( const idBox &a ) const; // exact compare, no epsilon
void Clear( void ); // inside out box
void Zero( void ); // single point at origin
const idVec3 & GetCenter( void ) const; // returns center of the box
const idVec3 & GetExtents( void ) const; // returns extents of the box
const idMat3 & GetAxis( void ) const; // returns the axis of the box
float GetVolume( void ) const; // returns the volume of the box
bool IsCleared( void ) const; // returns true if box are inside out
bool AddPoint( const idVec3 &v ); // add the point, returns true if the box expanded
bool AddBox( const idBox &a ); // add the box, returns true if the box expanded
idBox Expand( const float d ) const; // return box expanded in all directions with the given value
idBox & ExpandSelf( const float d ); // expand box in all directions with the given value
idBox Translate( const idVec3 &translation ) const; // return translated box
idBox & TranslateSelf( const idVec3 &translation ); // translate this box
idBox Rotate( const idMat3 &rotation ) const; // return rotated box
idBox & RotateSelf( const idMat3 &rotation ); // rotate this box
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 IntersectsBox( const idBox &a ) const; // includes touching
bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
// intersection points are (start + dir * scale1) and (start + dir * scale2)
bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
// tight box for a collection of points
void FromPoints( const idVec3 *points, const int numPoints );
// most tight box for a translation
void FromPointTranslation( const idVec3 &point, const idVec3 &translation );
void FromBoxTranslation( const idBox &box, const idVec3 &translation );
// most tight box for a rotation
void FromPointRotation( const idVec3 &point, const idRotation &rotation );
void FromBoxRotation( const idBox &box, const idRotation &rotation );
void ToPoints( idVec3 points[8] ) const;
idSphere ToSphere( void ) const;
// calculates the projection of this box onto the given axis
void AxisProjection( const idVec3 &dir, float &min, float &max ) const;
void AxisProjection( const idMat3 &ax, idBounds &bounds ) const;
// calculates the silhouette of the box
int GetProjectionSilhouetteVerts( const idVec3 &projectionOrigin, idVec3 silVerts[6] ) const;
int GetParallelProjectionSilhouetteVerts( const idVec3 &projectionDir, idVec3 silVerts[6] ) const;
private:
idVec3 center;
idVec3 extents;
idMat3 axis;
};
extern idBox box_zero;
ID_INLINE idBox::idBox( void ) {
}
ID_INLINE idBox::idBox( const idVec3 &center, const idVec3 &extents, const idMat3 &axis ) {
this->center = center;
this->extents = extents;
this->axis = axis;
}
ID_INLINE idBox::idBox( const idVec3 &point ) {
this->center = point;
this->extents.Zero();
this->axis.Identity();
}
ID_INLINE idBox::idBox( const idBounds &bounds ) {
this->center = ( bounds[0] + bounds[1] ) * 0.5f;
this->extents = bounds[1] - this->center;
this->axis.Identity();
}
ID_INLINE idBox::idBox( const idBounds &bounds, const idVec3 &origin, const idMat3 &axis ) {
this->center = ( bounds[0] + bounds[1] ) * 0.5f;
this->extents = bounds[1] - this->center;
this->center = origin + this->center * axis;
this->axis = axis;
}
ID_INLINE idBox idBox::operator+( const idVec3 &t ) const {
return idBox( center + t, extents, axis );
}
ID_INLINE idBox &idBox::operator+=( const idVec3 &t ) {
center += t;
return *this;
}
ID_INLINE idBox idBox::operator*( const idMat3 &r ) const {
return idBox( center * r, extents, axis * r );
}
ID_INLINE idBox &idBox::operator*=( const idMat3 &r ) {
center *= r;
axis *= r;
return *this;
}
ID_INLINE idBox idBox::operator+( const idBox &a ) const {
idBox newBox;
newBox = *this;
newBox.AddBox( a );
return newBox;
}
ID_INLINE idBox &idBox::operator+=( const idBox &a ) {
idBox::AddBox( a );
return *this;
}
ID_INLINE idBox idBox::operator-( const idBox &a ) const {
return idBox( center, extents - a.extents, axis );
}
ID_INLINE idBox &idBox::operator-=( const idBox &a ) {
extents -= a.extents;
return *this;
}
ID_INLINE bool idBox::Compare( const idBox &a ) const {
return ( center.Compare( a.center ) && extents.Compare( a.extents ) && axis.Compare( a.axis ) );
}
ID_INLINE bool idBox::Compare( const idBox &a, const float epsilon ) const {
return ( center.Compare( a.center, epsilon ) && extents.Compare( a.extents, epsilon ) && axis.Compare( a.axis, epsilon ) );
}
ID_INLINE bool idBox::operator==( const idBox &a ) const {
return Compare( a );
}
ID_INLINE bool idBox::operator!=( const idBox &a ) const {
return !Compare( a );
}
ID_INLINE void idBox::Clear( void ) {
center.Zero();
extents[0] = extents[1] = extents[2] = -idMath::INFINITY;
axis.Identity();
}
ID_INLINE void idBox::Zero( void ) {
center.Zero();
extents.Zero();
axis.Identity();
}
ID_INLINE const idVec3 &idBox::GetCenter( void ) const {
return center;
}
ID_INLINE const idVec3 &idBox::GetExtents( void ) const {
return extents;
}
ID_INLINE const idMat3 &idBox::GetAxis( void ) const {
return axis;
}
ID_INLINE float idBox::GetVolume( void ) const {
return ( extents * 2.0f ).LengthSqr();
}
ID_INLINE bool idBox::IsCleared( void ) const {
return extents[0] < 0.0f;
}
ID_INLINE idBox idBox::Expand( const float d ) const {
return idBox( center, extents + idVec3( d, d, d ), axis );
}
ID_INLINE idBox &idBox::ExpandSelf( const float d ) {
extents[0] += d;
extents[1] += d;
extents[2] += d;
return *this;
}
ID_INLINE idBox idBox::Translate( const idVec3 &translation ) const {
return idBox( center + translation, extents, axis );
}
ID_INLINE idBox &idBox::TranslateSelf( const idVec3 &translation ) {
center += translation;
return *this;
}
ID_INLINE idBox idBox::Rotate( const idMat3 &rotation ) const {
return idBox( center * rotation, extents, axis * rotation );
}
ID_INLINE idBox &idBox::RotateSelf( const idMat3 &rotation ) {
center *= rotation;
axis *= rotation;
return *this;
}
ID_INLINE bool idBox::ContainsPoint( const idVec3 &p ) const {
idVec3 lp = p - center;
if ( idMath::Fabs( lp * axis[0] ) > extents[0] ||
idMath::Fabs( lp * axis[1] ) > extents[1] ||
idMath::Fabs( lp * axis[2] ) > extents[2] ) {
return false;
}
return true;
}
ID_INLINE idSphere idBox::ToSphere( void ) const {
return idSphere( center, extents.Length() );
}
ID_INLINE void idBox::AxisProjection( const idVec3 &dir, float &min, float &max ) const {
float d1 = dir * center;
float 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 void idBox::AxisProjection( const idMat3 &ax, idBounds &bounds ) const {
for ( int i = 0; i < 3; i++ ) {
float d1 = ax[i] * center;
float d2 = idMath::Fabs( extents[0] * ( ax[i] * axis[0] ) ) +
idMath::Fabs( extents[1] * ( ax[i] * axis[1] ) ) +
idMath::Fabs( extents[2] * ( ax[i] * axis[2] ) );
bounds[0][i] = d1 - d2;
bounds[1][i] = d1 + d2;
}
}
#endif /* !__BV_BOX_H__ */