我正试图在我的OpenGL 2D游戏中实现视锥体剔除。此时我游戏中唯一的几何对象是矩形,所以我认为这很容易,但我得到了意想不到的结果。我设置了一个对称的透视投影,视场角为45度,近和远的平面分别为0.01和50。眼睛矢量始终与z轴平行,摄像机只能沿x轴和y轴移动。
我的想法是在我试图剔除的矩形的z坐标处获取当前对相机可见的世界空间的矩形区域。因为相机正在观察平截头体的中心,所以我计算到这个可见矩形区域边缘的距离如下:
GLfloat maxDistance = givenRectangle.z * tanf(0.5 * (fovAngle * M_PI/180) );
然后我在摄像机的x和y坐标上添加和减去此距离以获得最大和最小可见x和y,然后测试给定的矩形以查看它是否在这些值之间。
我的问题是我是否在这里正确的轨道,以及当我有一个z = 5的物体时,为什么上面的公式会返回一个荒谬的小值(某些东西* 10 ^ -37),这应该清楚地显示在相机在(0,0,0)?
答案 0 :(得分:3)
从顶部解决问题,我检查了你的公式 - 见草图确认我已经理解你了。
鉴于我们知道A和Z而想要解决X,我首先写道:
tan(A)= X / Z
重新排列,我明白了:X = Z tan(A)
由于Z = 5且A = 22.5度......
X = 5 * tan(22.5度)
X = 2.07106781
所以,看起来好像你的数学是正确的,但你的代码错了 - 也许你的tan函数是期望度而不是弧度,或者 fovAngle 还没有设置?我认为您需要调试并手动检查每个值。
回到更广泛的问题,找出你的截头体内有什么和不是什么,你可能会发现你可以使用不同的测试来更优雅地回答同一个问题。许多图形编码器使用“平面侧”测试。考虑到您的视锥体是由一组6个平面限定的空间体积(视口两侧为4个,近剪裁平面和远剪裁平面)。
给定平面上的点和平面的法线,您可以非常容易地计算平面的方程,而方程makes it trivial to test whether a given point is "inside" (in the direction of the normal) a given plane。迭代所有6个平面,您将快速统治您观看音量的特定点。
这个测试的真正优点在于你可以轻松地重复使用它:你碰巧想要进行测试的任何简单凸多边形(例如矩形)可以被描述为一组平面,允许你重新使用它 - 使用你的“内部或外部”测试。很一般。