- 
                Notifications
    You must be signed in to change notification settings 
- Fork 1
merge-train(geom-1): rmg-geom foundation + broad-phase AABB tree #14
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 6 commits
      Commits
    
    
            Show all changes
          
          
            5 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      9d09359
              
                merge-train(geom): merge echo/split-geom-foundation
              
              
                flyingrobots d7ec4ca
              
                merge-train(geom): merge echo/split-broadphase
              
              
                flyingrobots 87d9f53
              
                docs: log PR #14 (geom merge train) in execution plan and decision log
              
              
                flyingrobots d649e9f
              
                merge(train-geom-1): resolve docs + hook conflicts with origin/main
              
              
                flyingrobots 1c052bc
              
                geom(timespan): make fat_aabb conservative for rotations by unioning …
              
              
                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
    
  
  
    
              
  
    
      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,15 @@ | ||
| [package] | ||
| name = "rmg-geom" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
| description = "Echo geometry primitives: AABB, transforms, temporal proxies, and broad-phase scaffolding" | ||
| license = "Apache-2.0" | ||
| repository = "https://example.invalid/echo" | ||
| readme = "../../README.md" | ||
| keywords = ["echo", "geometry", "aabb", "broad-phase"] | ||
| categories = ["game-engines", "data-structures"] | ||
|  | ||
| [dependencies] | ||
| rmg-core = { path = "../rmg-core" } | ||
|  | ||
| #[dev-dependencies] | 
  
    
      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,81 @@ | ||
| use crate::types::aabb::Aabb; | ||
| use core::cmp::Ordering; | ||
| use std::collections::BTreeMap; | ||
|  | ||
| /// Broad-phase interface for inserting proxies and querying overlapping pairs. | ||
| /// | ||
| /// Implementations must return pairs deterministically: the pair `(a, b)` is | ||
| /// canonicalized such that `a < b`, and the full list is sorted ascending by | ||
| /// `(a, b)`. | ||
| pub trait BroadPhase { | ||
| /// Inserts or updates the proxy with the given `id` and `aabb`. | ||
| fn upsert(&mut self, id: usize, aabb: Aabb); | ||
| /// Removes a proxy if present. | ||
| fn remove(&mut self, id: usize); | ||
| /// Returns a canonical, deterministically-ordered list of overlapping pairs. | ||
| fn pairs(&self) -> Vec<(usize, usize)>; | ||
| } | ||
|  | ||
| /// A minimal AABB-based broad-phase using an `O(n^2)` all-pairs sweep. | ||
| /// | ||
| /// Why this exists: | ||
| /// - Serves as a correctness and determinism baseline while API surfaces | ||
| /// stabilize (canonical pair identity and ordering, inclusive face overlap). | ||
| /// - Keeps the algorithm small and easy to reason about for early tests. | ||
| /// | ||
| /// Performance plan (to be replaced): | ||
| /// - Sweep-and-Prune (aka Sort-and-Sweep) with stable endpoint arrays per | ||
| /// axis. Determinism ensured via: | ||
| /// - fixed axis order (e.g., X→Y→Z) or a deterministic axis choice | ||
| /// (variance with ID tie-breakers), | ||
| /// - stable sort and explicit ID tie-breaks, | ||
| /// - final pair list sorted lexicographically by `(min_id, max_id)`. | ||
| /// - Dynamic AABB Tree (BVH): deterministic insert/rotation heuristics with | ||
| /// ID-based tie-breakers; canonical pair set post-sorted by `(min_id,max_id)`. | ||
| /// | ||
| /// Complexity notes: | ||
| /// - Any broad phase degenerates to `O(n^2)` when all proxies overlap (k≈n²). | ||
| /// The goal of SAP/BVH is near-linear behavior when the true overlap count | ||
| /// `k` is small and motion is temporally coherent. | ||
| /// | ||
| /// TODO(geom): replace this reference implementation with a deterministic | ||
| /// Sweep-and-Prune (Phase 1), and optionally a Dynamic AABB Tree. Preserve | ||
| /// canonical pair ordering and inclusive face-touch semantics. | ||
| #[derive(Default)] | ||
| pub struct AabbTree { | ||
| items: BTreeMap<usize, Aabb>, | ||
| } | ||
|  | ||
| impl AabbTree { | ||
| /// Creates an empty tree. | ||
| #[must_use] | ||
| pub fn new() -> Self { Self { items: BTreeMap::new() } } | ||
| } | ||
|  | ||
| impl BroadPhase for AabbTree { | ||
| fn upsert(&mut self, id: usize, aabb: Aabb) { | ||
| self.items.insert(id, aabb); | ||
| } | ||
|  | ||
| fn remove(&mut self, id: usize) { | ||
| self.items.remove(&id); | ||
| } | ||
|  | ||
| fn pairs(&self) -> Vec<(usize, usize)> { | ||
| // BTreeMap iteration is already sorted by key; copy to a vector for indexed loops. | ||
| let items: Vec<(usize, Aabb)> = self.items.iter().map(|(id, aabb)| (*id, *aabb)).collect(); | ||
| let mut out: Vec<(usize, usize)> = Vec::new(); | ||
| for (i, (a_id, a_bb)) in items.iter().enumerate() { | ||
| for (b_id, b_bb) in items.iter().skip(i + 1) { | ||
| if a_bb.overlaps(b_bb) { | ||
| out.push((*a_id, *b_id)); // canonical since a_id < b_id | ||
| } | ||
| } | ||
| } | ||
| out.sort_unstable_by(|x, y| match x.0.cmp(&y.0) { | ||
| Ordering::Equal => x.1.cmp(&y.1), | ||
| o => o, | ||
| }); | ||
| out | ||
| } | ||
| } | 
  
    
      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,13 @@ | ||
