pub mod rb_entity; use fxhash::FxHashMap; use rapier2d::{ dynamics::{self}, geometry, glamx::vec2, math, prelude, }; use crate::{ config::{CELLS_IN_CHUNK, PHYSICS_DELTA_TIME}, sim::{ cell::{cell::Cell, materials::MaterialId}, rb_sim::rb_entity::RbEntity, }, }; 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, } 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 { 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(), } } } pub struct RbSimManager { physics_manager: PhysicsManager, pub rb_entities: FxHashMap, } impl RbSimManager { pub fn rb_tick(&mut self, delta_time: f32) { let gravity = vec2(0.0, 25.0); 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 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_parent); rb.map(|rb| { let position = rb.position(); let angle = position.rotation.angle(); ( position.translation.x, position.translation.y, angle.cos(), angle.sin(), ) }) } None => return None, } } pub fn test(&mut self) { /* Create the ground. */ let collider = geometry::ColliderBuilder::cuboid(100.0, 0.1).build(); self.physics_manager.collider_set.insert(collider); /* Create the bouncing ball. */ let rigid_body = dynamics::RigidBodyBuilder::dynamic() .translation(math::Vector::new(0.0, -100.0)) .build(); let collider = geometry::ColliderBuilder::ball(5.0) .restitution(0.7) .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 test_cells = Box::new([Cell::void(); CELLS_IN_CHUNK]); let mut rb_entity = RbEntity { id: 0, cells: test_cells, rb_parent: ball_body_handle, }; for x in 0..10 { for y in 0..10 { rb_entity.set_cell_at_local_position(x, y, Cell::from_material(MaterialId::Wood)); } } self.rb_entities.insert(0, rb_entity); } pub fn new() -> Self { RbSimManager { physics_manager: PhysicsManager::new(), rb_entities: FxHashMap::default(), } } }