# Geometric Approach – Extracting the Planes

Prev: View Frustum's Shape | Next: Implementation |

The geometric approach operates in world space and uses the information from the shape of the view frustum to extract the six planes that define the boundaries of the frustum’s volume: near, far, top, bottom, left and right.

The planes are defined such that the normal points towards the inside of the view frustum. Testing if an object is inside the view frustum is performed by computing on which side of the plane the object resides. This can be done computing the signed distance from the point ot the plane. If it is on the side that the normal is pointing, i.e. the signed distance is positive, then it is on the right side of the respective plane. If an object is on the right side of all six planes then the object is inside the frustum.

In this section the computation of the six planes that define the frustum is provided. Testing will be detailed on the next sections.

An approach is to first determine the eight points that define the corners of the view frustum, and then use these points to define the six planes.

The following figure shows the above mentioned points that may be used to compute the six planes.

The notation used to define the points is as follows: the first letter indicates if the point is on the near (n) or far plane (f); the second letter states if the point is at the top (t) or bottom (b); and the third letter indicates left (l) or right (r).

Lets recall the information that was collected in the previous section:

- p – the camera position
- d – a vector with the direction of the camera’s view ray. In here it is assumed that this vector has been normalized
- nearDist – the distance from the camera to the near plane
- Hnear – the “height” of the near plane
- Wnear – the “width” of the near plane
- farDist – the distance from the camera to the far plane
- Hfar – the “height” of the far plane
- Wfar – the “width” of the far plane

A couple more unit vectors are required, namely the *up* vector and the *right* vector. The former is obtained by normalizing the vector (ux,uy,uz) (the components of this vector are the last parameters of the `gluLookAt`

function); the latter is obtained with the cross product between the *up* vector and the *d* vector.

The following figure shows how to obtain the point on the top left side of the far plane, point *ftl*.

To compute *ftl* all is required is vector math:

fc = p + d * farDist ftl = fc + (up * Hfar/2) - (right * Wfar/2)

The remaining points are defined as:

ftr = fc + (up * Hfar/2) + (right * Wfar/2) fbl = fc - (up * Hfar/2) - (right * Wfar/2) fbr = fc - (up * Hfar/2) + (right * Wfar/2) nc = p + d * nearDist ntl = nc + (up * Hnear/2) - (right * Wnear/2) ntr = nc + (up * Hnear/2) + (right * Wnear/2) nbl = nc - (up * Hnear/2) - (right * Wnear/2) nbr = nc - (up * Hnear/2) + (right * Wnear/2)

A plane can be defined with three points. For instance, to define the far plane the following points can be used: ftl, ftr, and fbr. It is advisable to make sure that the normals are oriented consistently, for instance that all are directed towards the interior of the view frustum, see the plane section on the maths tutorial.

An optimization can be performed using this approach to extract the near and far planes. A plane can be defined with a normal and a point, and for those planes these are known based on the camera definition.

The near plane can be defined with *d* as a normal, and *nc* as a point on the plane. As for the far plane the normal is –*d* and the point is *fc*.

The other planes can also be computed in a more efficient manner, namely by using a normal vector and a point to define a plane. The following code provides the normal for the right plane. As for the point, the camera position, *p* is a point in all top, bottom, left and right planes (considering a perspective projection).

nc = p + d * nearDist fc = p + d * farDist a = (nc + right * Wnear / 2) - p a.normalize(); normalRight = up * a

Both *up* and *a* are vectors that belong to the right plane, so their cross product will provide a normal for the plane.

Prev: View Frustum's Shape | Next: Implementation |

### 11 Responses to “Geometric Approach – Extracting the Planes”

### Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Wouldn’t it be faster to get the ftr by simply adding Wfar to ftl, then adding Hfar to ftl to get fbl, and finally you could then add Wfar to fbl to get fbr. It would save a pile of multiplications and divisions. You would only need to compute the ftl initially. Something similar could be done for the near plane as well.

Hi Neil,

You’re absolutely right. The code could be severely optimised. I wrote to be as clear as possible for someone learning, hence the repetitions 🙂

Correct me if I’m wrong, but it is my understanding that the “find the signed distance to the six planes” method will work also for orthographic projections. In orthographic projections the planes do not meet in a point, but checking the signed distance to the six planes should steel work. If one plane returns negative then the object must be culled.

Yes, you’re right. Only the method to compute the planes differs.

Hi

Is it possible to extract what points are with in the coverage area (plane between the near and far planes using frustum culling?

no, resolution matters but only the Width/Hegith ratio. So 640*480 is same as 800*600, but 1200: 736 makes difference (objects near screen side tends to be sheared depending on FOV angle

Thanks for this awesome explanation, i have one question, do the resolution of screen effect on the width size of near clipping plane.

Hi,

No, the frustum is resolution independent.

Thanks for this superb work – works well with my 3d code first time. WELL DONE

How do I compute the planes when only having a FOV and output window dimensions?

you can do it like this: suppose your horizontal field of view is APLHA. and distance to near plane is nd then:

Wnear/2 = tan(ALPHA/2)*nd; // tan – is sin/cos

the same goes for Wfar, just put fd instead of nd.

for height put your vertical FOV should be something like ALPHA/aspect;