The function BoundingBox.Contains(BoundingFrustum) doesn't work properly. If I have a BoundingFrustum that is outside a BoundingBox, the returned value will be ContainmentType.Intersects.
If I instead call the equivalent (?) function on the BoundingFrustum.Contains(BoundingBox), I get the right result, namely ContainmentType.Disjoint.
https://github.com/MonoGame/MonoGame/blob/6f4e51030120913bc1d5b21b34b07493d2eeebff/MonoGame.Framework/BoundingFrustum.cs#L179
The BoundingFrustum code is more complicated that it need to be.
The construction says that BoundingFrustum is defined as a View * Projection matrix.
Let's look at Contains(Vector3 point)
If you have a vector3 in world coordinates and you tranform it by ViewProj, you get this point in normalized device coordinates (NDC a.k.a. Clip coordinates). You can then check if the point is withing -1 to +1 (-1 to 0 for Z).
Same goes for Planes, Spheres, boxes. Tranform them with ViewProj and then check if it's inside the NDC.
The NDC is virtual a BoundingBox with corners at (-1,-1,-1) and (1,1,0).
You can extract corners and planes the same way. Tranform the corner (1,1,0) from Clip coordinates with inverse ViewProj into world coordinates.
I bet you can simplify the transform by combining values from the matrix Left,Right,Up,Down, Forward. (it's multiplying with 1 and 0 after all).
Most helpful comment
The BoundingFrustum code is more complicated that it need to be.
The construction says that BoundingFrustum is defined as a View * Projection matrix.
Let's look at Contains(Vector3 point)
If you have a vector3 in world coordinates and you tranform it by ViewProj, you get this point in normalized device coordinates (NDC a.k.a. Clip coordinates). You can then check if the point is withing -1 to +1 (-1 to 0 for Z).
Same goes for Planes, Spheres, boxes. Tranform them with ViewProj and then check if it's inside the NDC.
The NDC is virtual a BoundingBox with corners at (-1,-1,-1) and (1,1,0).
You can extract corners and planes the same way. Tranform the corner (1,1,0) from Clip coordinates with inverse ViewProj into world coordinates.
I bet you can simplify the transform by combining values from the matrix Left,Right,Up,Down, Forward. (it's multiplying with 1 and 0 after all).