diff options
| -rw-r--r-- | src/main.rs | 19 | ||||
| -rw-r--r-- | src/sim/rb_sim/mod.rs | 57 |
2 files changed, 55 insertions, 21 deletions
diff --git a/src/main.rs b/src/main.rs index 640e5b9..586b456 100644 --- a/src/main.rs +++ b/src/main.rs @@ -120,10 +120,6 @@ impl App { && let Some(rbsm) = &mut self.rb_sim_manager { self.input.trigger_test_2 = false; - rbsm.test_add_collider_from_chunk( - Vec2::new((cx * CHUNK_SIZE) as f32, (cy * CHUNK_SIZE) as f32), - &world.chunks[*world.chunk_position_to_chunk_idx.get(&(cx, cy)).unwrap()], - ); } // --TEST DRAWING-- @@ -202,7 +198,22 @@ impl App { // may be called multiple times if the physics time is behind // physics_delta_time is statically 1/PHYSICS_FPS fn physics_update(&mut self, physics_delta_time: f32) { + // before we move the rigidbodies, upsert the current terrain state + // TODO use the chunk sleeping, and make this range dynamic if let Some(physics_manager) = &mut self.rb_sim_manager { + if let Some(world) = &self.world { + for cx in -5..5 { + for cy in -5..5 { + if let Some(chunk) = world + .chunk_position_to_chunk_idx + .get(&(cx, cy)) + .map(|&idx| &world.chunks[idx]) + { + physics_manager.upsert_chunk_collider(cx, cy, chunk); + } + } + } + } physics_manager.rb_tick(physics_delta_time); } } diff --git a/src/sim/rb_sim/mod.rs b/src/sim/rb_sim/mod.rs index 0192555..b79de86 100644 --- a/src/sim/rb_sim/mod.rs +++ b/src/sim/rb_sim/mod.rs @@ -5,7 +5,7 @@ use fxhash::FxHashMap; use glam::Vec2; use rapier2d::{ dynamics::{self}, - geometry, + geometry::{self, ColliderHandle}, glamx::vec2, math, prelude, }; @@ -70,8 +70,10 @@ impl PhysicsManager { } pub struct RbSimManager { - physics_manager: PhysicsManager, + chunk_colliders: FxHashMap<(i32, i32), ColliderHandle>, pub rb_entities: FxHashMap<u32, RbEntity>, + + physics_manager: PhysicsManager, next_id: u32, debug_line_buffer: DebugLineBuffer, } @@ -165,25 +167,44 @@ impl RbSimManager { } fn collider_from_chunk(&self, position: Vec2, chunk: &Chunk) -> geometry::Collider { - let mut paths = marching_squares_vertex_trace(chunk, CHUNK_SIZE, CHUNK_SIZE); - let mut path: Vec<Vec2> = paths - // NAIVE, using the second and assuming it's the outer path - .swap_remove(0) - .iter() - .map(|v| v / PIXELS_TO_METRES) - .collect(); - // close the loop - let first = (*path.first().unwrap()).clone(); - path.push(first); + let polys = marching_squares_vertex_trace(chunk, CHUNK_SIZE, CHUNK_SIZE); + let mut vertices = Vec::new(); + let mut indices = Vec::new(); - geometry::ColliderBuilder::polyline(path, None) + for poly in polys { + let v = vertices.len() as u32; + let p = poly.len() as u32; + if p < 3 { + continue; + } + for i in 0..p { + vertices.push(poly[i as usize] / PIXELS_TO_METRES); + indices.push([v + i, v + (i + 1) % p]); + } + } + + geometry::ColliderBuilder::polyline(vertices, Some(indices)) .translation(position / PIXELS_TO_METRES) .build() } - pub fn test_add_collider_from_chunk(&mut self, position: Vec2, chunk: &Chunk) { - let collider = self.collider_from_chunk(position, chunk); - self.physics_manager.collider_set.insert(collider); + pub fn upsert_chunk_collider(&mut self, cx: i32, cy: i32, chunk: &Chunk) { + let collider = self.collider_from_chunk( + Vec2::new((cx * CHUNK_SIZE) as f32, (cy * CHUNK_SIZE) as f32), + chunk, + ); + + if let Some(handle) = self.chunk_colliders.remove(&(cx, cy)) { + self.physics_manager.collider_set.remove( + handle, + &mut self.physics_manager.island_manager, + &mut self.physics_manager.rigid_body_set, + false, + ); + } + + let handle = self.physics_manager.collider_set.insert(collider); + self.chunk_colliders.insert((cx, cy), handle); } pub fn test(&mut self) { @@ -231,8 +252,10 @@ impl RbSimManager { pub fn new() -> Self { RbSimManager { - physics_manager: PhysicsManager::new(), rb_entities: FxHashMap::default(), + chunk_colliders: FxHashMap::default(), + + physics_manager: PhysicsManager::new(), next_id: 0, debug_line_buffer: DebugLineBuffer::default(), } |
