summaryrefslogtreecommitdiff
path: root/src/sim/rb_sim/mod.rs
diff options
context:
space:
mode:
authorKai Stevenson <kai@kaistevenson.com>2026-08-18 20:20:32 -0700
committerKai Stevenson <kai@kaistevenson.com>2026-08-18 20:20:32 -0700
commit92dd02d7cc4d9fc930760d26d81edbe2197a3fc0 (patch)
tree6dfde8d306d20266c2185882c635360478a2b6ef /src/sim/rb_sim/mod.rs
parent5877fbf3991b1f35696bf86d9e1b3da3ece01f42 (diff)
marching rigid bodies
Diffstat (limited to 'src/sim/rb_sim/mod.rs')
-rw-r--r--src/sim/rb_sim/mod.rs121
1 files changed, 54 insertions, 67 deletions
diff --git a/src/sim/rb_sim/mod.rs b/src/sim/rb_sim/mod.rs
index b79de86..d986962 100644
--- a/src/sim/rb_sim/mod.rs
+++ b/src/sim/rb_sim/mod.rs
@@ -1,21 +1,17 @@
+pub mod debug_ops;
pub mod debug_render;
pub mod rb_entity;
use fxhash::FxHashMap;
use glam::Vec2;
-use rapier2d::{
- dynamics::{self},
- geometry::{self, ColliderHandle},
- glamx::vec2,
- math, prelude,
-};
+use rapier2d::{dynamics, geometry, glamx::vec2, prelude};
use crate::{
- config::{CELLS_IN_CHUNK, CHUNK_SIZE, PHYSICS_DELTA_TIME, PIXELS_TO_METRES},
+ config::{CHUNK_SIZE, PHYSICS_DELTA_TIME, PIXELS_TO_METRES},
sim::{
- cell::{cell::Cell, materials::MaterialId},
+ cell::cell::Cell,
cell_sim::chunk::Chunk,
- lib::marching_squares::marching_squares_vertex_trace,
+ lib::marching_squares::{Marchable, marching_squares_vertex_trace},
rb_sim::{
debug_render::{DebugLineBuffer, DebugVertex},
rb_entity::RbEntity,
@@ -70,7 +66,7 @@ impl PhysicsManager {
}
pub struct RbSimManager {
- chunk_colliders: FxHashMap<(i32, i32), ColliderHandle>,
+ chunk_colliders: FxHashMap<(i32, i32), geometry::ColliderHandle>,
pub rb_entities: FxHashMap<u32, RbEntity>,
physics_manager: PhysicsManager,
@@ -116,20 +112,33 @@ impl RbSimManager {
&self.debug_line_buffer.vertices
}
- pub fn create_rb_entity(
- &mut self,
- cells: Box<[Cell; CELLS_IN_CHUNK]>,
- rb_parent: prelude::RigidBodyHandle,
- ) {
+ 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 entity: RbEntity = RbEntity {
id,
cells,
- rb_parent,
+ rb_parent: rb_handle,
+ width: w,
+ height: h,
};
+ let collider = self.convex_hull_collider_from_marchable(&entity).build();
+
self.rb_entities.insert(id, entity);
+ self.physics_manager.collider_set.insert_with_parent(
+ collider,
+ rb_handle,
+ &mut self.physics_manager.rigid_body_set,
+ );
+
+ id
}
pub fn destroy_rb_entity(&mut self, entity_id: u32) {
@@ -166,8 +175,9 @@ impl RbSimManager {
}
}
- fn collider_from_chunk(&self, position: Vec2, chunk: &Chunk) -> geometry::Collider {
- let polys = marching_squares_vertex_trace(chunk, CHUNK_SIZE, CHUNK_SIZE);
+ fn polyline_from_marchable(&self, marchable: &impl Marchable) -> (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();
@@ -178,20 +188,40 @@ impl RbSimManager {
continue;
}
for i in 0..p {
- vertices.push(poly[i as usize] / PIXELS_TO_METRES);
+ 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,
+ ) -> geometry::ColliderBuilder {
+ let (vertices, indices) = self.polyline_from_marchable(marchable);
+
geometry::ColliderBuilder::polyline(vertices, Some(indices))
- .translation(position / PIXELS_TO_METRES)
- .build()
+ }
+
+ fn convex_hull_collider_from_marchable(
+ &self,
+ marchable: &impl Marchable,
+ ) -> geometry::ColliderBuilder {
+ let (vertices, indices) = self.polyline_from_marchable(marchable);
+ geometry::ColliderBuilder::convex_decomposition(&vertices, &indices)
}
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,
+ let collider = self.polyline_collider_from_marchable(chunk).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)) {
@@ -207,49 +237,6 @@ impl RbSimManager {
self.chunk_colliders.insert((cx, cy), handle);
}
- pub fn test(&mut self) {
- /* Create the ground. */
- let collider =
- geometry::ColliderBuilder::cuboid(100.0 / PIXELS_TO_METRES, 8.0 / PIXELS_TO_METRES)
- .position(math::Pose2::from_translation(vec2(
- 0 as f32,
- CHUNK_SIZE as f32 / PIXELS_TO_METRES,
- )))
- .build();
- self.physics_manager.collider_set.insert(collider);
- }
-
- 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(
- x / PIXELS_TO_METRES,
- y / PIXELS_TO_METRES,
- ))
- .build();
- let collider =
- geometry::ColliderBuilder::cuboid(5.0 / PIXELS_TO_METRES, 5.0 / PIXELS_TO_METRES)
- .build();
- let ball_body_handle = self.physics_manager.rigid_body_set.insert(rigid_body);
- self.physics_manager.collider_set.insert_with_parent(
- collider,
- ball_body_handle,
- &mut self.physics_manager.rigid_body_set,
- );
-
- let mut test_cells = Box::new([Cell::void(); CELLS_IN_CHUNK]);
-
- for x in CHUNK_SIZE / 2 - 5..CHUNK_SIZE / 2 + 5 {
- for y in CHUNK_SIZE / 2 - 5..CHUNK_SIZE / 2 + 5 {
- let cell_idx = x + y * CHUNK_SIZE;
- test_cells[cell_idx as usize] = Cell::from_material(material);
- test_cells[cell_idx as usize].set_rb(true);
- }
- }
-
- self.create_rb_entity(test_cells, ball_body_handle);
- }
-
pub fn new() -> Self {
RbSimManager {
rb_entities: FxHashMap::default(),