Skip to content

Phase 1 / Forge / Queries: raycast#63

Merged
guysenpai merged 20 commits into
mainfrom
phase-1/forge/queries-raycast
Jul 26, 2026
Merged

Phase 1 / Forge / Queries: raycast#63
guysenpai merged 20 commits into
mainfrom
phase-1/forge/queries-raycast

Conversation

@guysenpai

Copy link
Copy Markdown
Contributor

Tenth M1.1 sub-milestone. Everything before it moves bodies; this one interrogates them.
Only the raycast is implemented; the complete query family's signatures freeze here, because
a comptime strategy interface cannot gain a method after its M1.1.15 freeze without breaking
every Tier 3 solver.

What lands

  • foundation/math/aabb.zigAabb(T).rayInterval: the slab test returning the
    parametric interval. A direction component that is exactly zero leaves the product and is
    replaced by origin-in-slab containment — TRUE ZERO, no epsilon, deliberately unlike the
    reference's absolute 1.0e-20f guard. Plus an exact NaN -> 0 repair for the one
    0 * inf the mask cannot cover (a subnormal component with the origin on a face plane:
    the numerator is exactly zero, so the repair is the exact quotient, not a tolerance), and
    a domain assertion that makes that exactness a precondition instead of a hope.
  • pipeline/broadphase.zigBvh(T).queryRay + Broadphase(T).queryRay, branch and
    bound on the existing traversal. The collector contract gains maxDistance(), re-read
    before every descent, and shouldStop(), read before every descent, between the four
    layer trees and before each root. The two are not interchangeable: a zero bound still
    admits every node whose interval contains the origin and says nothing about trees not yet
    walked, so "terminates at the first candidate" needed the second. Descent is near-first.
  • pipeline/narrowphase/raycast.zig (new) — analytic ray-core kernels in the core +
    inflation-radius convention. A rounded box fails loud, rejected before the membership test
    since a shape rejection cannot depend on where the ray starts. Both quadratics are written
    cancellation-free: at f32, a radius-1 sphere 5 000 m away used to return a distance short
    by exactly the radius with a normal of length ZERO.
  • forge_3d/query.zig (new) — stateless Real-bound orchestration taking
    (bp, bm, store): the shared filter, the three collectors, the exact tie-break on the
    smaller BodyId, and a normalisation that survives both ends of the float range.
  • api/types.zig — the seven public query types, a verbatim mirror of
    engine-tier-interfaces.md §1, plus collision_layer_count and a typed
    error.InvalidCollisionLayer in addBody. The five deferred entries keep their frozen
    signatures and @panic: they carry no error channel, so a null or a 0 would be a
    silent lie in the caller's own vocabulary.

Two corrections outside the milestone's own scope

  • Body.rotation is now unit at the solver precision, permanently. An f32-unit
    quaternion widened to f64 is off by 3.4e-8; the invariant held by accident for a dynamic
    body from its first tick and never for a static or kinematic one, scaling a static
    collider's frame by 1 ± 3.4e-8 — 0.34 mm at 10 km, the regime -Dphysics_f64 exists
    for. Pre-existing, exposed by the raycast's unit-direction assertion, corrected here. The
    eleven inherited M1.1.5-M1.1.8 envelope quantities were re-measured against main through
    a worktree at both precisions: zero movement, digit for digit.
  • tests/ipc/crash_recovery.zig asserts behaviour, not latency. Four wall-clock
    assertions measured kernel scheduling on a machine the suite loads itself; one of them
    refused a push. They are gone, every behaviour assertion stays, and the measured figures
    live in validation/s6-go-nogo.md.

Verification

  • 257/257 forge_3d tests at f32 AND -Dphysics_f64=true, debug AND ReleaseSafe.
  • zig build, zig build test (debug + ReleaseSafe), zig fmt --check, zig build lint:
    all clean.
  • Bench REPORTED, not gated (ReleaseFast, 10 000 static bodies, 10 000 rays): closest
    845 ns/ray, any 558, all-32 1 458, closest with a 5 m bound 392. No envelope is
    pre-registered — this is the first measurement of the path.
  • Language audit: git diff main over 4 781 lines, zero French accented characters and
    zero French function words in added lines, same over the brief. Three quotations were found
    and rewritten in English rather than excused.

Open for review

The CLAUDE.md §3.4 patch content was never received in-session; the applied patch is
derived from the milestone and submitted as a draft — see the brief's Closing notes, which
names it as the one place to overwrite wholesale.

@guysenpai
guysenpai merged commit dd7fa1f into main Jul 26, 2026
10 checks passed
@guysenpai
guysenpai deleted the phase-1/forge/queries-raycast branch July 26, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant