• Advertisement
Sign in to follow this  

Help Understanding Frustum Calculations

This topic is 2622 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all. I'm having trouble understanding the code below. I'm trying to understand the first part (calculating the 8 parts of the frustum in Wolrd Space) so I've omitted the second part of the code. This is not my code. So basically there are multiple parts of this code I do not understand.

First question - Is vector "A" equal to unit vector x in camera space?
- If A is indeed x, does that make "B" equal to unit vector z in camera space?
- I'm guessing ch is calculating the height, but why is it tan((FOV*pi)/360)?

I've tried to draw an arbitrary frustum and camera space in world space to visualize what's happening, but I just can't understand what's going on. Any help is appreciated. Thank you.

// Name: CalcCullingInfo
// Arguments: An eight element array of Points for each of the frustum
// corners.
// Returns: none
// Side Effects: Stores the plane information (normal and d component) for
// each of the six frustum planes in the local frustumPlanes
// array.
void PerspectiveCam::CalcCullingInfo(Point3 frustumCorners[])
Vector3 dir = Target - Eye;
Vector3 up(0,1,0);
Vector3 A;
A.Cross(dir, up);
Vector3 B;
B.Cross(A, dir);
float ch = tanf(FOV*M_PI/360);
float cw = ch*(float)PixelWidth/PixelHeight;

frustumCorners[0] = Eye + dir*NearClip + A*cw*NearClip + B*ch*NearClip;
frustumCorners[1] = Eye + dir*NearClip - A*cw*NearClip + B*ch*NearClip;
frustumCorners[2] = Eye + dir*NearClip - A*cw*NearClip - B*ch*NearClip;
frustumCorners[3] = Eye + dir*NearClip + A*cw*NearClip - B*ch*NearClip;

frustumCorners[4] = Eye + dir*FarClip + A*cw*FarClip + B*ch*FarClip;
frustumCorners[5] = Eye + dir*FarClip - A*cw*FarClip + B*ch*FarClip;
frustumCorners[6] = Eye + dir*FarClip - A*cw*FarClip - B*ch*FarClip;
frustumCorners[7] = Eye + dir*FarClip + A*cw*FarClip - B*ch*FarClip;

//rest of code

Here's the class header

// Camera
class Camera
// Local Structure
struct Plane {
Vector3 normal;
float d;

// Constructors/Destructors
virtual ~Camera() {};

// Local Procedures
void SetEye(const Point3& eye) { Eye = eye; }
void SetUp(const Vector3& up) { Up = up; }
void SetTarget(const Point3& t) { Target = t; }
void SetNearClip(float nc) { NearClip = nc;}
void SetFarClip(float fc) { FarClip = fc;}

void SetWindowDimensions(unsigned int width,unsigned height)
{ PixelWidth = width; PixelHeight = height; }

Vector3& GetUp() { return Up; }
Point3& GetEye() { return Eye; }
Point3& GetTarget() { return Target; }
float GetNearClip() { return NearClip; }
float GetFarClip() { return FarClip; }

void GetWindowDimensions(unsigned int &width,unsigned &height)
{ width = PixelWidth; height = PixelHeight; }

void CalcInvLookAt(Matrix &out);
virtual void CalcProjectionMatrix(Matrix &out)=0;
virtual void CalcCullingInfo(Point3 *frustumCorners)=0;
void DrawFrustum(Point3 *frustumCorners);
char CullBoundingSphere(const Point3 &pos, float radius);
char TestBoundingSpherePlane(const Point3 &pos, float radius, const Vector3 &normal, float d);

// Member Variables
// main screen params
Point3 Eye;
Point3 Target;
Vector3 Up;
float NearClip, FarClip;
unsigned int PixelWidth,PixelHeight;

// For Culling
Plane frustumPlanes[6];


// PerspectiveCam
class PerspectiveCam : public Camera
// Constructor/Destructor
PerspectiveCam(float fov) {FOV = fov;}
virtual ~PerspectiveCam() {};

// Local Procedures
void SetFOV(float fov) { FOV = fov; }
float& GetFOV() { return FOV; }
void CalcProjectionMatrix(Matrix &out);
void CalcCullingInfo(Point3 *frustumCorners);

// Member Variables
float FOV;

Share this post

Link to post
Share on other sites
It does look like A and B are the side and up vectors for the camera, respectively.

However, I wouldn't compute the corners that way. If you already have the frustum planes, you can instead intersect the planes in sets of three to yield the frustum corners. This way, you'll be guaranteed to get the correct corners as long as the planes themselves are correct (for example, you'll get the correct corners even for an orthographic projection, assuming the planes have been computed correctly).

Share this post

Link to post
Share on other sites
[font="Arial"]A and B are the right and up directions for the camera. A, B, and dir (the vector from eye to look) form a basis (three orthogonal axes), so B is not necessarily the Z-unit vector. You can use A and B with the eye coordinates to make pick rays.

It really doesn't make sense to have a DrawFrustum() for the corners. After the perspective transform, the frustum corners will be the eight corners of the unit cube in clip coordinates. You might see the points drawn in the corners of the display for the near plane and further out for the far plane.

See the "Stages of Vertex Transformation"

Normally, calculations are done [/font][font="Arial"]using the half angle of the field of view. The 360 simple compensates for not using a half FOV angle. A little clearer would be
float ch = tanf(FOV * 0.5 * M_PI / 180.0);[/font]

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement