视锥体剔除矩形问题
我正在尝试在我的 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 处有一个对象时,上面的公式会返回一个荒谬的小值(some*10^-37),该对象应该在 ( 0,0,0)?
I am trying to implement frustum culling in my OpenGL 2d game. The only kind of geometric objects in my game at this point are rectangles, so I thought this would be pretty easy, but I am getting unexpected results. I have setup a symmetrical perspective projection with a field-of-view angle of 45 degrees, and near and far planes at 0.01 and 50 respectively. The eye vector is always parallel to the z-axis, the camera can only move along the x and y axes.
My idea was to get the rectangular area of the world space that is currently visible to the camera at the z-coordinate of the rectangle I am trying to cull. Because the camera is looking at the center of the frustum, I calculate the distance to the edges of this visible rectangular area as follows:
GLfloat maxDistance = givenRectangle.z * tanf(0.5 * (fovAngle * M_PI/180) );
Then I add and substract this distance to and from the x and y coordinates of the camera to get the maximum and minimum visible x and y, and then test the given rectangle to see if it's in between these values.
My question is whether I am on the right track here, and why the above formula returns an absurdly small value (something*10^-37) when I have an object at z=5, which should clearly be visible with the Camera at (0,0,0)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从顶部开始解决问题,我检查了你的公式 - 请参阅草图以确认我正确理解了你。
鉴于我们知道 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 个平面代表视口的侧面,一个近剪裁平面和一个远剪裁平面)。
给定平面上的点和平面的法线,您可以很容易地计算平面的方程,进而 使得测试给定点是否在给定平面“内部”(在法线方向)变得微不足道。迭代所有 6 个平面,您将快速将给定点划入或划出您的查看体积。
这个测试的真正巧妙之处在于您可以轻松地重复使用它:您碰巧想要进行测试的任何简单凸多边形(例如矩形)都可以描述为一组平面,从而允许您重复使用您的“内部或外部”测试。很一般。
Taking the problem from the top, I've checked your formula - see sketch to confirm I've understood you correctly.
Given that we know A and Z and want to solve for X, I first wrote:
tan(A) = X/Z
rearranging, I get:
X = Z tan(A)
Since Z = 5 and A = 22.5 degrees...
X = 5* tan(22.5 degrees)
X = 2.07106781
So, it does seem as though you've got the maths right but your code wrong - maybe your tan function is expecting degrees rather than radians, or fovAngle hasn't been set? I think you need to debug and hand-check each value.
Going back to the wider problem of figuring out what does and does not lie inside your frustum, you might find that you can use a different test to answer the same question more elegantly. Many graphics coders use a "side-of-plane" test. Consider that your viewing frustum is a volume of space bounded by a set of 6 planes (4 for the sides of your viewport, a near clipping plane and a far clipping plane).
Given a point on a plane and a normal for the plane, you can quite easily calculate the equation of a plane, which in turn makes it trivial to test whether a given point is "inside" (in the direction of the normal) a given plane. Iterate through all 6 planes and you'll quickly rule a given point in or out of your viewing volume.
The really neat thing about this test is how easily you can re-use it: any simple convex polygon you happen to want to do tests on (e.g. a rectangle) can be described as a set of planes, allowing you to re-use your "insider or outside" test. Very general.