135 lines
3.4 KiB
Rust
135 lines
3.4 KiB
Rust
use crossbeam::channel::Receiver;
|
|
use rapier2d::{
|
|
dynamics::{
|
|
CCDSolver, GenericJoint, ImpulseJointSet, IntegrationParameters, IslandManager,
|
|
MultibodyJointSet, RigidBody, RigidBodyHandle, RigidBodySet,
|
|
},
|
|
geometry::{BroadPhase, Collider, ColliderHandle, ColliderSet, CollisionEvent, NarrowPhase},
|
|
na::vector,
|
|
pipeline::{ChannelEventCollector, PhysicsPipeline},
|
|
};
|
|
|
|
/// Wraps Rapier2d physics parameters
|
|
pub struct PhysWrapper {
|
|
ip: IntegrationParameters,
|
|
pp: PhysicsPipeline,
|
|
im: IslandManager,
|
|
bp: BroadPhase,
|
|
np: NarrowPhase,
|
|
mj: MultibodyJointSet,
|
|
ccd: CCDSolver,
|
|
|
|
rigid_body_set: RigidBodySet,
|
|
collider_set: ColliderSet,
|
|
joint_set: ImpulseJointSet,
|
|
|
|
collision_handler: ChannelEventCollector,
|
|
|
|
/// Collision event queue
|
|
/// this should be emptied after every frame.
|
|
pub collision_queue: Receiver<CollisionEvent>,
|
|
}
|
|
|
|
impl PhysWrapper {
|
|
/// Make a new physics wrapper
|
|
pub fn new() -> Self {
|
|
let (collision_send, collision_queue) = crossbeam::channel::unbounded();
|
|
let (contact_force_send, _) = crossbeam::channel::unbounded();
|
|
|
|
Self {
|
|
ip: IntegrationParameters::default(),
|
|
pp: PhysicsPipeline::new(),
|
|
im: IslandManager::new(),
|
|
bp: BroadPhase::new(),
|
|
np: NarrowPhase::new(),
|
|
mj: MultibodyJointSet::new(),
|
|
ccd: CCDSolver::new(),
|
|
collision_queue,
|
|
collision_handler: ChannelEventCollector::new(collision_send, contact_force_send),
|
|
|
|
rigid_body_set: RigidBodySet::new(),
|
|
collider_set: ColliderSet::new(),
|
|
joint_set: ImpulseJointSet::new(),
|
|
}
|
|
}
|
|
|
|
/// Step physics sim by `t` seconds
|
|
pub fn step(&mut self, t: f32) {
|
|
self.ip.dt = t;
|
|
self.pp.step(
|
|
&vector![0.0, 0.0],
|
|
&self.ip,
|
|
&mut self.im,
|
|
&mut self.bp,
|
|
&mut self.np,
|
|
&mut self.rigid_body_set,
|
|
&mut self.collider_set,
|
|
&mut self.joint_set,
|
|
&mut self.mj,
|
|
&mut self.ccd,
|
|
None,
|
|
&(),
|
|
&mut self.collision_handler,
|
|
);
|
|
}
|
|
|
|
/// Remove a rigid body and all its colliders from this physics wrapper
|
|
pub fn remove_rigid_body(&mut self, body: RigidBodyHandle) -> Option<RigidBody> {
|
|
return self.rigid_body_set.remove(
|
|
body,
|
|
&mut self.im,
|
|
&mut self.collider_set,
|
|
&mut self.joint_set,
|
|
&mut self.mj,
|
|
true,
|
|
);
|
|
}
|
|
}
|
|
|
|
impl PhysWrapper {
|
|
/// Get a rigidbody from this physics wrapper
|
|
pub fn get_rigid_body(&self, h: RigidBodyHandle) -> Option<&RigidBody> {
|
|
self.rigid_body_set.get(h)
|
|
}
|
|
|
|
/// Get a rigidbody from this physics wrapper, mutably
|
|
pub fn get_rigid_body_mut(&mut self, h: RigidBodyHandle) -> Option<&mut RigidBody> {
|
|
self.rigid_body_set.get_mut(h)
|
|
}
|
|
|
|
/// Get a collider from this physics wrapper
|
|
pub fn get_collider(&self, h: ColliderHandle) -> Option<&Collider> {
|
|
self.collider_set.get(h)
|
|
}
|
|
|
|
/// Get a collider from this physics wrapper, mutably
|
|
pub fn get_collider_mut(&mut self, h: ColliderHandle) -> Option<&mut Collider> {
|
|
self.collider_set.get_mut(h)
|
|
}
|
|
|
|
/// Add a rigid body
|
|
pub fn insert_rigid_body(&mut self, rb: RigidBody) -> RigidBodyHandle {
|
|
self.rigid_body_set.insert(rb)
|
|
}
|
|
|
|
/// Attach a collider to a rigid body
|
|
pub fn insert_collider(
|
|
&mut self,
|
|
collider: Collider,
|
|
parent_handle: RigidBodyHandle,
|
|
) -> ColliderHandle {
|
|
self.collider_set
|
|
.insert_with_parent(collider, parent_handle, &mut self.rigid_body_set)
|
|
}
|
|
|
|
/// Add an impulse joint between two bodies
|
|
pub fn add_joint(
|
|
&mut self,
|
|
body1: RigidBodyHandle,
|
|
body2: RigidBodyHandle,
|
|
joint: impl Into<GenericJoint>,
|
|
) {
|
|
self.joint_set.insert(body1, body2, joint, false);
|
|
}
|
|
}
|