241 lines
9.7 KiB
C
241 lines
9.7 KiB
C
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
#ifndef __BV_FRUSTUM_H__
|
||
|
#define __BV_FRUSTUM_H__
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
Orthogonal Frustum
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
class idFrustum {
|
||
|
public:
|
||
|
idFrustum( void );
|
||
|
|
||
|
void SetOrigin( const idVec3 &origin );
|
||
|
void SetAxis( const idMat3 &axis );
|
||
|
void SetSize( float dNear, float dFar, float dLeft, float dUp );
|
||
|
void SetPyramid( float dNear, float dFar );
|
||
|
void MoveNearDistance( float dNear );
|
||
|
void MoveFarDistance( float dFar );
|
||
|
|
||
|
const idVec3 & GetOrigin( void ) const; // returns frustum origin
|
||
|
const idMat3 & GetAxis( void ) const; // returns frustum orientation
|
||
|
idVec3 GetCenter( void ) const; // returns center of frustum
|
||
|
|
||
|
bool IsValid( void ) const; // returns true if the frustum is valid
|
||
|
float GetNearDistance( void ) const; // returns distance to near plane
|
||
|
float GetFarDistance( void ) const; // returns distance to far plane
|
||
|
float GetLeft( void ) const; // returns left vector length
|
||
|
float GetUp( void ) const; // returns up vector length
|
||
|
|
||
|
idFrustum Expand( const float d ) const; // returns frustum expanded in all directions with the given value
|
||
|
idFrustum & ExpandSelf( const float d ); // expands frustum in all directions with the given value
|
||
|
idFrustum Translate( const idVec3 &translation ) const; // returns translated frustum
|
||
|
idFrustum & TranslateSelf( const idVec3 &translation ); // translates frustum
|
||
|
idFrustum Rotate( const idMat3 &rotation ) const; // returns rotated frustum
|
||
|
idFrustum & RotateSelf( const idMat3 &rotation ); // rotates frustum
|
||
|
|
||
|
float PlaneDistance( const idPlane &plane ) const;
|
||
|
int PlaneSide( const idPlane &plane, const float epsilon = ON_EPSILON ) const;
|
||
|
|
||
|
// fast culling but might not cull everything outside the frustum
|
||
|
bool CullPoint( const idVec3 &point ) const;
|
||
|
bool CullBounds( const idBounds &bounds ) const;
|
||
|
bool CullBox( const idBox &box ) const;
|
||
|
bool CullSphere( const idSphere &sphere ) const;
|
||
|
bool CullFrustum( const idFrustum &frustum ) const;
|
||
|
bool CullWinding( const class idWinding &winding ) const;
|
||
|
|
||
|
// exact intersection tests
|
||
|
bool ContainsPoint( const idVec3 &point ) const;
|
||
|
bool IntersectsBounds( const idBounds &bounds ) const;
|
||
|
bool IntersectsBox( const idBox &box ) const;
|
||
|
bool IntersectsSphere( const idSphere &sphere ) const;
|
||
|
bool IntersectsFrustum( const idFrustum &frustum ) const;
|
||
|
bool IntersectsWinding( const idWinding &winding ) const;
|
||
|
bool LineIntersection( const idVec3 &start, const idVec3 &end ) const;
|
||
|
bool RayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||
|
|
||
|
// returns true if the projection origin is far enough away from the bounding volume to create a valid frustum
|
||
|
bool FromProjection( const idBounds &bounds, const idVec3 &projectionOrigin, const float dFar );
|
||
|
bool FromProjection( const idBox &box, const idVec3 &projectionOrigin, const float dFar );
|
||
|
bool FromProjection( const idSphere &sphere, const idVec3 &projectionOrigin, const float dFar );
|
||
|
|
||
|
// moves the far plane so it extends just beyond the bounding volume
|
||
|
bool ConstrainToBounds( const idBounds &bounds );
|
||
|
bool ConstrainToBox( const idBox &box );
|
||
|
bool ConstrainToSphere( const idSphere &sphere );
|
||
|
bool ConstrainToFrustum( const idFrustum &frustum );
|
||
|
|
||
|
void ToPlanes( idPlane planes[6] ) const; // planes point outwards
|
||
|
void ToPoints( idVec3 points[8] ) const; // 8 corners of the frustum
|
||
|
|
||
|
// calculates the projection of this frustum onto the given axis
|
||
|
void AxisProjection( const idVec3 &dir, float &min, float &max ) const;
|
||
|
void AxisProjection( const idMat3 &ax, idBounds &bounds ) const;
|
||
|
|
||
|
// calculates the bounds for the projection in this frustum
|
||
|
bool ProjectionBounds( const idBounds &bounds, idBounds &projectionBounds ) const;
|
||
|
bool ProjectionBounds( const idBox &box, idBounds &projectionBounds ) const;
|
||
|
bool ProjectionBounds( const idSphere &sphere, idBounds &projectionBounds ) const;
|
||
|
bool ProjectionBounds( const idFrustum &frustum, idBounds &projectionBounds ) const;
|
||
|
bool ProjectionBounds( const idWinding &winding, idBounds &projectionBounds ) const;
|
||
|
|
||
|
// calculates the bounds for the projection in this frustum of the given frustum clipped to the given box
|
||
|
bool ClippedProjectionBounds( const idFrustum &frustum, const idBox &clipBox, idBounds &projectionBounds ) const;
|
||
|
|
||
|
private:
|
||
|
idVec3 origin; // frustum origin
|
||
|
idMat3 axis; // frustum orientation
|
||
|
float dNear; // distance of near plane, dNear >= 0.0f
|
||
|
float dFar; // distance of far plane, dFar > dNear
|
||
|
float dLeft; // half the width at the far plane
|
||
|
float dUp; // half the height at the far plane
|
||
|
float invFar; // 1.0f / dFar
|
||
|
|
||
|
private:
|
||
|
bool CullLocalBox( const idVec3 &localOrigin, const idVec3 &extents, const idMat3 &localAxis ) const;
|
||
|
bool CullLocalFrustum( const idFrustum &localFrustum, const idVec3 indexPoints[8], const idVec3 cornerVecs[4] ) const;
|
||
|
bool CullLocalWinding( const idVec3 *points, const int numPoints, int *pointCull ) const;
|
||
|
bool BoundsCullLocalFrustum( const idBounds &bounds, const idFrustum &localFrustum, const idVec3 indexPoints[8], const idVec3 cornerVecs[4] ) const;
|
||
|
bool LocalLineIntersection( const idVec3 &start, const idVec3 &end ) const;
|
||
|
bool LocalRayIntersection( const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||
|
bool LocalFrustumIntersectsFrustum( const idVec3 points[8], const bool testFirstSide ) const;
|
||
|
bool LocalFrustumIntersectsBounds( const idVec3 points[8], const idBounds &bounds ) const;
|
||
|
void ToClippedPoints( const float fractions[4], idVec3 points[8] ) const;
|
||
|
void ToIndexPoints( idVec3 indexPoints[8] ) const;
|
||
|
void ToIndexPointsAndCornerVecs( idVec3 indexPoints[8], idVec3 cornerVecs[4] ) const;
|
||
|
void AxisProjection( const idVec3 indexPoints[8], const idVec3 cornerVecs[4], const idVec3 &dir, float &min, float &max ) const;
|
||
|
void AddLocalLineToProjectionBoundsSetCull( const idVec3 &start, const idVec3 &end, int &startCull, int &endCull, idBounds &bounds ) const;
|
||
|
void AddLocalLineToProjectionBoundsUseCull( const idVec3 &start, const idVec3 &end, int startCull, int endCull, idBounds &bounds ) const;
|
||
|
bool AddLocalCapsToProjectionBounds( const idVec3 endPoints[4], const int endPointCull[4], const idVec3 &point, int pointCull, int pointClip, idBounds &projectionBounds ) const;
|
||
|
bool BoundsRayIntersection( const idBounds &bounds, const idVec3 &start, const idVec3 &dir, float &scale1, float &scale2 ) const;
|
||
|
void ClipFrustumToBox( const idBox &box, float clipFractions[4], int clipPlanes[4] ) const;
|
||
|
bool ClipLine( const idVec3 localPoints[8], const idVec3 points[8], int startIndex, int endIndex, idVec3 &start, idVec3 &end, int &startClip, int &endClip ) const;
|
||
|
};
|
||
|
|
||
|
|
||
|
ID_INLINE idFrustum::idFrustum( void ) {
|
||
|
dNear = dFar = 0.0f;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idFrustum::SetOrigin( const idVec3 &origin ) {
|
||
|
this->origin = origin;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idFrustum::SetAxis( const idMat3 &axis ) {
|
||
|
this->axis = axis;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idFrustum::SetSize( float dNear, float dFar, float dLeft, float dUp ) {
|
||
|
assert( dNear >= 0.0f && dFar > dNear && dLeft > 0.0f && dUp > 0.0f );
|
||
|
this->dNear = dNear;
|
||
|
this->dFar = dFar;
|
||
|
this->dLeft = dLeft;
|
||
|
this->dUp = dUp;
|
||
|
this->invFar = 1.0f / dFar;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idFrustum::SetPyramid( float dNear, float dFar ) {
|
||
|
assert( dNear >= 0.0f && dFar > dNear );
|
||
|
this->dNear = dNear;
|
||
|
this->dFar = dFar;
|
||
|
this->dLeft = dFar;
|
||
|
this->dUp = dFar;
|
||
|
this->invFar = 1.0f / dFar;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idFrustum::MoveNearDistance( float dNear ) {
|
||
|
assert( dNear >= 0.0f );
|
||
|
this->dNear = dNear;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idFrustum::MoveFarDistance( float dFar ) {
|
||
|
assert( dFar > this->dNear );
|
||
|
float scale = dFar / this->dFar;
|
||
|
this->dFar = dFar;
|
||
|
this->dLeft *= scale;
|
||
|
this->dUp *= scale;
|
||
|
this->invFar = 1.0f / dFar;
|
||
|
}
|
||
|
|
||
|
ID_INLINE const idVec3 &idFrustum::GetOrigin( void ) const {
|
||
|
return origin;
|
||
|
}
|
||
|
|
||
|
ID_INLINE const idMat3 &idFrustum::GetAxis( void ) const {
|
||
|
return axis;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idVec3 idFrustum::GetCenter( void ) const {
|
||
|
return ( origin + axis[0] * ( ( dFar - dNear ) * 0.5f ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idFrustum::IsValid( void ) const {
|
||
|
return ( dFar > dNear );
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idFrustum::GetNearDistance( void ) const {
|
||
|
return dNear;
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idFrustum::GetFarDistance( void ) const {
|
||
|
return dFar;
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idFrustum::GetLeft( void ) const {
|
||
|
return dLeft;
|
||
|
}
|
||
|
|
||
|
ID_INLINE float idFrustum::GetUp( void ) const {
|
||
|
return dUp;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idFrustum idFrustum::Expand( const float d ) const {
|
||
|
idFrustum f = *this;
|
||
|
f.origin -= d * f.axis[0];
|
||
|
f.dFar += 2.0f * d;
|
||
|
f.dLeft = f.dFar * dLeft * invFar;
|
||
|
f.dUp = f.dFar * dUp * invFar;
|
||
|
f.invFar = 1.0f / dFar;
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idFrustum &idFrustum::ExpandSelf( const float d ) {
|
||
|
origin -= d * axis[0];
|
||
|
dFar += 2.0f * d;
|
||
|
dLeft = dFar * dLeft * invFar;
|
||
|
dUp = dFar * dUp * invFar;
|
||
|
invFar = 1.0f / dFar;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idFrustum idFrustum::Translate( const idVec3 &translation ) const {
|
||
|
idFrustum f = *this;
|
||
|
f.origin += translation;
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idFrustum &idFrustum::TranslateSelf( const idVec3 &translation ) {
|
||
|
origin += translation;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idFrustum idFrustum::Rotate( const idMat3 &rotation ) const {
|
||
|
idFrustum f = *this;
|
||
|
f.axis *= rotation;
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idFrustum &idFrustum::RotateSelf( const idMat3 &rotation ) {
|
||
|
axis *= rotation;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
#endif /* !__BV_FRUSTUM_H__ */
|