diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-22 15:00:35 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-22 15:00:35 -0700 |
| commit | 1a515237afb7ad09353a65f5fbc6e98a7c29ce8e (patch) | |
| tree | 48cd4b4bcf8f8e357811f905f22607838d7c1f96 /src/sim/rb_sim | |
| parent | 6350e4ffca8ce1e46465284ef3d7559e0f40229b (diff) | |
sim manager refactor
Diffstat (limited to 'src/sim/rb_sim')
| -rw-r--r-- | src/sim/rb_sim/debug_ops.rs | 48 | ||||
| -rw-r--r-- | src/sim/rb_sim/debug_render.rs | 71 | ||||
| -rw-r--r-- | src/sim/rb_sim/mod.rs | 289 | ||||
| -rw-r--r-- | src/sim/rb_sim/rb_entity.rs | 39 |
4 files changed, 0 insertions, 447 deletions
diff --git a/src/sim/rb_sim/debug_ops.rs b/src/sim/rb_sim/debug_ops.rs deleted file mode 100644 index d6852da..0000000 --- a/src/sim/rb_sim/debug_ops.rs +++ /dev/null @@ -1,48 +0,0 @@ -use glam::{ivec2, vec2}; - -use crate::sim::{ - cell::{cell::Cell, materials::MaterialId}, - rb_sim::RbSimManager, -}; - -pub trait DebugOperator { - fn test_spawn_box(&mut self, x: f32, y: f32, material: MaterialId) -> (); - fn test_spawn_ball(&mut self, x: f32, y: f32, material: MaterialId) -> (); -} - -impl DebugOperator for RbSimManager { - fn test_spawn_box(&mut self, x: f32, y: f32, material: MaterialId) { - let w = 10; - let h = 10; - let mut test_cells = vec![Cell::void(); (w * h) as usize]; - - for x in 0..w { - for y in 0..h { - let cell_idx = x + y * w; - test_cells[cell_idx as usize] = Cell::from_material(material); - test_cells[cell_idx as usize].set_rb(true); - } - } - - self.create_rb_entity(vec2(x, y), test_cells, w, h); - } - - fn test_spawn_ball(&mut self, x: f32, y: f32, material: MaterialId) { - let r = 5; - let w = r * 2; - let h = r * 2; - let mut test_cells = vec![Cell::void(); (w * h) as usize]; - - for x in 0..w { - for y in 0..h { - let cell_idx = x + y * w; - if ivec2(x, y).distance_squared(ivec2(w / 2, h / 2)) < r.pow(2) { - test_cells[cell_idx as usize] = Cell::from_material(material); - test_cells[cell_idx as usize].set_rb(true); - } - } - } - - self.create_rb_entity(vec2(x, y), test_cells, w, h); - } -} diff --git a/src/sim/rb_sim/debug_render.rs b/src/sim/rb_sim/debug_render.rs deleted file mode 100644 index 342fc5b..0000000 --- a/src/sim/rb_sim/debug_render.rs +++ /dev/null @@ -1,71 +0,0 @@ -use rapier2d::pipeline::{DebugColor, DebugRenderBackend, DebugRenderObject}; - -use crate::config::PIXELS_TO_METRES; - -#[repr(C)] -#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -pub struct DebugVertex { - pub position: [f32; 2], - pub color: [f32; 4], -} - -#[derive(Default)] -pub struct DebugLineBuffer { - pub vertices: Vec<DebugVertex>, -} - -impl DebugRenderBackend for DebugLineBuffer { - fn draw_line( - &mut self, - _object: DebugRenderObject, - a: rapier2d::math::Vector, - b: rapier2d::math::Vector, - color: DebugColor, - ) { - let color = hsla_to_linear_rgba(color); - self.vertices.push(DebugVertex { - position: [a.x * PIXELS_TO_METRES, a.y * PIXELS_TO_METRES], - color, - }); - self.vertices.push(DebugVertex { - position: [b.x * PIXELS_TO_METRES, b.y * PIXELS_TO_METRES], - color, - }); - } -} - -fn hsla_to_linear_rgba(hsla: DebugColor) -> [f32; 4] { - let [hue, saturation, lightness, alpha] = hsla; - - let hue = hue.rem_euclid(360.0) / 60.0; - let saturation = saturation.clamp(0.0, 1.0); - let lightness = lightness.clamp(0.0, 1.0); - - let chroma = (1.0 - (2.0 * lightness - 1.0).abs()) * saturation; - let second = chroma * (1.0 - (hue % 2.0 - 1.0).abs()); - let (r, g, b) = match hue as u32 { - 0 => (chroma, second, 0.0), - 1 => (second, chroma, 0.0), - 2 => (0.0, chroma, second), - 3 => (0.0, second, chroma), - 4 => (second, 0.0, chroma), - _ => (chroma, 0.0, second), - }; - let m = lightness - chroma / 2.0; - - [ - srgb_to_linear(r + m), - srgb_to_linear(g + m), - srgb_to_linear(b + m), - alpha.clamp(0.0, 1.0), - ] -} - -fn srgb_to_linear(channel: f32) -> f32 { - let channel = channel.clamp(0.0, 1.0); - if channel <= 0.04045 { - channel / 12.92 - } else { - ((channel + 0.055) / 1.055).powf(2.4) - } -} diff --git a/src/sim/rb_sim/mod.rs b/src/sim/rb_sim/mod.rs deleted file mode 100644 index f81d5f1..0000000 --- a/src/sim/rb_sim/mod.rs +++ /dev/null @@ -1,289 +0,0 @@ -pub mod debug_ops; -pub mod debug_render; -pub mod rb_entity; - -use fxhash::FxHashMap; -use glam::Vec2; -use rapier2d::{dynamics, geometry, glamx::vec2, prelude}; - -use crate::{ - config::{CHUNK_SIZE, PHYSICS_DELTA_TIME, PIXELS_TO_METRES}, - sim::{ - cell::cell::Cell, - cell_sim::chunk::Chunk, - lib::marching_squares::{Marchable, marching_squares_vertex_trace}, - rb_sim::{ - debug_render::{DebugLineBuffer, DebugVertex}, - rb_entity::RbEntity, - }, - }, -}; - -pub use rapier2d::pipeline::DebugRenderMode; - -pub struct PhysicsManager { - rigid_body_set: prelude::RigidBodySet, - collider_set: prelude::ColliderSet, - physics_pipeline: prelude::PhysicsPipeline, - integration_parameters: prelude::IntegrationParameters, - island_manager: prelude::IslandManager, - broad_phase: prelude::DefaultBroadPhase, - narrow_phase: prelude::NarrowPhase, - impulse_joint_set: prelude::ImpulseJointSet, - multibody_joint_set: prelude::MultibodyJointSet, - ccd_solver: prelude::CCDSolver, - debug_render_pipeline: prelude::DebugRenderPipeline, -} - -impl PhysicsManager { - pub fn new() -> Self { - PhysicsManager { - rigid_body_set: prelude::RigidBodySet::new(), - collider_set: prelude::ColliderSet::new(), - physics_pipeline: prelude::PhysicsPipeline::new(), - integration_parameters: prelude::IntegrationParameters { - // 20 pixels <-> 1 meter - length_unit: PIXELS_TO_METRES, - dt: PHYSICS_DELTA_TIME, - ..prelude::IntegrationParameters::default() - }, - island_manager: prelude::IslandManager::new(), - broad_phase: prelude::DefaultBroadPhase::new(), - narrow_phase: prelude::NarrowPhase::new(), - impulse_joint_set: prelude::ImpulseJointSet::new(), - multibody_joint_set: prelude::MultibodyJointSet::new(), - ccd_solver: prelude::CCDSolver::new(), - debug_render_pipeline: prelude::DebugRenderPipeline::new( - prelude::DebugRenderStyle { - sleep_color_multiplier: [1.0; 4], - sleep_eligible_color_multiplier: [1.0; 4], - ..prelude::DebugRenderStyle::default() - }, - prelude::DebugRenderMode::default(), - ), - } - } -} - -pub struct RbSimManager { - chunk_colliders: FxHashMap<(i32, i32), geometry::ColliderHandle>, - pub rb_entities: FxHashMap<u32, RbEntity>, - - physics_manager: PhysicsManager, - next_id: u32, - debug_line_buffer: DebugLineBuffer, -} - -impl RbSimManager { - pub fn rb_tick(&mut self, delta_time: f32) { - let gravity = vec2(0.0, 9.81); - - self.physics_manager.physics_pipeline.step( - gravity, - &self.physics_manager.integration_parameters, - &mut self.physics_manager.island_manager, - &mut self.physics_manager.broad_phase, - &mut self.physics_manager.narrow_phase, - &mut self.physics_manager.rigid_body_set, - &mut self.physics_manager.collider_set, - &mut self.physics_manager.impulse_joint_set, - &mut self.physics_manager.multibody_joint_set, - &mut self.physics_manager.ccd_solver, - &(), - &(), - ); - } - - pub fn debug_render(&mut self, mode: DebugRenderMode) -> &[DebugVertex] { - puffin::profile_function!(); - - let physics = &mut self.physics_manager; - self.debug_line_buffer.vertices.clear(); - physics.debug_render_pipeline.mode = mode; - physics.debug_render_pipeline.render( - &mut self.debug_line_buffer, - &physics.rigid_body_set, - &physics.collider_set, - &physics.impulse_joint_set, - &physics.multibody_joint_set, - &physics.narrow_phase, - ); - - &self.debug_line_buffer.vertices - } - - pub fn create_rb_entity(&mut self, position: Vec2, cells: Vec<Cell>, w: i32, h: i32) -> u32 { - let id = self.next_id; - self.next_id += 1; - - let rb = dynamics::RigidBodyBuilder::dynamic() - .translation(position / PIXELS_TO_METRES) - .build(); - let rb_handle = self.physics_manager.rigid_body_set.insert(rb); - - let mut entity: RbEntity = RbEntity { - id, - cells, - width: w, - height: h, - rb: rb_handle, - collider: None, - }; - - let collider = self - .convex_hull_collider_from_marchable(&entity, None) - .build(); - let collider_handle = self.physics_manager.collider_set.insert_with_parent( - collider, - rb_handle, - &mut self.physics_manager.rigid_body_set, - ); - - entity.collider = Some(collider_handle); - - self.rb_entities.insert(id, entity); - - id - } - - pub fn update_rb_entity(&mut self, entity_id: u32) { - let entity = self.rb_entities.get(&entity_id).unwrap(); - let new_collider = self - .convex_hull_collider_from_marchable(entity, None) - .build(); - - self.physics_manager.collider_set.remove( - entity.collider.unwrap(), - &mut self.physics_manager.island_manager, - &mut self.physics_manager.rigid_body_set, - false, - ); - - let new_collider_handle = self.physics_manager.collider_set.insert_with_parent( - new_collider, - entity.rb, - &mut self.physics_manager.rigid_body_set, - ); - - let entity = self.rb_entities.get_mut(&entity_id).unwrap(); - entity.collider = Some(new_collider_handle); - } - - 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, - &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 { - Some(entity) => { - let rb = self.physics_manager.rigid_body_set.get(entity.rb); - rb.map(|rb| { - let position = rb.position(); - let angle = position.rotation.angle(); - ( - position.translation.x * PIXELS_TO_METRES, - position.translation.y * PIXELS_TO_METRES, - angle.cos(), - angle.sin(), - ) - }) - } - None => return None, - } - } - - fn polyline_from_marchable( - &self, - marchable: &impl Marchable, - minimum_verts: Option<u32>, - ) -> (Vec<Vec2>, Vec<[u32; 2]>) { - let (w, h) = marchable.size(); - let polys = marching_squares_vertex_trace(marchable, w, h); - let mut vertices = Vec::new(); - let mut indices = Vec::new(); - - let minimum_verts = minimum_verts.unwrap_or(3); - - for poly in polys { - let v = vertices.len() as u32; - let p = poly.len() as u32; - if p < minimum_verts { - continue; - } - for i in 0..p { - vertices.push( - (poly[i as usize] - vec2((w as f32 - 1.0) / 2.0, (h as f32 - 1.0) / 2.0)) - / PIXELS_TO_METRES, - ); - indices.push([v + i, v + (i + 1) % p]); - } - } - - (vertices, indices) - } - - fn polyline_collider_from_marchable( - &self, - marchable: &impl Marchable, - minimum_verts: Option<u32>, - ) -> geometry::ColliderBuilder { - let (vertices, indices) = self.polyline_from_marchable(marchable, minimum_verts); - - geometry::ColliderBuilder::polyline(vertices, Some(indices)) - } - - fn convex_hull_collider_from_marchable( - &self, - marchable: &impl Marchable, - minimum_verts: Option<u32>, - ) -> geometry::ColliderBuilder { - let (vertices, indices) = self.polyline_from_marchable(marchable, minimum_verts); - geometry::ColliderBuilder::convex_decomposition(&vertices, &indices) - } - - pub fn upsert_chunk_collider(&mut self, cx: i32, cy: i32, chunk: &Chunk) { - puffin::profile_function!(); - let collider = self - .polyline_collider_from_marchable(chunk, Some(20)) - .translation( - vec2( - (cx as f32 + 0.5) * CHUNK_SIZE as f32, - (cy as f32 + 0.5) * CHUNK_SIZE as f32, - ) / PIXELS_TO_METRES, - ); - - 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 new() -> Self { - RbSimManager { - rb_entities: FxHashMap::default(), - chunk_colliders: FxHashMap::default(), - - physics_manager: PhysicsManager::new(), - next_id: 0, - debug_line_buffer: DebugLineBuffer::default(), - } - } -} diff --git a/src/sim/rb_sim/rb_entity.rs b/src/sim/rb_sim/rb_entity.rs deleted file mode 100644 index 18a6693..0000000 --- a/src/sim/rb_sim/rb_entity.rs +++ /dev/null @@ -1,39 +0,0 @@ -use rapier2d::prelude; - -use crate::sim::{ - cell::{cell::Cell, materials::MaterialId}, - lib::marching_squares::Marchable, -}; - -pub struct RbEntity { - pub id: u32, - pub width: i32, - pub height: i32, - pub cells: Vec<Cell>, - pub rb: prelude::RigidBodyHandle, - pub collider: Option<prelude::ColliderHandle>, -} - -impl RbEntity { - #[inline] - pub fn get_cell_at_local_position(&self, x: u8, y: u8) -> Cell { - self.cells[x as usize + y as usize * self.width as usize] - } - #[inline] - pub fn set_cell_at_local_position(&mut self, x: u8, y: u8, cell: Cell) { - self.cells[x as usize + y as usize * self.width as usize] = cell; - } -} - -impl Marchable for RbEntity { - fn occupied(&self, x: i32, y: i32) -> bool { - if x < 0 || x >= self.width || y < 0 || y >= self.height { - false - } else { - self.get_cell_at_local_position(x as u8, y as u8).material != MaterialId::Void - } - } - fn size(&self) -> (i32, i32) { - (self.width, self.height) - } -} |