| //! Broad-phase interfaces and a minimal reference implementation. | ||
| //! | ||
| //! Determinism contract (applies to all implementations used here): | ||
| //! - Pair identity is canonicalized as `(min_id, max_id)`. | ||
| //! - The emitted pair list is strictly sorted lexicographically by that tuple. | ||
| //! - Overlap is inclusive on faces (touching AABBs are considered overlapping). | ||
| //! | ||
| //! The current `AabbTree` is an `O(n^2)` all-pairs baseline intended only for | ||
| //! early tests. It will be replaced by a deterministic Sweep-and-Prune (and/or | ||
| //! a Dynamic AABB Tree) while preserving the ordering and overlap semantics. | ||
|  | ||
| #[doc = "Reference AABB-based broad-phase and trait definitions."] | ||
| pub mod aabb_tree; | 
  
    
      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,35 @@ | ||
| #![deny( | ||
| warnings, | ||
| clippy::all, | ||
| clippy::pedantic, | ||
| clippy::nursery, | ||
| clippy::cargo, | ||
| rust_2018_idioms, | ||
| missing_docs, | ||
| clippy::unwrap_used, | ||
| clippy::expect_used, | ||
| clippy::panic | ||
| )] | ||
| #![doc = r"Geometry primitives for Echo. | ||
|  | ||
| This crate provides: | ||
| - Axis-aligned bounding boxes (`Aabb`). | ||
| - Rigid transforms (`Transform`). | ||
| - Temporal utilities (`Tick`, `TemporalTransform`, `TemporalProxy`). | ||
| - A minimal broad-phase trait and an AABB-based pairing structure. | ||
|  | ||
| Design notes: | ||
| - Deterministic: no ambient RNG; ordering of pair outputs is canonical. | ||
| - Float32 throughout; operations favor clarity and reproducibility. | ||
| - Rustdoc is treated as part of the contract; public items are documented. | ||
| "] | ||
|  | ||
| /// Foundational geometric types. | ||
| pub mod types; | ||
| /// Time-aware utilities for broad-phase and motion. | ||
| pub mod temporal; | ||
| /// Broad-phase interfaces and a simple AABB-based implementation. | ||
| pub mod broad; | ||
|  | ||
| pub use types::aabb::Aabb; | ||
| pub use types::transform::Transform; | 
  
    
      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,8 @@ | ||
| //! Temporal types and helpers used for tick-based motion and broad-phase. | ||
|  | ||
| #[doc = "Discrete Chronos ticks (u64 newtype)."] | ||
| pub mod tick; | ||
| #[doc = "Start/end transforms over a tick and fat AABB computation."] | ||
| pub mod temporal_transform; | ||
| #[doc = "Broad-phase proxy carrying entity id, tick, and fat AABB."] | ||
| pub mod temporal_proxy; | 
  
    
      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,32 @@ | ||
