3d 计算三维空间中的视锥体

3d 计算三维空间中的视锥体,3d,geometry,trigonometry,lwjgl,frustum,3d,Geometry,Trigonometry,Lwjgl,Frustum,我画了一张又一张的图,说明了如何计算三维空间中的边界点。首先,我有两组数据,每个数据包含三个值:相机的xyz坐标和围绕x、y和z轴的旋转。给定一定的视距,应该可以计算6个平面中每个平面的边界点。我一直在使用这些方程来计算远平面的宽度和高度: hfar = 2 * tan(45/2) * view_distance wfar = hfar * ratio hfar是远平面的高度,wfar是宽度,比率是视口宽度除以高度的比率。我一直在使用下面的图表来尝试解决这个问题: 我需要找到用(?,,?)注

我画了一张又一张的图,说明了如何计算三维空间中的边界点。首先,我有两组数据,每个数据包含三个值:相机的xyz坐标和围绕x、y和z轴的旋转。给定一定的视距,应该可以计算6个平面中每个平面的边界点。我一直在使用这些方程来计算远平面的宽度和高度:

hfar = 2 * tan(45/2) * view_distance
wfar = hfar * ratio
hfar是远平面的高度,wfar是宽度,比率是视口宽度除以高度的比率。我一直在使用下面的图表来尝试解决这个问题:

我需要找到用(?,,?)注释的点。我已经试着计算这些数值好几天了,但是没有用。任何帮助都将不胜感激

此外,还可以找到一些很好的资料来源,提供有关该主题的信息

编辑: 我弹出的另一张图像显示了一个穿过y轴的切片,它向下看x轴。它显示了与上图相同的信息,但也显示了我的问题:我无法为远平面的每个边界点计算正确的z轴值


请记住,可以在x轴上进行相同的切割,以显示相同的过程,但与播放器上下观看的角度相同。

我认为您要解决的一般问题是如何在3d中旋转对象。据我所知,你知道如何获得相机矢量的大小,但不知道它们的方向。您已经定义了围绕x、y和z轴的角度旋转,您希望将这些旋转应用于相机的[up]、[side]和[view/lookAt]向量

上图说明了我所说的向上、侧向和注视向量的含义。如下图所示,它们与您的平截头体相关

这里有一些C++中的粗代码,它会旋转给定轴和角度的点:

    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;
    }

将视图和侧向量向上旋转后,可以找到远平面的角点

计算近平面和远平面的中心点:

    vec3 nearCenter = camPos - camForward * nearDistance;
    vec3 farCenter = camPos - camForward * farDistance;
    real nearHeight = 2 * tan(fovRadians/ 2) * nearDistance;
    real farHeight = 2 * tan(fovRadians / 2) * farDistance;
    real nearWidth = nearHeight * viewRatio;
    real farWidth = farHeight * viewRatio;
    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);
计算近平面和远平面的宽度和高度:

    vec3 nearCenter = camPos - camForward * nearDistance;
    vec3 farCenter = camPos - camForward * farDistance;
    real nearHeight = 2 * tan(fovRadians/ 2) * nearDistance;
    real farHeight = 2 * tan(fovRadians / 2) * farDistance;
    real nearWidth = nearHeight * viewRatio;
    real farWidth = farHeight * viewRatio;
    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);
从近平面和远平面计算角点:

    vec3 nearCenter = camPos - camForward * nearDistance;
    vec3 farCenter = camPos - camForward * farDistance;
    real nearHeight = 2 * tan(fovRadians/ 2) * nearDistance;
    real farHeight = 2 * tan(fovRadians / 2) * farDistance;
    real nearWidth = nearHeight * viewRatio;
    real farWidth = farHeight * viewRatio;
    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);
从平面的任意三个角计算每个平面,沿顺时针或逆时针方向缠绕以指向内部(取决于坐标系)


您可以使用trig来解决这个问题。我在你的帖子中没有看到的一条信息是垂直视野。你需要这个角度来找出这些点。设A为(x,y,z),B为远平面的中心点,C为远平面上边缘的中点。这三个点形成一个三角形,最靠近a的角度为垂直视野的一半。可以使用tan()计算半高。水平视场可以由你的比率决定。。。然后你也可以算出你的一半宽度。考虑到我的视场是45度,我会取其中的一半,取它的切线,然后乘以视距。这是针对x轴和y轴完成的。我明白,但这个过程对z轴不起作用。哇,我怎么会错过你的公式?一旦有了f_height/2和f_width/2的大小,它们对应的方向就来自于相机的方向向量[让我们把它们调起来,从侧面和正面]。这就是你找不到的吗?没错!我的整个问题在于能够通过指向边界球体上任意点的空间旋转整个图形。但如果你能解释一下,我会是一个非常高兴的程序员:通过轴角度旋转,你可以使用类似()的东西将旋转应用到初始的向上、侧面和正面向量。例如,“向上”向量最初为[0,1,0]。对该点应用绕轴旋转将得到新的上方向向量。你对你的初始侧向量和前向量做同样的事情。。。然后你可以使用你描述的初始方法得到你要寻找的点,在代码中,const是包含点坐标的原始向量。axisVec会是什么?我假设它是另一个向量。不过解释得很好。我必须说,它确实清楚了一点:D。谢谢“const”是C++中的限定符,它只是表示“AxISVEC”不会在函数中被修改的方式。这两个输入是(axisVec和angleDegCCW)。我对lwjgl不是很熟悉,但如果您使用Java,可能有一些库具有用于3d游戏编程的强大功能。当然,lwjgl!我喜欢在没有其他图书馆帮助的情况下尝试弄清楚这些事情(因此我会问)。虽然我不能说我非常理解C++。我对它有大致了解。我想我只需要算出这个向量数学,我会很好的。谢谢你的时间和回答!camForward代表什么?我肯定camPos是坐标系中的位置,但camForward对我来说不清楚。我想这意味着摄像机的观察方向。()有点晚了,但中心的前两个公式不应该用+号而不是-?如果我们从凸轮位置减去凸轮向前,这不会使相机后面的近平面与观察方向相反吗?@Martin Spasov我相信这是因为答案假设-z轴进入屏幕。