How to define the planes for frustum culling..?

Started by
4 comments, last by robertgamble 21 years, 2 months ago
Right, I have a camera: //coordinates camera.x camera.y camera.z //angles camera.xa camera.ya camera.za I want to clip my scenery to a frustum coming from the camera, I know that to do that I need left,right,top,bottom,near and far planes all with normals pointing into the frustum. From there I know what to do. However I just can''t work out how to define/create these planes. All of the tutorials I''ve found assume that you either know how to do this already or that you''re using openGL and can "extract" the planes somehow. Any help would be greatly appreciated. Also can anyone recommend a 3D design package? My engine has a function create_quad(vector1,vector2,vector3,vector4,color), are there any packages that will allow me to design my scenery and then export it as a list of calls to my create_quad function (or just a list of coordinate sets)? Please bare with me, I''m very new to 3D graphics programming
Advertisement
OK, that''s actually not so easy to explain without images, I''ll still try. Note that there are quicker methods to get the planes (most of them involving matrix extraction), but this is the basic, most understandable one.

I don''t know if you are familiar with the mathematical representation of a plane, and its relation to normals and space orientation. If not, I''ll quickly summarize it:

A 3D plane is mathemtically represented by the plane equation: Ax + By + Cz + D = 0. (A,B,C) are the three components of it''s (normalized) normal, D is the displacement offset along the normal. This equation simply states, that any point (x,y,z) that satisfies the equation (result is 0) will lie on that plane.

To cull geometry against a plane, you need the normal, and the D value. You can rewrite the equation in terms more familiar to a graphics programmer: N.x*P.x + N.y*P.y + N.z*P.z + D = 0. So first, you need to get N, the normal. A normal of a plane can be computed from three points that are guaranteed to lie on that plane. Let''s call them P1, P2 and P3. The normal N is now defined as the crossproduct of the differential vectors between P1,P2 and P1,P3:

U = P2-P1
V = P3-P1

N = U CROSS V
N = Normalize(N)

Now you have your normal. Next step is to get the D value. You use the plane equation for that: you have the normal, and you have a point on the plane (choose one of your P1 to P3). So, reorder your equation to have D on the left side, and you get:

D = -( N.x*P1.x + N.y*P1.y + N.z*P1.z )

That''s it.

Now, to build a frustum, you need 6 planes: the four side planes, the near camera and the far camera plane. The first 4 create a pyramidal structure that define the view frustum, and the later 2 define the minimum and maximum view distance. The near plane must always be infront of the camera, otherwise your geometry will flip around.

From the equations above, you''ll need 3 points to create a plane. Consider your view frustum: imagine a pyramid with it''s apex (top) at the camera position (x,y,z) and pointing into the direction (xa,ya,za). Let''s ignore the near and far planes for now. The 4 pyramid faces represent the four planes. The pyramid also has 4 edges, those edges can be represented by vectors and each edge vector is shared by two faces.

You already have your first plane vertex: the camera position. Since it is at the pyramid''s top, it is shared by all planes, thous is a valid point for all four frustum planes. To get the remaining 2 per plane, you''ll first need to calculate the 4 edge vectors. They all originate at the camera position, and go out into infinity along the four pyramid edges.

To obtain their direction, you have to take camera direction into account. But you also need two additional values: the horizontal and vertical FOV (field of view). Those values represent the opening angles of your pyramid planes: the vertical FOV is the angle from the bottom to the top plane (measured at the apex), the horizontal FOV is from the left to the right plane.

With those values, you can now compute the 4 edge vectors (that are actually direction rays) using basic trigonometry. To finally get hold of your plane points, just pick an arbitrary distance, and compute the 3D point along all four edge vectors at that distance. Now each of those four points is shared by two planes. The last step is to use the correct 3 points per plane (the camera position, and the two corresponding points from the edge vectors), and plug them into the plane equation above.

The near and far plane are computed in a little different way. In both cases, their normal is simply the vector formed by your camera rotation (xa,ya,za): Transform this rotation into a normalized vector, and you have your near-plane normal. Flip it, and you have the far plane.

/ Yann
Thanks Yann!

To start off with I''m clipping against a plane straight infront of my camera (near plane?):
var angle1=camera.ya-90;if(angle1<0)angle1+=360;var angle2=camera.ya+90;if(angle2>360)angle2-=360;	tri.points[2]=new vector3D(camera.x+sin[angle1],camera.y,camera.z-cos[angle1]);tri.points[1]=new vector3D(camera.x,camera.y,camera.z);tri.points[0]=new vector3D(camera.x+sin[angle2],camera.y,camera.z-cos[angle2]);this.normal=calculate_normal(tri); 


Which should generate a normal pointing in the same direction as my camera. But for some reason it''s pointing downwards a bit, have I got some numbers mixed around?

Thanks again
normalize(new vector3D(camera.xa,camera.ya,camera.za));

Doesn''t work for the near plane
No, that will not work. Your 3 direction values are angles, not vector components.

But it''s a good idea to start with the near plane. To get the normal, you need to create a unit vector in the origin direction of the camera. IE: it must point into the direction (in 3D space) the camera would be looking into, if all three values (xa,ya,za) are zero. The length has no importance here, it will be renormalized later anyway (to compensate for floating point precision problems). Now, you get the normal of the near plane, by rotating this vector by INV(xa,ya,za). That part is important: you basically transform the direction vector into the camera''s new coordinate system. The INV() infront of the angles denote inversion: you need to rotate the plane by the inverse of the angles. This is done to compensate for the two different coordinate frames encountered: your camera and the world around you. Think about it: if your camera turns right, then the world around actually turns left. The rotation is inverted. BTW, when using matrix transforms, then this is typically done by transposing the matrix.

Once you have your new inversly rotated normal, you should renormalize it. It is then ready to be used as normal for the near clipping plane.
Here''s a link to a article on extracting view planes from your world-view-projection matrix - covers both DirectX and OpenGL:

http://www2.ravensoft.com/users/ggribb/plane%20extraction.pdf

JustinH

This topic is closed to new replies.

Advertisement