forked from 0ad/0ad
Ykkrosh
b08e142193
Add shadow filtering (PCF) option. Fix ugly shadow saturation in old lighting mode. Fix fancy water shader. Fix camera matrix computation. Support scissoring of camera frustum. Optimise vertex skinning. Inline various matrix functions. Support filtering of the list of submitted models before a rendering pass, for more precise culling. Optimise water renderer (fixes #721, based on patch by ortalo). Use scissoring when generating reflection/refraction textures. Skip reflection/refraction texture generation when no water is visible. Render alpha-blended objects differently (fixes #434). Reduce shadow swimming effects. This was SVN commit r9814.
189 lines
3.9 KiB
C++
189 lines
3.9 KiB
C++
/* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/*
|
|
* 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/Bound.h"
|
|
#include "maths/MathUtil.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)
|
|
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;
|
|
}
|
|
|
|
bool CFrustum::IsPointVisible (const CVector3D &point) const
|
|
{
|
|
PLANESIDE Side;
|
|
|
|
for (size_t i=0; i<m_NumPlanes; i++)
|
|
{
|
|
Side = m_aPlanes[i].ClassifyPoint (point);
|
|
|
|
if (Side == PS_BACK)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
bool CFrustum::DoesSegmentIntersect(const CVector3D& startRef, const CVector3D &endRef)
|
|
{
|
|
CVector3D start = startRef;
|
|
CVector3D end = endRef;
|
|
|
|
if(IsPointVisible(start) || IsPointVisible(end))
|
|
return true;
|
|
|
|
CVector3D intersect;
|
|
for ( size_t i = 0; i<m_NumPlanes; ++i )
|
|
{
|
|
if ( m_aPlanes[i].FindLineSegIntersection(start, end, &intersect) )
|
|
{
|
|
if ( IsPointVisible( intersect ) )
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
bool CFrustum::IsSphereVisible (const CVector3D ¢er, float radius) const
|
|
{
|
|
for (size_t 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
|
|
{
|
|
//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<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;
|
|
}
|
|
|
|
|