| use crate::temporal::tick::Tick; | ||
| use crate::types::aabb::Aabb; | ||
|  | ||
| /// Broad-phase proxy summarizing an entity’s motion window for a tick. | ||
| /// | ||
| /// Stores a conservative fat AABB and the owning `entity` identifier (opaque | ||
| /// to the geometry layer). The proxy is suitable for insertion into a broad- | ||
| /// phase accelerator. | ||
| #[derive(Debug, Copy, Clone, PartialEq)] | ||
| pub struct TemporalProxy { | ||
| entity: u64, | ||
| tick: Tick, | ||
| fat: Aabb, | ||
| } | ||
|  | ||
| impl TemporalProxy { | ||
| /// Creates a new proxy for `entity` at `tick` with precomputed `fat` AABB. | ||
| #[must_use] | ||
| pub const fn new(entity: u64, tick: Tick, fat: Aabb) -> Self { Self { entity, tick, fat } } | ||
|  | ||
| /// Opaque entity identifier owning this proxy. | ||
| #[must_use] | ||
| pub const fn entity(&self) -> u64 { self.entity } | ||
|  | ||
| /// Tick associated with the motion window. | ||
| #[must_use] | ||
| pub const fn tick(&self) -> Tick { self.tick } | ||
|  | ||
| /// Conservative fat AABB for this proxy. | ||
| #[must_use] | ||
| pub const fn fat(&self) -> Aabb { self.fat } | ||
| } | 
  
    
      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,44 @@ | ||
| use crate::types::{aabb::Aabb, transform::Transform}; | ||
|  | ||
| /// Transform at two adjacent ticks used to bound motion in the broad-phase. | ||
| /// | ||
| /// - `start` corresponds to tick `n`. | ||
| /// - `end` corresponds to tick `n+1`. | ||
| /// | ||
| /// Determinism and plan: | ||
| /// - `fat_aabb` below currently uses a union of the start/end AABBs. This is | ||
| /// conservative for linear motion and sufficient for pairing/CCD triggers. | ||
| /// - Future: introduce a quantized margin policy (based on velocity, `dt`, and | ||
| /// shape scale) so that fat proxies are identical across peers/branches. The | ||
| /// policy and quantization will be recorded in the graph/spec. | ||
| #[derive(Debug, Copy, Clone, PartialEq)] | ||
| pub struct TemporalTransform { | ||
| start: Transform, | ||
| end: Transform, | ||
| } | ||
|  | ||
| impl TemporalTransform { | ||
| /// Creates a new `TemporalTransform` from start and end transforms. | ||
| #[must_use] | ||
| pub const fn new(start: Transform, end: Transform) -> Self { Self { start, end } } | ||
|  | ||
| /// Returns the start transform. | ||
| #[must_use] | ||
| pub const fn start(&self) -> Transform { self.start } | ||
|  | ||
| /// Returns the end transform. | ||
| #[must_use] | ||
| pub const fn end(&self) -> Transform { self.end } | ||
|  | ||
| /// Computes a conservative fat AABB for a collider with local-space `shape` AABB. | ||
| /// | ||
| /// The fat box is defined as the union of the shape’s AABBs at the start and | ||
| /// end transforms. This is conservative for linear motion and suffices for | ||
| /// broad-phase pairing and CCD triggering. | ||
| #[must_use] | ||
| pub fn fat_aabb(&self, shape: &Aabb) -> Aabb { | ||
| let a0 = shape.transformed(&self.start.to_mat4()); | ||
| let a1 = shape.transformed(&self.end.to_mat4()); | ||
| a0.union(&a1) | ||
|         
                  flyingrobots marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| } | ||
| } | ||
  
    
      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,19 @@ | ||
| /// Discrete simulation tick in Chronos time. | ||
| /// | ||
| /// The engine advances in integer ticks with a fixed `dt` per branch. This | ||
| /// newtype ensures explicit tick passing across APIs. | ||
| #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
| pub struct Tick { | ||
| index: u64, | ||
| } | ||
|  | ||
| impl Tick { | ||
| /// Creates a new tick with the given index. | ||
| #[must_use] | ||
| pub const fn new(index: u64) -> Self { Self { index } } | ||
|  | ||
| /// Returns the tick index. | ||
| #[must_use] | ||
| pub const fn index(&self) -> u64 { self.index } | ||
| } | ||
|  | 
      
      Oops, something went wrong.
        
    
  
      
      Oops, something went wrong.
        
    
  
  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.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.