# geometry - Calculating the Viewing Frustum in a 3D Space

I have drawn diagram after diagram of how to calculate the bounding points of the viewing frustum in a three-dimensional space. To start, I have a two sets of data containing three values each: the xyz coordinates of the camera and the rotation around the x, y, and z axis. Given a certain view distance, it should be possible to calculate the bounding points of each of the 6 planes. I have been using these equations to calculate the width and height of the far plane:

``hfar = 2 * tan(45/2) * view_distancewfar = hfar * ratio``

hfar being the height of the far plane, wfar being the width, and ratio being the ratio of the view port width divided by the height. I have been using the following diagram to try and figure it out: I need to find the points annotated by (?,?,?). I have been trying to calculate these values for a few days now but to no avail. Any help would be appreciated.

Also, some nice sources providing information on the topic can be found here and here.

EDIT:

Another image I whipped up shows a single slice through the y axis looking down on the x axis. It shows the same information as the image above, but it also shows my issue: I can't calculate the proper z axis values for each of the bounding points of the far plane. Keep in mind, the same cut could be made through the x axis to show the same process but with the angle at which the player is looking up or down.

I think the general problem you're looking to solve is how to rotate an object in 3d. From what I understand, you know how to get the magnitude of your camera's vectors, but not their orientation. You have angular rotations defined about the x,y and z axes that you want to apply to your camera's [up],[side] and [view/lookAt] vectors. The above picture illustrates what I mean by up, side and lookAt vectors. They're relevant to your frustum as shown in the below pic. Here is some rough code in C++ that'll rotate a point given an axis and an angle:

``````    Vec3 RotatedBy(Vec3 const &axisVec, double angleDegCCW)
{
if(!angleDegCCW)
{   return Vec3(this->x,this->y,this->z);   }

Vec3 rotatedVec;
double angleRad = angleDegCCW*3.141592653589/180.0;
rotatedVec = this->ScaledBy(cos(angleRad)) +
(axisVec.Cross(*this)).ScaledBy(sin(angleRad)) +
axisVec.ScaledBy(axisVec.Dot(*this)).ScaledBy(1-cos(angleRad));

return rotatedVec;
}
``````

Once you have the rotated up, view and side vectors you can find your far plane's corners.

Compute the center points of the near and far planes:

``````    vec3 nearCenter = camPos - camForward * nearDistance;
vec3 farCenter = camPos - camForward * farDistance;
``````

Compute the widths and heights of the near and far planes:

``````    real nearHeight = 2 * tan(fovRadians/ 2) * nearDistance;
real farHeight = 2 * tan(fovRadians / 2) * farDistance;
real nearWidth = nearHeight * viewRatio;
real farWidth = farHeight * viewRatio;
``````

Compute the corner points from the near and far planes:

``````    vec3 farTopLeft = farCenter + camUp * (farHeight*0.5) - camRight * (farWidth*0.5);
vec3 farTopRight = farCenter + camUp * (farHeight*0.5) + camRight * (farWidth*0.5);
vec3 farBottomLeft = farCenter - camUp * (farHeight*0.5) - camRight * (farWidth*0.5);
vec3 farBottomRight = farCenter - camUp * (farHeight*0.5) + camRight * (farWidth*0.5);

vec3 nearTopLeft = nearCenter + camY * (nearHeight*0.5) - camX * (nearWidth*0.5);
vec3 nearTopRight = nearCenter + camY * (nearHeight*0.5) + camX * (nearWidth*0.5);
vec3 nearBottomLeft = nearCenter - camY * (nearHeight*0.5) - camX * (nearWidth*0.5);
vec3 nearBottomRight = nearCenter - camY * (nearHeight*0.5) + camX * (nearWidth*0.5);
``````

Compute each plane from any three corners of the plane, wound CW or CCW to point inward (depending on coordinate system).

``````    vec3 p0, p1, p2;

p0 = nearBottomLeft; p1 = farBottomLeft; p2 = farTopLeft;
vec3 leftPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 leftPlaneOffset = Dot(leftPlaneNormal, p0);

p0 = nearTopLeft; p1 = farTopLeft; p2 = farTopRight;
vec3 topPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 topPlaneNormal = Dot(topPlaneNormal , p0);

p0 = nearTopRight; p1 = farTopRight; p2 = farBottomRight;
vec3 rightPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 rightPlaneNormal = Dot(rightPlaneNormal , p0);

p0 = nearBottomRight; p1 = farBottomRight; p2 = farBottomLeft;
vec3 bottomPlaneNormal = Normalize(Cross(p1-p0, p2-p1));
vec3 bottomPlaneNormal = Dot(bottomPlaneNormal , p0);
``````