diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-23 22:48:38 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-23 22:48:38 -0700 |
| commit | 820e4d00837376bc63b614a382809469a719ed0b (patch) | |
| tree | 79d3fff7b76777c6f241183d4fd9f5479d709cbe /src/sim/sim_manager/utils.rs | |
| parent | 3c5b52c742a86dfb86238bad3bfc375bf12fc518 (diff) | |
entity partitioning
Diffstat (limited to 'src/sim/sim_manager/utils.rs')
| -rw-r--r-- | src/sim/sim_manager/utils.rs | 58 |
1 files changed, 53 insertions, 5 deletions
diff --git a/src/sim/sim_manager/utils.rs b/src/sim/sim_manager/utils.rs index f30e9a0..264597d 100644 --- a/src/sim/sim_manager/utils.rs +++ b/src/sim/sim_manager/utils.rs @@ -1,10 +1,13 @@ use glam::IVec2; +use rapier2d::{dynamics::RigidBodyBuilder, math::Pose}; use crate::{ + config::CELLS_TO_METRES, content::materials::MaterialId, sim::{ cell::Cell, - entity::{EntityId, EntityUpdateResult}, + entity::{EntityCells, EntityDef, EntityId, EntityUpdateResult}, + lib::components::compute_components, sim_manager::SimManager, }, }; @@ -117,10 +120,17 @@ pub fn read_back_entities_from_world( if let Some(entity) = &mut entity && should_update_entity { - puffin::profile_scope!("Recompute collider"); - if let Some(new_collider) = entity.compute_collider() { - { - puffin::profile_scope!("Upsert collider"); + // correctness: there's no way to get here if the entity is an uncelled entity + let ec = entity.data.cells.as_mut().unwrap(); + // first check if the entity has been partitioned + let components = compute_components(&ec.cells, ec.size.x, ec.size.y); + if components.len() == 0 { + panic!("The entity was completely destroyed?") + } else if components.len() == 1 { + // the entity's cells were changed, but not partitioned + puffin::profile_scope!("Recompute collider"); + if let Some(new_collider) = entity.compute_collider() { + // don't profile this separately as it's basically free sim.rb_manager .physics_manager .world @@ -134,6 +144,44 @@ pub fn read_back_entities_from_world( entity.data.collider_h = Some(new_handle); } + } else { + // the entity was partitioned + // destroy the original entity + // correctness -- not correct! because we don't have pos without rb + let old_rb = sim + .rb_manager + .physics_manager + .world + .bodies + .get(entity.data.rb_h.unwrap()) + .unwrap(); + let old_pose = old_rb.position().clone(); + let old_linvel = old_rb.linvel().clone(); + let old_angvel = old_rb.angvel().clone(); + + sim.destroy_entity(entity_id); + // and create a new entity for each component + for component in components { + let r = old_pose.transform_vector(component.position / CELLS_TO_METRES); + let mut pose = old_pose; + pose.translation += r; + + let rb = RigidBodyBuilder::dynamic() + .pose(pose) + .linvel(old_linvel) + .angvel(old_angvel) + .build(); + + let def = EntityDef::from_cells_and_rb( + EntityCells { + cells: component.cells, + size: component.size, + }, + rb, + None, + ); + sim.create_entity(def); + } } } } |
