Phase 1 / Forge / Forge 3D integration (semi-implicit Euler)#58
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Milestone brief:
briefs/M1.1.5-integration-euler.mdSixth core sub-milestone of the M1.1 rigid arc — the FIRST where bodies move. Adds semi-implicit (symplectic) Euler integration as an internal free-flight pass over the
forge_3dSoA store. No solver/contacts, noPhysicsModulewiring (M1.1.6 / M1.1.15).Closing notes
Delivered.
pipeline/integration.zigintegrate(bm, dt, gravity)— one pure per-tick pass, ascending slot-index order,isAliveIndex-filtered over the non-compacting SoA store, free-flight only (broadphase/narrowphase exist but are never invoked; contact response is M1.1.6). Linear: gravity as an acceleration ×gravity_factor(mass-independent), Jolt clamped-linear damping, position from the new velocity. Angular:α = (R·I_local_inv·Rᵀ)·τ, clamp-dampedω, first-order orientationq ← normalize(q + ½·dt·(ω_quat ⊗ q))with world-space ω on the LEFT; gyroscopic term dropped.Bodygainedforce/torqueaccumulator columns;BodyManagergained the stale-safe velocity getters/setters,addForce/addTorque,addImpulse(addTorque/setAngularVelocityinternal — no public interface change). No EPA/GJK/manifold file touched;PhysicsModulenot instantiated.Threshold discipline (M1.1.4 class). The only guard is the damping clamp
max(0, 1 − d·dt)(physical, not a geometric epsilon). The first-order quaternion path divides by no|ω|and needs no zero guard —ω_quat ⊗ q ⊥ qin 4D, so‖q + dq‖ ≥ 1and the renormalisation is never near-zero.Tests. 112/112 green at f32 AND
-Dphysics_f64=true, Debug AND ReleaseSafe;zig fmt --check,zig build lint,zig buildclean. Discrete semi-implicit free-fall oracle (−4.98675 m / −9.81 m/s, tolerance justified at the site), mass-independence,gravity_factorscaling, damping bend + clamp, force consume-once, impulse, static/kinematic invariance (position + orientation + accumulators-cleared), freed-slot skip observed bit-exact, angular closed form on a rotated anisotropic box, angular damping + clamp, unit-quaternion preservation, ω=0 no-op/no-NaN, left-product lock, and full-integrator determinism (linear + angular, bit-identical).Recorded deviations / decisions. (1) E1 mutator/getter/
isAliveIndextests placed in the existingtests/body_manager_test.zig(BodyManager's established acceptance-test home) — outside the brief's file list, justified. (2) f32 fix: descriptormass/gravity_factorare alwaysf32(caught by the f64 sweep). (3) Codex review P2×2, TEST-ONLY (production untouched): dead-slot skip now observed bit-exact incl. stale-force-not-cleared, and the LEFT quaternion product locked by a non-commutative one-step oracle with a discrimination guard.§3.6.1 audits. Language: production code,
CLAUDE.md, and the brief's LIVING section are French-free (one leaked French spec quote inbody.zig's doc comment was removed). The brief's FROZEN SECTION retains verbatim French spec citations authored by Claude.ai (the demonstrator label, the plan row, the§2 "reset chaque fixed tick"contract) — left untouched per the FROZEN-section rule. Drift: the introduced symbols are referenced consistently acrossintegration.zig/root.zig/body_manager.zig/tests — no orphaned or half-renamed references.Out of scope — confirmed untouched. No solver / Sequential Impulses / friction / restitution / warm-start, no sleeping, no CCD, no substep handling, no kinematic position-from-velocity, no gyroscopic term, no ECS↔BodyManager sync, no
PhysicsModulewiring, no bench, no spec-file edit, no EPA hotfix.Validation
isAliveIndex; E2 linear + gravity + damping + oracle; E3 angular + close)-Dphysics_f64=true(112/112)zig build,zig build test,zig fmt --check,zig build lintgreenCLAUDE.md§3.4 updated (current-state table, +1 Tags row, open-decisions delta, "Last updated") and committed on-branchStatus: CLOSED,Closed: 2026-07-23; finaldocs(brief): close M1.1.5commitMerge and tag (
v0.11.5-integration-euler) are Guy's — not performed here.🤖 Generated with Claude Code