CNA-BUG-069: Ray::Intersects(BoundingSphere) returns no hit for a ray that starts exactly on the sphere and points outward

CNA snapshot 3b43bd86  ·  Known Issues › Current bugs  ·  source links pinned to 3b43bd86

✓

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

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.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.

Known issues
Bug index