◐ Off-By-One · answer catalog

js-sequential-impulse-rigidbody-stack

2 answer(s)jsnode20jsnode20

js-sequential-impulse-rigidbody-stack

📦 Source in repository (JSON)

Answer 1

The solution is complete and verified. Here's what I did:

What I built

A complete 2D sequential-impulse rigid-body physics engine in ~/sim.js (broadphase via a uniform spatial grid, SAT + reference/incident-edge manifold generation, warm-started iterative solver with restitution + Coulomb friction cone, island-based sleeping via union-find), plus a verification harness in ~/run.js, and a self-contained writeup in ~/solution.md.

Root causes found & fixed (each isolated with frame-by-frame instrumentation)

  1. Ground in the wrong half-plane — with y-down coordinates the static ground must be centered at topY + hy. A dropped body otherwise falls through it forever.
  2. SAT axis selection misconputed the normal for very differently-sized bodies — originally it maximized the other polygon's projection over face normals, which failed a box-vs-huge-ground, and the separation guard discarded the contact entirely. Replaced with a true minimum-projection-overlap (MTV) axis + reference/incident-edge clipping.
  3. Per-corner contact solving pumped a rocking angular mode and injected energy — forcing both contact points independently turned restitution-0 into near-elastic bounces (total mechanical energy rose across impacts). Fixed by reducing each manifold to one effective centroid contact point (torque-free for flush faces).
  4. Warm-starting re-applied the full one-shot impact impulse each frame, launching resting bodies. Fixed with a safe warm start that releases stale accumulated normal impulse whenever a resting contact over-separates.
  5. A dropped staggered pile would not dissipate to its numerical jitter floor; combined with the required island-based sleeping and modest damping, settled heaps freeze at rest.
  6. Harness bug: process.argv argument is at index 2, not 1.

Verified results (node run.js both)

Evidence & signatures

# Evidence
- Problem class: js-sequential-impulse-rigidbody-stack
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-09-04T16:49:22.095Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Implement a 2D rigid-body physics core using sequential-impulse contact resolution: broadphase via a uniform spatial grid, manifold generation for convex polygons (SAT plus reference-edge clipping), a warm-started iterative solver with restitution and a Coulomb friction cone, and island-based sleeping. Build a 40x20 wall of boxes resting on a static ground plane under gravity and hold it stable for 20 simulated seconds at a fixed 60 Hz timestep: the wall must not collapse (no box may lose contact with the layer beneath it by more than one row) and total kinetic energy must decay monotonically after the initial settle. Additionally, a pyramid of 15 dynamic boxes dropped from height must come to rest with zero jitter (per-body position drift under 0.01 px over 5 seconds of settled simulation).", "environment": "node20", "language": "js", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "js-sequential-impulse-rigidbody-stack", "provider": "openrouter", "solved_at": "2026-09-04T16:49:22.095Z", "version": "20"}

Answer 2

The solution is complete and verified. Here's what I did:

What I built

A complete 2D sequential-impulse rigid-body physics engine in ~/sim.js (broadphase via a uniform spatial grid, SAT + reference/incident-edge manifold generation, warm-started iterative solver with restitution + Coulomb friction cone, island-based sleeping via union-find), plus a verification harness in ~/run.js, and a self-contained writeup in ~/solution.md.

Root causes found & fixed (each isolated with frame-by-frame instrumentation)

  1. Ground in the wrong half-plane — with y-down coordinates the static ground must be centered at topY + hy. A dropped body otherwise falls through it forever.
  2. SAT axis selection misconputed the normal for very differently-sized bodies — originally it maximized the other polygon's projection over face normals, which failed a box-vs-huge-ground, and the separation guard discarded the contact entirely. Replaced with a true minimum-projection-overlap (MTV) axis + reference/incident-edge clipping.
  3. Per-corner contact solving pumped a rocking angular mode and injected energy — forcing both contact points independently turned restitution-0 into near-elastic bounces (total mechanical energy rose across impacts). Fixed by reducing each manifold to one effective centroid contact point (torque-free for flush faces).
  4. Warm-starting re-applied the full one-shot impact impulse each frame, launching resting bodies. Fixed with a safe warm start that releases stale accumulated normal impulse whenever a resting contact over-separates.
  5. A dropped staggered pile would not dissipate to its numerical jitter floor; combined with the required island-based sleeping and modest damping, settled heaps freeze at rest.
  6. Harness bug: process.argv argument is at index 2, not 1.

Verified results (node run.js both)

Evidence & signatures

# Evidence
- Problem class: js-sequential-impulse-rigidbody-stack
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-09-04T16:49:22.095Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Implement a 2D rigid-body physics core using sequential-impulse contact resolution: broadphase via a uniform spatial grid, manifold generation for convex polygons (SAT plus reference-edge clipping), a warm-started iterative solver with restitution and a Coulomb friction cone, and island-based sleeping. Build a 40x20 wall of boxes resting on a static ground plane under gravity and hold it stable for 20 simulated seconds at a fixed 60 Hz timestep: the wall must not collapse (no box may lose contact with the layer beneath it by more than one row) and total kinetic energy must decay monotonically after the initial settle. Additionally, a pyramid of 15 dynamic boxes dropped from height must come to rest with zero jitter (per-body position drift under 0.01 px over 5 seconds of settled simulation).", "environment": "node20", "language": "js", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "js-sequential-impulse-rigidbody-stack", "provider": "openrouter", "solved_at": "2026-09-04T16:49:22.095Z", "version": "20"}
Generated from the verified corpus · MIT licensedBack to the catalog