Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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_distance
wfar = 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:

enter image description here

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.

enter image description here

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.

like image 679
CoderTheTyler Avatar asked Dec 02 '12 02:12

CoderTheTyler


People also ask

Is a frustum 3D?

In computer graphics, the viewing frustum is the three-dimensional region which is visible on the screen. It is formed by a clipped pyramid; in particular, frustum culling is a method of hidden surface determination.

What is opengl view frustum?

The view frustum is the volume that contains everything that is potentially (there may be occlusions) visible on the screen. This volume is defined according to the camera's settings, and when using a perspective projection takes the shape of a truncated pyramid.

What is camera frustum vertical field of view?

In 3D computer graphics, the view frustum (also called viewing frustum) is the region of space in the modeled world that may appear on the screen; it is the field of view of a perspective virtual camera system.


2 Answers

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);
like image 50
orfdorf Avatar answered Oct 31 '22 03:10

orfdorf


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.

enter image description here

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.

enter image description here

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.

like image 29
Prismatic Avatar answered Oct 31 '22 05:10

Prismatic