当前位置: 动力学知识库 > 问答 > 编程问答 >

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_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:

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);
分享给朋友:
您可能感兴趣的文章:
随机阅读: