Jump to content
  • Advertisement
Sign in to follow this  
mizuno hadouken

Help Understanding Frustum Calculations

This topic is 2715 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;
dir.Normalize();
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
protected:
struct Plane {
Vector3 normal;
float d;
};

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

////////////////////////////////
// Local Procedures
public:
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
protected:
// 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
public:
PerspectiveCam(float fov) {FOV = fov;}
virtual ~PerspectiveCam() {};

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

// Member Variables
private:
float FOV;
};

Share this post


Link to post
Share on other sites
Advertisement
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"
http://fly.cc.fer.hr.../chapter03.html

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
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!