A Faster Overlap Test for a Plane and a Bounding
Box
based on Gem 1.7 in Graphics Gems IV (by Ned Greene)
Kenny Hoff
07/08/96
Often in culling or clipping to a view-frustum it is necessary to "classify" a bounding box with respect to a plane as either lying completely on one side or as intersecting the plane. Normally, this involves performing an "inside-outside" test for each of the eight vertices of the box and then many logical operations and comparisons to classify the box based on these test results. Each of these tests requires the evaluation of the plane equation - 3 multiplies and 3 adds times 8 = 24 multiplies and 24 adds. This method use too expensive and too general; we would like to significantly reduce the number of operations for the special case of rectangular bounding boxes (both arbitrarily oriented OBBs and axis-aligned AABBs).
It seems unnecessary to check all of the points with respect to a plane when we really only need to know about the extremal points when projected onto the axis defined by the normal of the plane. This simply involves finding the farthest vertex in the direction of the normal (PosFarPt) and the farthest vertex in the negative direction of the normal (NegFarPt). Rather than actually perform this projection (which is exactly the previously mentioned method when the plane equation is evaluated), for the case of rectangular bounding boxes, we can quickly determine these points.
If the normal of the plane is defined in the box's coordinate system we can simply use the vertex that occupies the same octant as the direction of the normal as the PosFarPt and the "opposite" octant's vertex as the NegFarPt. Now how do we transform the plane normal to the box's coordinate system? If we have the normalized axis vectors of the box, we can simply project the normal onto these axes by performing three dot products to get the components of the normal in box coordinates:
Given box normalized axis vectors and the plane normal: Xaxis, Yaxis,
Zaxis, N
Calculate N' (normal in box coords) as follows:
N' = ( dotprod(N, Xaxis), dotprod(N,Yaxis), dotprod(N,Zaxis) )
This involves the evaluation of three dot products - three multiplies and 2 adds each times 3 = 9 multiplies and 6 adds. This handles the case of arbitrarily oriented bounding boxes, but we can completely get rid of these operations for axis-aligned bounding boxes by observing that N' = N. The plane's normal is defined in the "world" coordinate system and so are the axes of the box, so the transformation is merely the "identity".
Now that we have the plane's normal N (we will now refer to N' as N) in the box's coordinate system, how can we quickly determine the corresponding vertex? We will simply create a cascading set of conditionals using only the signs of the normal components:
if(N.x>0) //RIGHT if(N.y>0) //RIGHT,TOP if(N.z>0) //RIGHT,TOP,FRONT else //RIGHT,TOP,BACK else //RIGHT,BOTTOM if(N.z>0) //RIGHT,BOTTOM,FRONT else //RIGHT,BOTTOM,BACK else //LEFT if(N.y>0) //LEFT,TOP if(N.z>0) //LEFT,TOP,FRONT else //LEFT,TOP,BACK else //LEFT,BOTTOM if(N.z>0) //LEFT,BOTTOM,FRONT else //LEFT,BOTTOM,BACK
This will determine the PosFarPt. Just let N = -N to find the NegFarPt. This routine only requires three comparisons to zero.
We now have PosFarPt and NegFarPt with only 9 multiplies and 6 adds and 3comparisons for each point for a total of 18 multiplies, 12 adds, 6 comparisons, and 3 negations to get the -N. That is in the general orientation case, but with axis-aligned box (AABBs) it only requires 6 comparisons and 3 negations. However, if we find the NegFarPt by taking advantage of the symmetry of the bounding box by simply taking the opposite corner with respect to the PosFarPt, we can reduce this to only 9 multiplies, 6 adds, and 3 comparisons for oriented bounding boxes and only 3 comparisons for axis-aligned boxes. Now that we now these two points, how can we use them to perform a FAST overlap test?
We can start by testing if the box lies completely on one side or the other, if it doesn't then it must intersect the plane. If we perform the plane "inside-outside" test for the NegFarPt and it lies in the half-space in the direction of the normal, then the entire box must be completely "outside". We can then test the PosFarPt, if it lies in the negative half-space (negative direction of normal), the box must be completely "inside". Otherwise it intersects the box. We can summarize as follows:
if (Plane.InOutTest(NegFarPt)==OUTSIDE) // BOX IS "OUTSIDE" else if (Plane.InOutTest(PosFarPt)==INSIDE) // BOX IS "INSIDE" else // BOX INTERSECTS THE PLANE
So, how many operations are required now? We have as a worst case an additional 6 multiplies, 6 adds,and 2 comparisons for the two plane equation evaluations resulting in the following:
Previous method: 24 multiplies, 24 adds, more comparisons than new methods
Arbitrarily oriented (OBB): 24 multiplies, 18 adds, 8 comparisons, and 3 negations
Axis-aligned (AABB): 6 multiplies, 6 adds, 8 comparisons, 3 negations
This method may not prove to be very beneficial for OBBs, but for AABBs (as used in bounding-volume hierarchies or in various spatial-partitioning strategies) it offers a tremendous speedup.