CNA-BUG-069: Ray::Intersects(BoundingSphere) returns no hit for a ray that starts exactly on the sphere and points outward
Evidence basis: source-verified at the pinned commit; executed for this entry (the Evidence section names exactly what was run); tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 3b43bd86; unless a sentence says otherwise, nothing here was built or executed. Nothing on this page was executed unless the Evidence section says so.
The sphere overload returns 0 only when the origin is strictly inside, so a ray starting on the surface and pointing outward gets no hit, where XNA's inside test is <= and returns 0. The box overload now matches XNA.
- Identifier
CNA-BUG-069- Category
- Bug
- Subsystem
- Math & geometry
- Status
- Narrowed (partially fixed; describes only what survives)
- Verified against
- CNA
3b43bd86(3b43bd8687ed46523d873f9bec4b32bd8481dcb5) - Severity
- Low (a triage suggestion, not a project priority)
- Evidence basis
- Reproduced: executed for this entry (the Evidence section names exactly what was run)
- Tests touching this area
- Yes: see Current tests
- Affected contract
- Microsoft::Xna::Framework::Ray::Intersects(BoundingSphere) (and the out-parameter overload)
Expected behaviour
XNA 4.0 (IL of Ray.Intersects(ref BoundingSphere, out float?)) returns 0 when the squared centre distance is <= the squared radius.
Actual behaviour at TARGET
The sphere overload in Ray.cpp returns 0 only for differenceLengthSquared < sphereRadiusSquared; on the surface it falls through, and an outward direction gives a negative dot product and no hit.
Source locations
modules/math/src/Ray.cpp— Ray::Intersects(const BoundingSphere&, std::optional<float>&): strict inside test; the box overload (the fixed half)modules/math/tests/Microsoft/Xna/Framework/RayTests.cpp— existing ray testsmodules/math/tests/Microsoft/Xna/Framework/GeometryValuesCompatibilityTests.cpp— the box boundary cases added by e1377c437
Evidence
Checked by reading the named source at 3b43bd86; the audit's own executed comparison follows below. XNA behaviour from the genuine XNA 4.0 IL (comparison opcodes).
Independent re-verification: Reproduced by the audit at 009d40f5. That commit's math sources were compiled with g++ -O0 and compared with float32 models of the decompiled XNA 4.0 IL: a ray starting on a unit sphere and pointing outward returned nullopt (XNA 0). On 2,000,000 random rays hit and miss outcomes never disagreed, but about 1% of sphere results differed, by up to 0.2% for near-tangent rays, because the operations are ordered differently. The sharp-runtime types came from a sibling checkout that TARGET does not pin.
Narrowed at c6dec91f: e1377c437 (CNA-DEMOS-ISSUE-130) replaced the box slab test: Ray::Intersects(BoundingBox) now clips a non-negative interval starting at 0 with XNA's |d| < 1e-6 parallel threshold, so a stationary ray inside a box returns 0 and a 5e-7 component counts as parallel (GeometryValuesCompatibilityTest.StationaryRayHitsEveryContainedBoxBoundary and RayBoxUsesNonnegativeIntervalAndXnaParallelThreshold). The sphere comparison is unchanged.
Focused reproduction
// Illustrative; the audit's executed probe is described under Evidence.\nBoundingSphere s(Vector3::Zero, 1.0f);\nRay out(Vector3(1, 0, 0), Vector3(1, 0, 0));\nauto b = out.Intersects(s); // XNA: 0 CNA: nullopt
Current tests
RayTests.cpp covers ordinary hits and misses and GeometryValuesCompatibilityTests.cpp the box boundary cases; no test starts a ray on a sphere surface.
Regression test
A case for an outward ray starting on a sphere surface, asserting XNA's 0.
Blast radius
Picking and collision code that starts rays on a sphere surface; normal rays are unaffected in hit-or-miss outcome (their distances can differ from XNA's in the last bits).
Workaround
Nudge ray origins off sphere surfaces, or test containment before intersecting.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- Internals
- Math internals: geometry
- Deep dives
- Bounding volumes: containment matrix
- Known issues
- Bug index