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)?
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.
精彩评论