use indexmap::IndexMap;
use rapier3d::dynamics::{
CCDSolver, ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet, RigidBody,
RigidBodyHandle, RigidBodySet,
};
use rapier3d::geometry::{
BroadPhaseBvh, Collider, ColliderHandle, ColliderSet, NarrowPhase,
};
use rapier3d::math::Vector;
use rapier3d::pipeline::PhysicsPipeline;
use viewport_lib::NodeId;
pub struct RapierState {
pub integration_params: IntegrationParameters,
pub pipeline: PhysicsPipeline,
pub islands: IslandManager,
pub broad_phase: BroadPhaseBvh,
pub narrow_phase: NarrowPhase,
pub bodies: RigidBodySet,
pub colliders: ColliderSet,
pub impulse_joints: ImpulseJointSet,
pub multibody_joints: MultibodyJointSet,
pub ccd_solver: CCDSolver,
pub gravity: Vector,
pub node_to_body: IndexMap<NodeId, RigidBodyHandle>,
pub body_to_node: IndexMap<RigidBodyHandle, NodeId>,
pub node_to_collider: IndexMap<NodeId, ColliderHandle>,
pub collider_to_node: IndexMap<ColliderHandle, NodeId>,
}
impl RapierState {
pub fn new(gravity: Vector) -> Self {
Self {
integration_params: IntegrationParameters::default(),
pipeline: PhysicsPipeline::new(),
islands: IslandManager::new(),
broad_phase: BroadPhaseBvh::new(),
narrow_phase: NarrowPhase::new(),
bodies: RigidBodySet::new(),
colliders: ColliderSet::new(),
impulse_joints: ImpulseJointSet::new(),
multibody_joints: MultibodyJointSet::new(),
ccd_solver: CCDSolver::new(),
gravity,
node_to_body: IndexMap::new(),
body_to_node: IndexMap::new(),
node_to_collider: IndexMap::new(),
collider_to_node: IndexMap::new(),
}
}
pub fn add_body(&mut self, node_id: NodeId, body: RigidBody, collider: Collider) {
let body_handle = self.bodies.insert(body);
let collider_handle =
self.colliders
.insert_with_parent(collider, body_handle, &mut self.bodies);
self.node_to_body.insert(node_id, body_handle);
self.body_to_node.insert(body_handle, node_id);
self.node_to_collider.insert(node_id, collider_handle);
self.collider_to_node.insert(collider_handle, node_id);
}
pub fn remove_body(&mut self, node_id: NodeId) {
let Some(body_handle) = self.node_to_body.shift_remove(&node_id) else {
return;
};
self.body_to_node.shift_remove(&body_handle);
if let Some(collider_handle) = self.node_to_collider.shift_remove(&node_id) {
self.collider_to_node.shift_remove(&collider_handle);
}
self.bodies.remove(
body_handle,
&mut self.islands,
&mut self.colliders,
&mut self.impulse_joints,
&mut self.multibody_joints,
true,
);
}
pub fn clear_bodies(&mut self) {
let ids: Vec<NodeId> = self.node_to_body.keys().copied().collect();
for id in ids {
self.remove_body(id);
}
}
pub fn node_for_collider(&self, handle: ColliderHandle) -> Option<NodeId> {
self.collider_to_node.get(&handle).copied()
}
pub fn node_for_body(&self, handle: RigidBodyHandle) -> Option<NodeId> {
self.body_to_node.get(&handle).copied()
}
}