diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-24 20:15:21 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-24 20:15:21 -0700 |
| commit | e28f8b4ef5c0744912afd49d8d1ba9a94e144613 (patch) | |
| tree | a38fe431647834ea21ddd03984e41e5d00c32d50 /src/sim/sim_manager/utils.rs | |
| parent | 3bae37a2d439804aee543473ef9b44f18692a67f (diff) | |
fixes for small entities
Diffstat (limited to 'src/sim/sim_manager/utils.rs')
| -rw-r--r-- | src/sim/sim_manager/utils.rs | 93 |
1 files changed, 69 insertions, 24 deletions
diff --git a/src/sim/sim_manager/utils.rs b/src/sim/sim_manager/utils.rs index 69a4756..38f503a 100644 --- a/src/sim/sim_manager/utils.rs +++ b/src/sim/sim_manager/utils.rs @@ -1,12 +1,14 @@ -use glam::IVec2; +use glam::{IVec2, Vec2}; use rapier2d::dynamics::RigidBodyBuilder; use crate::{ + config::MIN_ENTITY_CELLS, content::materials::MaterialId, sim::{ cell::Cell, entity::{EntityCells, EntityDef, EntityId, EntityUpdateResult}, lib::components::compute_components, + particle_manager::particle::Particle, sim_manager::SimManager, }, }; @@ -66,10 +68,27 @@ fn write_entity_to_world(sim: &mut SimManager, entity_id: EntityId) -> Vec<(u8, cells_written } +pub struct WrittenEntitiesScope { + cells_written_by_entity: Vec<(EntityId, Vec<(u8, u8, i32, i32)>)>, +} + +impl WrittenEntitiesScope { + // TODO can use a hashmap to optimize this + pub fn get_entity_id_at_position(&self, position: IVec2) -> Option<EntityId> { + self.cells_written_by_entity + .iter() + .find(|(_, v)| { + v.iter() + .any(|&(_, _, x, y)| x == position.x && y == position.y) + }) + .map(|e| e.0) + } +} + pub fn write_entities_to_world( sim: &mut SimManager, // (entity_x, entity_y, cell_x, cell_y) -) -> Vec<(EntityId, Vec<(u8, u8, i32, i32)>)> { +) -> WrittenEntitiesScope { puffin::profile_function!(); // TODO optimize let entity_ids: Vec<EntityId> = sim.entities.keys().copied().collect(); @@ -80,16 +99,18 @@ pub fn write_entities_to_world( cells_written_by_entity.push((entity_id, cells_written)); } - cells_written_by_entity + WrittenEntitiesScope { + cells_written_by_entity, + } } // TODO optimize pub fn read_back_entities_from_world( sim: &mut SimManager, - cells_written_by_entity: Vec<(EntityId, Vec<(u8, u8, i32, i32)>)>, + written_entities_scope: WrittenEntitiesScope, ) { puffin::profile_function!(); - for (entity_id, cells_written) in cells_written_by_entity { + for (entity_id, cells_written) in written_entities_scope.cells_written_by_entity { let mut entity = sim.entities.get_mut(&entity_id); let mut should_update_entity = false; @@ -128,7 +149,10 @@ pub fn read_back_entities_from_world( } 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() { + // if the new entity is too small for a collider, we can turn the entity into particles + if components[0].cells.len() < MIN_ENTITY_CELLS { + sim.atomize_entity(entity_id); + } else if let Some(new_collider) = entity.compute_collider() { // don't profile this separately as it's basically free sim.rb_manager .physics_manager @@ -146,7 +170,6 @@ pub fn read_back_entities_from_world( } else { // the entity was partitioned // destroy the original entity - // correctness -- not correct! because we don't have pos without rb puffin::profile_scope!("Partition entity"); let old_rb = sim .rb_manager @@ -154,33 +177,55 @@ pub fn read_back_entities_from_world( .world .bodies .get(entity.data.rb_h.unwrap()) + // correctness -- not correct! because we don't have pos without rb .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); - let mut pose = old_pose; - pose.translation += r; + // unless it's too small + if component.cells.len() < MIN_ENTITY_CELLS { + for x in 0..component.size.x { + for y in 0..component.size.y { + let r = old_pose.transform_vector( + Vec2::new(x as f32, y as f32) - (component.size / 2).as_vec2() + + component.position, + ); + sim.particle_manager.particles.push(Particle::new( + old_pose.translation + r, + old_linvel, + component.cells[(x + y * component.size.x) as usize].material, + 3.0, + 0.1, + )) + } + } + } else { + let r = old_pose.transform_vector(component.position); + let mut pose = old_pose; + pose.translation += r; - let rb = RigidBodyBuilder::dynamic() - .pose(pose) - .linvel(old_linvel) - .angvel(old_angvel) - .build(); + 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); + let def = EntityDef::from_cells_and_rb( + EntityCells { + cells: component.cells, + size: component.size, + }, + rb, + None, + ); + + sim.create_entity(def); + } } } } |
