|
//
// CFrustum.cpp
//
// Copyright 2005 Paul Higinbotham
//
#include "stdafx.h"
#include "CFrustum.h"
using namespace ZGraphics;
//
// Accessors for frustum planes. Argument is one of the six frustum planes
// as defined by the FrustPlanes enum.
//
const Planef & CFrustum::FPlane(FrustPlanes ePlane) const
{
assert (ePlane >= 0 && ePlane <= eBottomPlane);
ePlane = (ePlane < 0) ? eNearPlane : ePlane;
ePlane = (ePlane > eBottomPlane) ? eBottomPlane : ePlane;
return m_FrustPlanes[ePlane];
}
Planef & CFrustum::FPlane(FrustPlanes ePlane)
{
assert (ePlane >= 0 && ePlane <= eBottomPlane);
ePlane = (ePlane < 0) ? eNearPlane : ePlane;
ePlane = (ePlane > eBottomPlane) ? eBottomPlane : ePlane;
return m_FrustPlanes[ePlane];
}
//
// Methods to set new view information and recompute the frustum planes
// based on the view information.
//
void CFrustum::SetView(const ZView & rView)
{
m_View = rView;
_computePlanes();
}
void CFrustum::SetView(float fAspect, float fFocalL, float fNearD, float fFarD)
{
m_View.Initialize(fAspect, fFocalL, fNearD, fFarD);
_computePlanes();
}
const ZView & CFrustum::View() const
{
return m_View;
}
// vBB parameter is an array of min [0] and max [1] points of the axis aligned bounding box.
// Method returns zero (0) if any part of the bounding box intersects the frustum.
int CFrustum::TestBoundingBox(const Vector3f vBB[2]) const
{
// Test all eight points of the given bounding box to the six frustum planes.
// If all points lie outside a single plane, then no intersection is possible
int n = eNearPlane;
while (n < eEndPlanes)
{
// Test eight points of bounding volume to plane
int nx, ny, nz;
for (nz=0; nz<2; nz++)
{
for (nx=0; nx<2; nx++)
{
for (ny=0; ny<2; ny++)
{
if (m_FrustPlanes[n].TestPoint((vBB[nx])[0], (vBB[ny])[1], (vBB[nz])[2]) >= -Math<float>::cZeroTolerance)
goto nextplane;
}
}
}
return 1; // All points outside of one plane. No intersection
nextplane:
++n;
}
return 0; // Intersection occurs
}
//
// Internal method functions
//
void CFrustum::_computePlanes()
{
//
// First compute camera frustum pyramid points
//
Vector3f vLeftTopNearPt;
Vector3f vLeftBottomNearPt;
Vector3f vRightTopNearPt;
Vector3f vRightBottomNearPt;
Vector3f vLeftTopFarPt;
Vector3f vLeftBottomFarPt;
Vector3f vRightTopFarPt;
Vector3f vRightBottomFarPt;
float fTanAlpha = std::tan(m_View.AngleAlpha() / 2.0f);
assert(fTanAlpha);
float fTanBeta = std::tan(m_View.AngleBeta() / 2.0f);
assert(fTanBeta);
float fX = m_View.NearPlaneDistance();
float fY = fX * fTanAlpha;
float fZ = fX * fTanBeta;
vLeftTopNearPt[0] = fX;
vLeftTopNearPt[1] = -fY;
vLeftTopNearPt[2] = fZ;
vLeftBottomNearPt[0] = fX;
vLeftBottomNearPt[1] = -fY;
vLeftBottomNearPt[2] = -fZ;
vRightTopNearPt[0] = fX;
vRightTopNearPt[1] = fY;
vRightTopNearPt[2] = fZ;
vRightBottomNearPt[0] = fX;
vRightBottomNearPt[1] = fY;
vRightBottomNearPt[2] = -fZ;
fX = m_View.FarPlaneDistance();
fY = fX * fTanAlpha;
fZ = fX * fTanBeta;
vLeftTopFarPt[0] = fX;
vLeftTopFarPt[1] = -fY;
vLeftTopFarPt[2] = fZ;
vLeftBottomFarPt[0] = fX;
vLeftBottomFarPt[1] = -fY;
vLeftBottomFarPt[2] = -fZ;
vRightTopFarPt[0] = fX;
vRightTopFarPt[1] = fY;
vRightTopFarPt[2] = fZ;
vRightBottomFarPt[0] = fX;
vRightBottomFarPt[1] = fY;
vRightBottomFarPt[2] = -fZ;
//
// Next compute the frustum planes from the frustum pryamid points
// Need to get (L.H. coordinate system) winding right so plane normals point inward.
//
m_FrustPlanes[eNearPlane].SetPlane(vRightTopNearPt, vLeftTopNearPt, vLeftBottomNearPt);
m_FrustPlanes[eFarPlane].SetPlane(vLeftBottomFarPt, vLeftTopFarPt, vRightTopFarPt);
m_FrustPlanes[eLeftPlane].SetPlane(vLeftBottomNearPt, vLeftTopNearPt, vLeftTopFarPt);
m_FrustPlanes[eRightPlane].SetPlane(vRightTopNearPt, vRightBottomFarPt, vRightTopFarPt);
m_FrustPlanes[eTopPlane].SetPlane(vLeftTopNearPt, vRightTopFarPt, vLeftTopFarPt);
m_FrustPlanes[eBottomPlane].SetPlane(vLeftBottomNearPt, vLeftBottomFarPt, vRightBottomFarPt);
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I am a senior software developer currently doing contract work for Microsoft. My educational background is in electrical engineering and I hold a masters degree from the University of Washington. I have experience in hardware and systems design but have done primarily software development for the last two decades. I have worked for various small companies as well as start-up companies, and have worked as a full time employee SDE at Microsoft Corporation.