Click here to Skip to main content
15,896,466 members
Articles / Desktop Programming / Win32

Half Life Game Level Viewer

Rate me:
Please Sign up or sign in to vote.
4.61/5 (23 votes)
7 Feb 2009CPOL26 min read 80K   2.3K   60  
DirectX based application to open and view Half Life 1 game files
//
//	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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
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.

Comments and Discussions