I want to figure out if 2 3D models overlap on screen. My general idea is:
- Compute the bounding box of each model
- Transform the bounding box to the View Volume using the ViewProjection matrix
- Check if bounding boxes overlap in the view volume, ignoring the Z-axis
For step 1 I've used the answer to this question. But I'm having problems implementing step two.
I wrote the function below but its giving me inconsistent results. The numbers seem good for corners that fall inside the view volume (after multiplying by the ViewProjection matrix). But if an object falls off the screen the numbers seem incorrect. What am I doing wrong?
public static BoundingRectangle ProjectBoundingBox(BoundingBox box, Matrix viewProjection)
{
var minX = float.MaxValue;
var maxX = float.MinValue;
var minY = float.MaxValue;
var maxY = float.MinValue;
var corners = box.GetCorners();
foreach (var corner in corners)
{
var projectedCorner = Vector4.Transform(corner, viewProjection);
projectedCorner /= projectedCorner.W;
minX = Math.Min(minX, projectedCorner.X);
maxX = Math.Max(maxX, projectedCorner.X);
minY = Math.Min(minY, projectedCorner.Y);
maxY = Math.Max(maxY, projectedCorner.Y);
}
return new BoundingRectangle(minX, maxX, minY, maxY);
}
Edit: the numbers
If you see the attached screenshot you see two semi-transparent stained glass windows.
Fully visible window:
Bounding Box: Min( -43.62131 25.6 -10.32131 ), Max( -37.38873 34.4 -4.08873 )
Projected Coordinates: Min(-0.7539723,-0.5401732), Max(-0.2793865, 0.27869606)
Partially visible window:
Bounding Box: Min( -40.5142 25.6 -1.2 ) Max( -40.5 34.4 7.6 )
Projected Coordinates: Min(-32.07214, -23.4672337), Max(47.5241241, 0.334790081)
As you can see the projected coordinates for the only partially visible window are gigantic. I would expect MaxX to be something like -0.9 and MinX maybe -5. But the numbers are way off.
The culprit seems to be some of the corners of the bounding box. For example (-40.5142 34.4 7.6)
is transformed to (47.52412 -12.65482 1.539964)
. What is interesting here is that the W coordinate is negative and less than 1 (-0.18), while for the corners that do seem correct w is positive and larger than 1.0.
Edit #2:
Here's a second picture where I've added a visualization of the projected rectangle. On the left you see the exact scenario where it goes wrong. The right side of the rectangle for the partially visible window is incorrect, while if I slightly wiggle the camera either way you get the result on the right with the correct rectangles around the models.