CNA-BUG-071: BoundingFrustum::Intersects differs from XNA 4.0: box and sphere overloads use a conservative plane test, and the Plane overload counts an on-plane corner as Intersecting
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
The box and sphere overloads report true for volumes just outside an edge or corner where XNA's exact GJK query reports false, and the Plane overload treats a zero corner distance as Intersecting (XNA: Back).
- Identifier
CNA-BUG-071- Category
- Bug
- Subsystem
- Math & geometry
- Status
- Open
- Verified against
- CNA
009d40f5(009d40f5dd085c4e674d3479675fac84b12b3e0a) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Source-verified: read at TARGET, not executed
- Tests touching this area
- Yes: see Current tests
- Affected contract
- Microsoft::Xna::Framework::BoundingFrustum::Intersects(BoundingBox), Intersects(BoundingSphere), Intersects(Plane); BoundingBox/BoundingSphere::Intersects(BoundingFrustum)
Expected behaviour
XNA 4.0 (IL): BoundingFrustum.Intersects(ref BoundingBox) and Intersects(ref BoundingSphere) run the Gjk helper, an exact convex-intersection query. Intersects(ref Plane) classifies each corner with dot + D > 0 as Front and everything else (including exactly 0) as Back.
Actual behaviour at TARGET
BoundingFrustum.cpp implements the box and sphere overloads as Contains(...) != Disjoint; Contains is a per-plane test that only returns Disjoint when the volume is wholly in front of one plane, so a box diagonally outside a frustum corner (in front of no single plane) is reported as intersecting. BoundingBox::Intersects(BoundingFrustum), BoundingSphere::Intersects(BoundingFrustum) and graphics-ext's FrustumCullerEXT forward to these. The Plane overload uses Plane::IntersectsPoint, which returns Intersecting for a zero distance, so a frustum touching a plane from behind is Intersecting in CNA and Back in XNA.
Source locations
modules/math/src/BoundingFrustum.cpp— BoundingFrustum::Intersects(const BoundingBox&, bool&), Intersects(const BoundingSphere&, bool&), Intersects(const Plane&, PlaneIntersectionType&), Contains(const BoundingBox&, ContainmentType&)modules/math/src/BoundingBox.cpp— BoundingBox::Intersects(BoundingFrustum) forwards to the frustummodules/graphics-ext/src/FrustumCullerEXT.cpp— culling helper forwards to BoundingFrustum::Intersects
Evidence
Checked by reading the named sources at 009d40f5; nothing was built or executed for this entry. XNA behaviour from the genuine XNA 4.0 IL (Gjk references; the Plane overload's comparison). The conservative answer is never a false negative for culling, so visible objects are not dropped.
Focused reproduction
No focused reproduction is known. Nothing has been invented here; the evidence above is what exists.
Current tests
BoundingFrustumTests.cpp covers clearly inside/outside volumes, not corner-adjacent ones or an on-plane corner.
Regression test
A test with a box just outside a frustum corner (outside, but in front of no single plane) expecting false, and a frustum with one corner exactly on a plane expecting Back.
Blast radius
Culling (extra draws, not missing ones), picking and gameplay tests that use frustum intersection as an exact predicate.
Workaround
No workaround is known.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- Math internals: frustum
- Deep dives
- Bounding volumes: frustum
- Known issues
- Bug index