2007-05-07 18:33:24 +02:00
|
|
|
/**
|
|
|
|
* =========================================================================
|
|
|
|
* File : Frustum.cpp
|
|
|
|
* Project : 0 A.D.
|
|
|
|
* Description : CFrustum is a collection of planes which define
|
|
|
|
* a viewing space.
|
|
|
|
* =========================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
Usually associated with the camera, there are 6 planes which define the
|
|
|
|
view pyramid. But we allow more planes per frustum which may be used for
|
|
|
|
portal rendering, where a portal may have 3 or more edges.
|
|
|
|
*/
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2004-06-03 20:38:14 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
#include "Frustum.h"
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "maths/Bound.h"
|
2006-08-25 21:31:01 +02:00
|
|
|
#include "maths/MathUtil.h"
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
CFrustum::CFrustum ()
|
|
|
|
{
|
|
|
|
m_NumPlanes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CFrustum::~CFrustum ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CFrustum::SetNumPlanes (int num)
|
|
|
|
{
|
|
|
|
m_NumPlanes = num;
|
|
|
|
|
|
|
|
//clip it
|
|
|
|
if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
|
|
|
|
m_NumPlanes = MAX_NUM_FRUSTUM_PLANES-1;
|
|
|
|
else if (m_NumPlanes < 0)
|
|
|
|
m_NumPlanes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CFrustum::IsPointVisible (const CVector3D &point) const
|
|
|
|
{
|
|
|
|
PLANESIDE Side;
|
|
|
|
|
|
|
|
for (int i=0; i<m_NumPlanes; i++)
|
|
|
|
{
|
|
|
|
Side = m_aPlanes[i].ClassifyPoint (point);
|
|
|
|
|
|
|
|
if (Side == PS_BACK)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2006-08-25 21:31:01 +02:00
|
|
|
bool CFrustum::DoesSegmentIntersect(const CVector3D& startRef, const CVector3D &endRef)
|
2006-08-25 08:04:33 +02:00
|
|
|
{
|
2006-08-25 21:31:01 +02:00
|
|
|
CVector3D start = startRef;
|
|
|
|
CVector3D end = endRef;
|
|
|
|
|
|
|
|
if(IsPointVisible(start) || IsPointVisible(end))
|
|
|
|
return true;
|
|
|
|
|
2006-08-25 08:04:33 +02:00
|
|
|
CVector3D intersect;
|
|
|
|
for ( int i = 0; i<m_NumPlanes; ++i )
|
|
|
|
{
|
|
|
|
if ( m_aPlanes[i].FindLineSegIntersection(start, end, &intersect) )
|
2006-08-25 21:31:01 +02:00
|
|
|
{
|
|
|
|
if ( IsPointVisible( intersect ) )
|
|
|
|
return true;
|
|
|
|
}
|
2006-08-25 08:04:33 +02:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2004-05-29 22:56:24 +02:00
|
|
|
bool CFrustum::IsSphereVisible (const CVector3D ¢er, float radius) const
|
|
|
|
{
|
|
|
|
for (int i=0; i<m_NumPlanes; i++)
|
|
|
|
{
|
|
|
|
float Dist = m_aPlanes[i].DistanceToPlane (center);
|
|
|
|
|
|
|
|
//is it behind the plane
|
|
|
|
if (Dist < 0)
|
|
|
|
{
|
|
|
|
//if non of it falls in front its outside the
|
|
|
|
//frustum
|
|
|
|
if (-Dist > radius)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CFrustum::IsBoxVisible (const CVector3D &position,const CBound &bounds) const
|
|
|
|
{
|
2005-03-18 23:30:23 +01:00
|
|
|
//basically for every plane we calculate the furthest point
|
2004-05-29 22:56:24 +02:00
|
|
|
//in the box to that plane. If that point is beyond the plane
|
|
|
|
//then the box is not visible
|
|
|
|
CVector3D FarPoint;
|
|
|
|
PLANESIDE Side;
|
|
|
|
CVector3D Min = position+bounds[0];
|
|
|
|
CVector3D Max = position+bounds[1];
|
|
|
|
|
|
|
|
for (int i=0; i<m_NumPlanes; i++)
|
|
|
|
{
|
|
|
|
if (m_aPlanes[i].m_Norm.X > 0.0f)
|
|
|
|
{
|
|
|
|
if (m_aPlanes[i].m_Norm.Y > 0.0f)
|
|
|
|
{
|
|
|
|
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
|
|
{
|
|
|
|
FarPoint.X = Max.X; FarPoint.Y = Max.Y; FarPoint.Z = Max.Z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FarPoint.X = Max.X; FarPoint.Y = Max.Y; FarPoint.Z = Min.Z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
|
|
{
|
|
|
|
FarPoint.X = Max.X; FarPoint.Y = Min.Y; FarPoint.Z = Max.Z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FarPoint.X = Max.X; FarPoint.Y = Min.Y; FarPoint.Z = Min.Z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_aPlanes[i].m_Norm.Y > 0.0f)
|
|
|
|
{
|
|
|
|
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
|
|
{
|
|
|
|
FarPoint.X = Min.X; FarPoint.Y = Max.Y; FarPoint.Z = Max.Z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FarPoint.X = Min.X; FarPoint.Y = Max.Y; FarPoint.Z = Min.Z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_aPlanes[i].m_Norm.Z > 0.0f)
|
|
|
|
{
|
|
|
|
FarPoint.X = Min.X; FarPoint.Y = Min.Y; FarPoint.Z = Max.Z;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FarPoint.X = Min.X; FarPoint.Y = Min.Y; FarPoint.Z = Min.Z;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Side = m_aPlanes[i].ClassifyPoint (FarPoint);
|
|
|
|
|
|
|
|
if (Side == PS_BACK)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
|