Checking for bounding box intersections/collisions with a view frustum
I want to check a view frustum against the axis aligned bounding boxes of some objects, to check roughl开发者_StackOverflow社区y whether those objects are in the field of view or not. Speed is not a big deal.
I figured out that building a world-space model of the view frustum and checking for bbox collisions with it was the wrong way to go about this.
A much simpler method is to go the opposite way and convert each vertex of a given bbox to screen-space, and if any vertex of the bbox is within the screen bounds then count that bbox as visible. I get the screen-space position by multiplying against the camera matrix and then accounting for perspective based on the field of view of the camera.Here's the code:
vertexMatrix = matrix([vertex.x,vertex.y,vertex.z,1])
productMatrix = (vertexMatrix * camMatrix)
pVectSS = vector(prodMatrix[0][0],prodMatrix[0][1],prodMatrix[0][2])
pointX = ((pVectSS.x/(-pVectSS.z))/tan(radians(hFOV/2)))/2.0+.5
pointY = ((pVectSS.y/(-pVectSS.z))/tan(radians(vFOV/2)))/2.0+.5
key:
camMatrix = camera inverse world-space matrix
pVectSS = position vector screen-space
hFOV = horizontal field of view
vFOV = vertical field of view
That will work. However, usually one would rather extract the frustum planes and calculate the distances to these. You said "speed is not a big deal", but eventually you may find that it is. After all, one does frustum culling to make things faster.
Multiplying a vertex with a matrix takes the equivalent of 4 dot products, therefore you need the equivalent of 32 dot products to check all 8 corners. Calculating the distance of a point to a plane takes a dot product and an addition, which is somewhat more efficient in the worst case and much more efficient in the average case (since you can often discard an object after clipping after one or two planes, and never more than three). There are a number of optimizations for clip planes that exploit temporary coherence, which I will not go into deeper detail.
Additionally, you can do some coarse culling beforehand by calculating the distance of the center point to a plane and check whether that is greater than the bounding box's radius. This will cull objects that are clearly "in" or "out" very cheaply. Or, alternatively, you could compare the dot product of your view vector to the cosine of your field of view value plus some "padding" (or alternatively, just see if it is positive) as a first ultra-coarse check. As you will remember, the dot product of two vectors tells you how much they point into the same direction. Something that has a negative dot product with your view vector certainly is something you can safely discard, because it's behind you.
精彩评论