From 3d476186f53d695c340c51dbd3aa14ff4621c520 Mon Sep 17 00:00:00 2001 From: Kai Stevenson Date: Sun, 16 Aug 2026 23:52:34 -0700 Subject: trivial placement --- src/sim/cell/cell.rs | 5 +++++ src/sim/cell_sim/sim.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++-- src/sim/rb_sim/mod.rs | 57 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 94 insertions(+), 22 deletions(-) (limited to 'src/sim') diff --git a/src/sim/cell/cell.rs b/src/sim/cell/cell.rs index d35fa76..2664721 100644 --- a/src/sim/cell/cell.rs +++ b/src/sim/cell/cell.rs @@ -18,6 +18,11 @@ impl Cell { pub fn flip_parity(&mut self) { self.flags ^= Self::FLAG_PARITY; } + #[inline] + pub fn match_parity(&mut self, seqno: u64) { + // TODO this will break with more flags + self.flags = (seqno as u8) & 0b1; + } } impl Cell { diff --git a/src/sim/cell_sim/sim.rs b/src/sim/cell_sim/sim.rs index fd9b6c9..0f02a23 100644 --- a/src/sim/cell_sim/sim.rs +++ b/src/sim/cell_sim/sim.rs @@ -5,10 +5,14 @@ use rand::{Rng, SeedableRng, rngs::SmallRng}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use crate::{ - config::CHUNK_SIZE, + config::{CELLS_IN_CHUNK, CHUNK_SIZE}, sim::{ - cell::{cell::Cell, materials::MaterialDef}, + cell::{ + cell::Cell, + materials::{MaterialDef, MaterialId}, + }, cell_sim::{chunk::Chunk, world::World}, + rb_sim::{RbSimManager, rb_entity::RbEntity}, }, }; @@ -177,6 +181,52 @@ const NEIGHBORHOOD_OFFSETS: [(i32, i32); 9] = [ (1, 1), ]; +pub fn write_rb_entity_to_world( + world: &mut World, + rb_sim_manager: &RbSimManager, + rb_entity_id: u32, + next_seqno: u64, +) { + if let Some(rb_entity) = rb_sim_manager.rb_entities.get(&rb_entity_id) + && let Some((rb_x, rb_y, cos, sin)) = rb_sim_manager.get_rb_entity_transform(rb_entity_id) + { + let half_size = CHUNK_SIZE as f32 / 2.0; + // half-extent of the rotated grid's axis-aligned bounding box, plus a cell of margin + let radius = half_size * (cos.abs() + sin.abs()) + 1.0; + + let world_xl = (rb_x - radius).floor() as i32; + let world_xu = (rb_x + radius).ceil() as i32; + let world_yl = (rb_y - radius).floor() as i32; + let world_yu = (rb_y + radius).ceil() as i32; + + for world_x in world_xl..=world_xu { + for world_y in world_yl..=world_yu { + // same as shader + let d = (world_x as f32 + 0.5 - rb_x, world_y as f32 + 0.5 - rb_y); + let q = (d.0.floor() + 0.5, d.1.floor() + 0.5); + let (lx, ly) = ( + (q.0 * cos + q.1 * sin + half_size).floor() as i32, + (-q.0 * sin + q.1 * cos + half_size).floor() as i32, + ); + + if lx < 0 || ly < 0 || lx >= CHUNK_SIZE || ly >= CHUNK_SIZE { + continue; + } + + let mut cell = rb_entity.get_cell_at_local_position(lx as u8, ly as u8); + if cell.material == MaterialId::Void { + continue; + } + + cell.match_parity(next_seqno); + + // TODO: OPTIMIZE!! + world.set_cell_from_game_position(world_x, world_y, cell, false); + } + } + } +} + pub fn sim_tick(world: &mut World, seqno: u64, use_threading: bool) { puffin::profile_function!(); diff --git a/src/sim/rb_sim/mod.rs b/src/sim/rb_sim/mod.rs index d76a721..10172a1 100644 --- a/src/sim/rb_sim/mod.rs +++ b/src/sim/rb_sim/mod.rs @@ -54,7 +54,7 @@ impl PhysicsManager { pub struct RbSimManager { physics_manager: PhysicsManager, pub rb_entities: FxHashMap, - last_id: u32, + next_id: u32, } impl RbSimManager { @@ -77,6 +77,36 @@ impl RbSimManager { ); } + pub fn create_rb_entity( + &mut self, + cells: Box<[Cell; CELLS_IN_CHUNK]>, + rb_parent: prelude::RigidBodyHandle, + ) { + let id = self.next_id; + self.next_id += 1; + let entity: RbEntity = RbEntity { + id, + cells, + rb_parent, + }; + + self.rb_entities.insert(id, entity); + } + + pub fn destroy_rb_entity(&mut self, entity_id: u32) { + if let Some(entity) = self.rb_entities.get(&entity_id) { + self.physics_manager.rigid_body_set.remove( + entity.rb_parent, + &mut self.physics_manager.island_manager, + &mut self.physics_manager.collider_set, + &mut self.physics_manager.impulse_joint_set, + &mut self.physics_manager.multibody_joint_set, + true, + ); + self.rb_entities.remove(&entity_id); + } + } + pub fn get_rb_entity_transform(&self, entity_id: u32) -> Option<(f32, f32, f32, f32)> { let entity = self.rb_entities.get(&entity_id); match entity { @@ -109,7 +139,7 @@ impl RbSimManager { self.physics_manager.collider_set.insert(collider); } - pub fn test_spawn_box(&mut self, x: f32, y: f32) { + pub fn test_spawn_box(&mut self, x: f32, y: f32, material: MaterialId) { /* Create the bouncing ball. */ let rigid_body = dynamics::RigidBodyBuilder::dynamic() .translation(math::Vector::new( @@ -127,36 +157,23 @@ impl RbSimManager { &mut self.physics_manager.rigid_body_set, ); - let id = self.last_id; - self.last_id += 1; - - let test_cells = Box::new([Cell::void(); CELLS_IN_CHUNK]); - let mut rb_entity = RbEntity { - id, - cells: test_cells, - rb_parent: ball_body_handle, - }; + let mut test_cells = Box::new([Cell::void(); CELLS_IN_CHUNK]); - let mut idx = 0; for x in CHUNK_SIZE / 2 - 5..CHUNK_SIZE / 2 + 5 { for y in CHUNK_SIZE / 2 - 5..CHUNK_SIZE / 2 + 5 { - idx += 1; - rb_entity.set_cell_at_local_position( - x as u8, - y as u8, - Cell::from_material(MaterialId::from_index(1 + idx % 6)), - ); + let cell_idx = x + y * CHUNK_SIZE; + test_cells[cell_idx as usize] = Cell::from_material(material); } } - self.rb_entities.insert(id, rb_entity); + self.create_rb_entity(test_cells, ball_body_handle); } pub fn new() -> Self { RbSimManager { physics_manager: PhysicsManager::new(), rb_entities: FxHashMap::default(), - last_id: 0, + next_id: 0, } } } -- cgit v1.3.1