Repository navigation
docs: import selected docs from geom smoke branch #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
d4e9d2c
docs: import selected docs from geom-broad-phase-docs-smoke (echo-vs-…
flyingrobots e3880b7
Merge branch 'main' into echo/docs-bonus-from-geom-smoke
flyingrobots 66198f1
Remove legacy docs
flyingrobots 9e83ffc
Merge remote-tracking branch 'origin/echo/docs-bonus-from-geom-smoke'…
flyingrobots File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| # Echo vs. Unity — Why Echo Is Fundamentally Different | ||
|
|
||
| > TL;DR: Unity is an object‑oriented, imperative frame loop over a mutable GameObject tree. Echo is a deterministic, typed graph‑rewriting engine (RMG) where state changes are explicit rewrite rules applied as atomic transactions along a fixed‑tick timeline. Echo treats time, branching, and merging as first‑class citizens. | ||
|
|
||
| ## One‑Screen Summary | ||
|
|
||
| - Data Model | ||
| - Unity: GameObject hierarchy with Components; behavior lives in scripts. | ||
| - Echo: Recursive Meta Graph (RMG). Everything (entities, components, systems, events, proxies, contacts) is a typed graph node or edge. | ||
| - State Change | ||
| - Unity: imperative mutation in `Update()`/`FixedUpdate()`; side effects are common. | ||
| - Echo: Double‑Pushout deterministic rewrites (DPOi). Rules transform subgraphs under snapshot isolation; no hidden mutation. | ||
| - Scheduling | ||
| - Unity: per‑frame script execution order (configurable, but often non‑deterministic in practice). | ||
| - Echo: deterministic local scheduler orders rewrites by `(rule_id, scope_hash)`; disjoint scopes commute. | ||
| - Time (Chronos/Kairos/Aion) | ||
| - Unity: `Time.deltaTime` and frame/update loops; time travel/branching are external. | ||
| - Echo: fixed Chronos ticks; Kairos branches for “what‑ifs”; Aion tags to rank event significance; sub‑tick TOI for CCD. | ||
| - Persistence | ||
| - Unity: scenes/prefabs + runtime state; save systems are custom. | ||
| - Echo: content‑addressed snapshots; identical inputs ⇒ identical snapshot hashes; easy replay/diff. | ||
| - Networking | ||
| - Unity: sync transforms/commands; engine/stack dependent; determinism optional. | ||
| - Echo: Confluence replication — peers apply the same ordered rewrites and converge by construction. | ||
| - Tooling | ||
| - Unity: Inspector reflects live object state; Profiler/Timeline optional. | ||
| - Echo: Inspector reflects the live graph, rewrite stream, determinism hashes, and collision/CCD events. | ||
| - Determinism & Testing | ||
| - Unity: cross‑platform determinism is hard; physics often divergent by platform. | ||
| - Echo: determinism is a design constraint; math, scheduling, PRNG, and collision policies are deterministic and quantized. | ||
|
|
||
| ## What “Everything Is a Graph” Means | ||
|
|
||
| - Typed Nodes: `Transform`, `Collider`, `TemporalProxy`, `PotentialPair`, `Contact`, `ContactEvent`, `System`, `Tick`, etc. | ||
| - Typed Edges: `has_component(entity→transform)`, `produced_in(x→tick)`, `pair_of(pair→a,b)`, `event_of(evt→contact)`. | ||
| - Rewrites: each frame phase is a set of DPO rules (BuildTemporalProxy, BroadPhasePairing, NarrowPhaseDiscrete/CCD, ContactEvents, GC). Rules are pure functions of host graph scope; they emit a new snapshot. | ||
| - Confluence: identical inputs + rule order ⇒ identical graph. Branch merges work because each branch does deterministic rewrites to the same canonical form. | ||
|
|
||
| ## How “Move an Entity” Differs | ||
|
|
||
| - Unity (conceptual): | ||
| ```csharp | ||
| // MonoBehaviour script | ||
| void Update() { | ||
| transform.position += velocity * Time.deltaTime; | ||
| } | ||
| ``` | ||
| - Echo (conceptual): | ||
| ```rust | ||
| // A rewrite rule with matcher + executor (see rmg-core demo motion rule) | ||
| // LHS: node with Motion payload; RHS: update position deterministically. | ||
| engine.register_rule(motion_rule()); | ||
| let tx = engine.begin(); | ||
| engine.apply(tx, "motion/update", &entity_id)?; // enqueues when LHS matches | ||
| let snap = engine.commit(tx)?; // atomic commit + snapshot hash | ||
| ``` | ||
| Key differences: Echo’s update is a named, scoped rewrite with auditability and a stable hash; the engine controls ordering and applies the rule atomically. | ||
|
|
||
| ## Time as a First‑Class Concept | ||
|
|
||
| - Chronos: fixed‑tick clock; sub‑tick Time‑of‑Impact (TOI) for CCD is quantized to eliminate drift. | ||
| - Kairos: branching points (e.g., alternate inputs or CCD substeps) create speculative timelines; merges are deterministic. | ||
| - Aion: significance decides logging/detail budgets (e.g., bullets get CCD and higher precision; dust particles do not). | ||
|
|
||
| ## Collision/CCD (Why It Fits Graph Rewrites) | ||
|
|
||
| - Broad phase adds `TemporalProxy` and `PotentialPair` nodes; narrow phase adds `Contact` and `Toi` nodes; events add `ContactEvent` nodes. All are created through deterministic rewrite rules with canonical IDs. | ||
| - See: `docs/spec-geom-collision.md` for the rules, IDs, and scheduler mapping. | ||
|
|
||
| ## Persistence & Networking | ||
|
|
||
| - Snapshots are content‑addressed; deterministic rewrites guarantee convergent hashes. | ||
| - Replication: send ordered rewrite packets `{tx_id, rule_id, scope_hash, snapshot_hash}`; peers apply locally; no “state drift by replication schedule”. | ||
|
|
||
| ## Authoring & Extensibility | ||
|
|
||
| - Replace ad‑hoc side effects with explicit rewrite rules. | ||
| - Ports/Adapters isolate non‑deterministic systems (render, input, OS clocks) from the core graph. | ||
| - Tools reason about intent (rules) rather than incidental effects. | ||
|
|
||
| ## When (Not) to Use Echo | ||
|
|
||
| - Use Echo if you need: deterministic multiplayer, time‑travel debugging, massive branching simulations, reproducible simulations, precise merges. | ||
| - Use Unity if you need: integrated editor + full renderer stack today, rich asset pipelines, large plugin ecosystem, rapid prototyping without determinism constraints. | ||
| - Bridge: Echo can power headless sims and feed renderers/tooling via adapters. | ||
|
|
||
| ## Migration Sketch | ||
|
|
||
| - Start by modeling gameplay state as graph nodes/edges. | ||
| - Port side‑effectful logic into rewrite rules with explicit match/replace. | ||
| - Introduce fixed Chronos ticks; route randomness through Echo’s PRNG. | ||
| - Adopt time‑aware collision: fat AABBs, deterministic pairs, quantized TOI. | ||
| - Add Confluence replication; verify identical snapshots across nodes. | ||
|
|
||
| ## Appendix: Concept Mapping | ||
|
|
||
| | Unity Concept | Echo Equivalent | | ||
| | --- | --- | | ||
| | GameObject/Component | Typed nodes in RMG (entity + components as nodes/edges) | | ||
| | Scene | Snapshot (content‑addressed) + graph of assets | | ||
| | Update/FixedUpdate | Deterministic rule scheduler phases | | ||
| | Physics collision callbacks | Contact/ContactEvent nodes via rewrite rules | | ||
| | Prefab | Graph template; rewrite rules to instantiate variants | | ||
| | Undo/Redo | Timeline replay; branch/merge via snapshots | | ||
| | Netcode | Confluence replication of rewrites | | ||
|
|
||
| --- | ||
|
|
||
| See also: | ||
| - `docs/architecture-outline.md` (core principles & loop) | ||
| - `docs/spec-rmg-core.md` (RMG, snapshots, confluence) | ||
| - `docs/spec-geom-collision.md` (time‑aware collision & CCD) | ||
| - `docs/phase1-geom-plan.md` (delivery milestones) | ||
|
|
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # Phase 1 Geometry/Collision Plan (Chronos/Kairos/Aion) | ||
|
|
||
| ## Scope | ||
| - Time‑aware collision pipeline with deterministic broad/narrow phases and CCD. | ||
| - Shapes: AABB, Sphere, Capsule, OBB, Convex Hull (narrow later), Static Mesh BVH. | ||
| - No dynamics/solver in this phase (contacts only); rigid body adapter later. | ||
|
|
||
| ## Milestones | ||
| - M0 — Scaffolding | ||
| - Crate `rmg-geom` with `types/{transform,aabb,sphere,capsule,obb}.rs`. | ||
| - Temporal types (`TickId`, `TimeSpan`, `TemporalTransform`, `TemporalProxy`). | ||
| - Tests: encoding/decoding, basic overlaps, determinism hashes. | ||
| - M1 — Broad Phase v1 | ||
| - Dynamic AABB Tree; deterministic updates and pair emission. | ||
| - Benchmarks vs grid/sap (micro); property tests (pairs invariant). | ||
| - M2 — Narrow Phase v1 | ||
| - Sphere/sphere, sphere/AABB, capsule/capsule, OBB/OBB (SAT). | ||
| - Manifold builder (2–4 pts) with stable ordering. | ||
| - M3 — GJK + EPA | ||
| - Convex/convex intersection and penetration; warm‑start cache. | ||
| - Robust tolerances and fallbacks; golden tests for degenerate configs. | ||
| - M4 — CCD v1 | ||
| - Conservative advancement; swept sphere/capsule; quantized `toi_s`. | ||
| - Policy thresholds; budget accounting. | ||
| - M5 — Static Mesh BVH | ||
| - Offline/online build; dynamic–static queries; determinism tests. | ||
| - M6 — ECS Integration | ||
| - Components (`Transform`, `Velocity`, `Collider`, `CcdPolicy`), systems (`broad`, `narrow`, `events`). | ||
| - Inspector packet with `ContactEvent`s and hashes. | ||
| - M7 — Hardening | ||
| - Fuzz/property tests; perf passes; docs completion; CI gates and coverage. | ||
|
|
||
| ## Determinism & Time Contracts | ||
| - Fixed `dt`; CCD substeps bounded and recorded. | ||
| - Stable sorts/tie‑breakers by ids; centralized tolerances in one module. | ||
| - Quantization for `toi_s` and manifold points to avoid drift. | ||
| - Derived state only; contacts/pairs are recomputed per tick. | ||
|
|
||
| ## Risks & Mitigations | ||
| - Numerical robustness (GJK/EPA/SAT): | ||
| - Use tolerances/quantization; fallback paths; golden tests for degenerate configs. | ||
| - Performance regressions: | ||
| - Bench suites; fat‑AABB sizing tuned; policy‑guided CCD only for fast movers. | ||
| - Determinism under parallelism: | ||
| - Single‑thread by default; island partition + sorted merges for parallel mode. | ||
|
|
||
| ## Test Strategy | ||
| - Unit tests per module; property tests for overlap symmetry/transitivity. | ||
| - Determinism tests: hash(pairs,contacts) stable across runs/platforms. | ||
| - CCD tests: bullets vs thin walls; quantized `toi_s` repeatability. | ||
|
|
||
| ## Deliverables | ||
| - `docs/spec-geom-collision.md` (this spec) + API docs in code. | ||
| - `rmg-geom` crate with 90%+ coverage gate; CI lints identical to core. | ||
| - Inspector hooks and example scene demonstrating CCD and Aion tagging. | ||
|
|
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| # Time‑Aware Geometry, Collision, and CCD (Deterministic v1) | ||
|
|
||
| > Chronos (sequence) drives simulation, Kairos (possibility) enables branching, Aion (significance) informs precision and logging. This spec defines Echo’s deterministic, time‑aware collision pipeline and APIs. | ||
|
|
||
| This module is a graph‑first design: every artifact (proxies, pairs, contacts, | ||
| events, policies) is a typed node/edge within the world’s Recursive Meta Graph | ||
| and created via deterministic rewrite rules. | ||
|
|
||
| ## Goals | ||
| - Deterministic across platforms and runs; branchable and mergeable. | ||
| - Minimal, composable primitives: geometry types, broad/narrow phases, CCD, and contact events. | ||
| - ECS‑friendly API; one concept per file; tests separate from code. | ||
| - Document tolerances and quantization to eliminate drift. | ||
|
|
||
| ## Terminology | ||
| - Chronos: fixed timestep driving the engine (`dt`, `TickId`). | ||
| - Kairos: branching timelines/speculative substeps. | ||
| - Aion: event significance; which effects persist across branches and are surfaced to tools. | ||
|
|
||
| ## Temporal Types | ||
| - `TickId(u64)`: discrete tick index. | ||
| - `TimeSpan { tick: TickId, dt: f32 }`: tick duration. | ||
| - `TemporalTransform { start: Transform, end: Transform }`: pose over a tick. | ||
| - `TemporalProxy { aabb_fat: Aabb, id: ProxyId, layers: u64 }`: broad‑phase proxy fattened to cover motion over `[start,end]`. | ||
| - `ContactId(Hash)`: stable hash of (ProxyId A, ProxyId B, feature ids, branch id). | ||
| - `Toi { s: f32, normal: Vec3, point: Vec3 }`: time‑of‑impact in `[0,1]` with contact info. | ||
|
|
||
| ## Determinism Invariants | ||
| 1. Fixed `dt` in core; substeps only through CCD with capped, recorded iterations. | ||
| 2. Stable sorts everywhere (proxies, pairs, features, events); ties break by ids. | ||
| 3. Tolerances centralized and quantized: overlap epsilon, TOI epsilon, manifold reduction. | ||
| 4. Contacts, pairs, and manifolds are derived state each tick; not authoritative. | ||
| 5. Identical inputs + rules ⇒ identical `Contact` and `ContactEvent` sequences and hashes. | ||
|
|
||
| ## Geometry Types | ||
| - `Transform` (position `Vec3`, rotation `Quat`, scale `Vec3`). | ||
| - Primitive volumes: `Aabb`, `Sphere`, `Capsule`, `Obb`, `Hull` (convex). | ||
| - Static mesh: triangle lists + immutable BVH (for environment colliders). | ||
|
|
||
| ## Broad Phase (Chronos‑aware) | ||
| - Dynamic AABB Tree (default) | ||
| - Update proxies with fat AABBs based on velocity and angular bounds: `pad = v_max*dt + rot_margin` (quantized). | ||
| - Deterministic updates: sorted insert/remove by `ProxyId`. | ||
| - Outputs deterministic `PotentialPair { a, b }[]` sorted by (min_id, max_id). | ||
| - Sweep and Prune (optional) | ||
| - Stable sort by endpoints, then by (id, axis). Scan for overlaps on `[start,end]`. | ||
| - Spatial Hash Grid (optional) | ||
| - Canonical neighbor iteration order; fixed cell hashing. | ||
| - Static BVH for meshes | ||
| - Prebuilt at load; deterministic traversal order and culling stats. | ||
|
|
||
| ## Narrow Phase (Precise) | ||
| - Fast paths: sphere/sphere, sphere/AABB, capsule/capsule, OBB/OBB (SAT). | ||
| - Convex–convex: GJK for intersection/closest, EPA for penetration depth/direction. | ||
| - Manifold builder: clip and reduce to 2–4 points; stable point ordering by feature ids; quantized outputs. | ||
|
|
||
| ## CCD | ||
| - Strategy: Conservative Advancement (CA) for general convex shapes; swept tests for spheres/capsules. | ||
| - Output: `Toi { s, normal, point }` with `s` quantized to bins in `[0,1]`. | ||
| - Policy (deterministic): CCD when any holds: `|v|*dt > size_thresh`, `ang*dt > angle_thresh`, or material requires CCD. | ||
|
|
||
| ## Events (Temporal Bridge) | ||
| - `ContactEvent` kinds: `Begin { toi_s }`, `Persist`, `End`. | ||
| - Emission order per tick: sort by `(toi_s, ContactId)`; include Aion tags (materials/layers). | ||
| - Inspector packets include hashes of pair order and contact manifolds for divergence checks. | ||
|
|
||
| ## ECS Integration (Phase 1 scope) | ||
| - Components | ||
| - `Transform`, `Velocity` (for CCD), `Collider { shape, layer_mask, material, aabb_cache }`. | ||
| - Internal staging: `PotentialPairs`, `Contacts`. | ||
| - Policy: `CcdPolicy { thresholds, quant_bins }`. | ||
| - Systems | ||
| - `broad_phase_system`: builds/updates proxies → emits deterministic `PotentialPairs`. | ||
| - `narrow_phase_system`: consumes pairs → writes `Contacts` with manifolds/TOI. | ||
| - `events_system`: compares last vs current contacts → emits `ContactEvent`s with Aion tagging. | ||
|
|
||
| ## Public Traits (sketch) | ||
| ```rust | ||
| pub trait BroadPhase { | ||
| fn update(&mut self, tick: TickId, proxies: &[TemporalProxy]); | ||
| fn find_pairs(&self, out: &mut Vec<PotentialPair>); | ||
| } | ||
|
|
||
| pub trait NarrowPhase { | ||
| fn collide(&mut self, a: &Collider, ta: &TemporalTransform, | ||
| b: &Collider, tb: &TemporalTransform, | ||
| policy: &CcdPolicy) -> ContactOutcome; | ||
| } | ||
| ``` | ||
|
|
||
| ## Instrumentation | ||
| - Per tick: proxies, pairs, CCD count, average `toi_s`, substeps, temporal budget usage. | ||
| - Hashes: `hash_pairs`, `hash_contacts` for quick determinism checks. | ||
|
|
||
| ## Open Questions | ||
| - Exact quantization bins for `toi_s` (power‑of‑two vs decimal) and impact on merging. | ||
| - Obb/Obb preference: SAT vs GJK (choose based on shape type or heuristics?). | ||
| - Mesh collider scope in v1 (static only vs limited dynamic with compound shapes). | ||
| - Parallelization strategy and island sorting without violating determinism. | ||
| - | ||
|
|
||
| ## Graph Mapping (Everything is a Graph) | ||
|
|
||
| Typed nodes (with indicative fields): | ||
| - `Tick` { id: TickId, dt: f32 } | ||
| - `Transform` { entity: NodeId, pos: Vec3, rot: Quat, scale: Vec3 } | ||
| - `Velocity` { entity: NodeId, lin: Vec3, ang: Vec3 } | ||
| - `Collider` { entity: NodeId, shape: ShapeRef, layer_mask: u64, material: Hash } | ||
| - `TemporalProxy` { id: TemporalProxyId, entity: NodeId, tick: TickId, aabb_fat: Aabb } | ||
| - `PotentialPair` { id: PairId, a: NodeId, b: NodeId, tick: TickId } | ||
| - `Contact` { id: ContactId, pair: PairId, tick: TickId, manifold: Manifold } | ||
| - `Toi` { pair: PairId, tick: TickId, s: Quantized<f32>, normal: Vec3, point: Vec3 } | ||
| - `ContactEvent` { kind: Begin|Persist|End, tick: TickId, pair: PairId, toi_s: Quantized<f32> } | ||
| - `CcdPolicy` { thresholds, quant_bins } | ||
| - `Material`, `Layer` (Aion tagging sources) | ||
|
|
||
| Typed edges (examples): | ||
| - `has_component(entity → Transform|Velocity|Collider)` | ||
| - `produced_in(x → Tick)` for all temporal artifacts | ||
| - `has_proxy(entity → TemporalProxy)` | ||
| - `pair_of(PotentialPair → a,b)` | ||
| - `contact_of(Contact → PotentialPair)` | ||
| - `event_of(ContactEvent → Contact)` | ||
| - `policy_for(CcdPolicy → Layer|Material)` | ||
|
|
||
| Deterministic ID recipes: | ||
| - `PairId = H(min(entityA,entityB) || max(entityA,entityB) || branch_id)` | ||
| - `ContactId = H(PairId || feature_ids || branch_id)` | ||
| - `TemporalProxyId = H(entity_id || tick_id || branch_id)` | ||
|
|
||
| ## Rewrite Rules (DPOi sketches) | ||
|
|
||
| BuildTemporalProxy (pre_update): | ||
| - LHS: `Collider(e)`, `Transform(e)`, optional `Velocity(e)`, `Tick(n)`; no `TemporalProxy(e,n)` | ||
| - K: `Collider(e)`, `Transform(e)`, `Tick(n)` | ||
| - RHS: add `TemporalProxy(e,n)` with fat AABB; `has_proxy(e→proxy)`, `produced_in(proxy→Tick n)` | ||
|
|
||
| BroadPhasePairing (update): | ||
| - LHS: `TemporalProxy(a,n)`, `TemporalProxy(b,n)` with overlapping fat AABBs; no `PotentialPair(a,b,n)` | ||
| - K: both proxies | ||
| - RHS: add `PotentialPair(a,b,n)`; `pair_of(pair→a,b)`, `produced_in(pair→Tick n)` | ||
|
|
||
| NarrowPhaseDiscrete (update): | ||
| - LHS: `PotentialPair(a,b,n)`; discrete test says overlap at end pose; no `Contact(pair,n)` | ||
| - K: pair | ||
| - RHS: add `Contact(pair,n)` with `Manifold`; `contact_of(contact→pair)`, `produced_in(contact→Tick n)` | ||
|
|
||
| NarrowPhaseCCD (update): | ||
| - LHS: `PotentialPair(a,b,n)`; CCD policy says “run CA/swept” | ||
| - K: pair | ||
| - RHS: if intersect at `toi_s<1`: add/update `Toi(pair,n)`, `Contact(pair,n)`; else ensure `Contact` absent | ||
|
|
||
| ContactEvents (post_update): | ||
| - LHS: `Contact(pair,n−1)` and `Contact(pair,n)` (or absence) | ||
| - K: pair | ||
| - RHS: add `ContactEvent(kind, pair, tick=n, toi_s)`; link to `Contact` and `Tick` | ||
|
|
||
| GC Ephemeral (timeline_flush): | ||
| - LHS: `TemporalProxy|PotentialPair|Toi|Contact` older than retention and unreferenced | ||
| - RHS: delete node (deterministic order by id) | ||
|
|
||
| ## Scheduler Phase Mapping | ||
| - `pre_update`: BuildTemporalProxy | ||
| - `update`: BroadPhasePairing → NarrowPhaseDiscrete/CCD (sorted scopes) | ||
| - `post_update`: ContactEvents (sort by `(toi_s, ContactId)`) | ||
| - `timeline_flush`: GC Ephemeral; persist Aion‑worthy events/metrics | ||
|
|
||
| ## Diagrams (SVG) | ||
|
|
||
| - BuildTemporalProxy: docs/assets/collision/dpo_build_temporal_proxy.svg | ||
| - BroadPhasePairing: docs/assets/collision/dpo_broad_phase_pairing.svg | ||
| - NarrowPhaseDiscrete: docs/assets/collision/dpo_narrow_phase_discrete.svg | ||
| - NarrowPhaseCCD: docs/assets/collision/dpo_narrow_phase_ccd.svg | ||
| - ContactEvents: docs/assets/collision/dpo_contact_events.svg | ||
| - GC Ephemeral: docs/assets/collision/dpo_gc_ephemeral.svg | ||
| - Phase Mapping: docs/assets/collision/scheduler_phase_mapping.svg | ||
|
|
||
| These SVGs carry semantic classes (node, edge, interfaceK, added, removed, scope) and optional animation hooks (pulse-add/pulse-remove). You can style/animate them via CSS using docs/assets/collision/diagrams.css. | ||
| - See the visual tour for step‑by‑step DPO rules and world views: [`collision-dpo-tour.html`](./collision-dpo-tour.html). | ||
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add blank lines around fenced code block.
Markdown linting requires blank lines before and after fenced code blocks (MD031). Add blank lines before line 77 and after line 89.
pub trait NarrowPhase { + ```rust pub trait BroadPhase { fn update(&mut self, tick: TickId, proxies: &[TemporalProxy]); fn find_pairs(&self, out: &mut Vec<PotentialPair>); } pub trait NarrowPhase { fn collide(&mut self, a: &Collider, ta: &TemporalTransform, b: &Collider, tb: &TemporalTransform, policy: &CcdPolicy) -> ContactOutcome; } +``` +🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
77-77: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
78-78: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
🤖 Prompt for AI Agents