/* Copyright (C) 2009 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see .
*/
/*
* 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.
*/
#include "precompiled.h"
#include "Frustum.h"
#include "maths/BoundingBoxAligned.h"
#include "maths/MathUtil.h"
#include "maths/Matrix3D.h"
CFrustum::CFrustum ()
{
m_NumPlanes = 0;
}
CFrustum::~CFrustum ()
{
}
void CFrustum::SetNumPlanes (size_t num)
{
m_NumPlanes = num;
//clip it
if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
{
debug_warn(L"CFrustum::SetNumPlanes: Too many planes");
m_NumPlanes = MAX_NUM_FRUSTUM_PLANES-1;
}
}
void CFrustum::AddPlane (const CPlane& plane)
{
if (m_NumPlanes >= MAX_NUM_FRUSTUM_PLANES)
{
debug_warn(L"CFrustum::AddPlane: Too many planes");
return;
}
m_aPlanes[m_NumPlanes++] = plane;
}
void CFrustum::Transform(CMatrix3D& m)
{
for (size_t i = 0; i < m_NumPlanes; i++)
{
CVector3D n = m.Rotate(m_aPlanes[i].m_Norm);
CVector3D p = m.Transform(m_aPlanes[i].m_Norm * -m_aPlanes[i].m_Dist);
m_aPlanes[i].Set(n, p);
m_aPlanes[i].Normalize();
}
}
bool CFrustum::IsPointVisible (const CVector3D &point) const
{
PLANESIDE Side;
for (size_t i=0; i radius)
return false;
}
return true;
}
bool CFrustum::IsBoxVisible (const CVector3D &position,const CBoundingBoxAligned &bounds) const
{
//basically for every plane we calculate the furthest point
//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 (size_t i=0; i 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;
}