Files
rapier/src_testbed/physics/mod.rs
Sébastien Crozet 0b7c3b34ec feat: migrate to glam whenever relevant + migrate testbed to kiss3d instead of bevy + release v0.32.0 (#909)
* feat: migrate to glam whenever relevant + migrate testbed to kiss3d instead of bevy

* chore: update changelog

* Fix warnings and tests

* Release v0.32.0
2026-01-09 17:26:36 +01:00

170 lines
5.8 KiB
Rust

use rapier::dynamics::{
CCDSolver, ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet,
RigidBodySet,
};
use rapier::geometry::{
BroadPhaseBvh, ColliderSet, CollisionEvent, ContactForceEvent, DefaultBroadPhase, NarrowPhase,
};
use rapier::pipeline::{PhysicsHooks, PhysicsPipeline};
use std::sync::mpsc::Receiver;
#[derive(Clone)]
pub struct PhysicsSnapshot {
timestep_id: usize,
broad_phase: Vec<u8>,
narrow_phase: Vec<u8>,
bodies: Vec<u8>,
colliders: Vec<u8>,
impulse_joints: Vec<u8>,
multibody_joints: Vec<u8>,
island_manager: Vec<u8>,
}
pub struct DeserializedPhysicsSnapshot {
pub timestep_id: usize,
pub broad_phase: DefaultBroadPhase,
pub narrow_phase: NarrowPhase,
pub island_manager: IslandManager,
pub bodies: RigidBodySet,
pub colliders: ColliderSet,
pub impulse_joints: ImpulseJointSet,
pub multibody_joints: MultibodyJointSet,
}
impl PhysicsSnapshot {
pub fn new(
timestep_id: usize,
broad_phase: &DefaultBroadPhase,
narrow_phase: &NarrowPhase,
island_manager: &IslandManager,
bodies: &RigidBodySet,
colliders: &ColliderSet,
impulse_joints: &ImpulseJointSet,
multibody_joints: &MultibodyJointSet,
) -> bincode::Result<Self> {
Ok(Self {
timestep_id,
broad_phase: bincode::serialize(broad_phase)?,
narrow_phase: bincode::serialize(narrow_phase)?,
island_manager: bincode::serialize(island_manager)?,
bodies: bincode::serialize(bodies)?,
colliders: bincode::serialize(colliders)?,
impulse_joints: bincode::serialize(impulse_joints)?,
multibody_joints: bincode::serialize(multibody_joints)?,
})
}
#[profiling::function]
pub fn restore(&self) -> bincode::Result<DeserializedPhysicsSnapshot> {
Ok(DeserializedPhysicsSnapshot {
timestep_id: self.timestep_id,
broad_phase: bincode::deserialize(&self.broad_phase)?,
narrow_phase: bincode::deserialize(&self.narrow_phase)?,
island_manager: bincode::deserialize(&self.island_manager)?,
bodies: bincode::deserialize(&self.bodies)?,
colliders: bincode::deserialize(&self.colliders)?,
impulse_joints: bincode::deserialize(&self.impulse_joints)?,
multibody_joints: bincode::deserialize(&self.multibody_joints)?,
})
}
pub fn print_snapshot_len(&self) {
let total = self.broad_phase.len()
+ self.narrow_phase.len()
+ self.island_manager.len()
+ self.bodies.len()
+ self.colliders.len()
+ self.impulse_joints.len()
+ self.multibody_joints.len();
println!("Snapshot length: {total}B");
println!("|_ broad_phase: {}B", self.broad_phase.len());
println!("|_ narrow_phase: {}B", self.narrow_phase.len());
println!("|_ island_manager: {}B", self.island_manager.len());
println!("|_ bodies: {}B", self.bodies.len());
println!("|_ colliders: {}B", self.colliders.len());
println!("|_ impulse_joints: {}B", self.impulse_joints.len());
println!("|_ multibody_joints: {}B", self.multibody_joints.len());
}
}
pub struct PhysicsState {
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 pipeline: PhysicsPipeline,
pub integration_parameters: IntegrationParameters,
pub gravity: rapier::math::Vector,
pub hooks: Box<dyn PhysicsHooks>,
}
impl Default for PhysicsState {
fn default() -> Self {
Self::new()
}
}
impl PhysicsState {
pub fn new() -> Self {
Self {
islands: IslandManager::new(),
broad_phase: DefaultBroadPhase::default(),
narrow_phase: NarrowPhase::new(),
bodies: RigidBodySet::new(),
colliders: ColliderSet::new(),
impulse_joints: ImpulseJointSet::new(),
multibody_joints: MultibodyJointSet::new(),
ccd_solver: CCDSolver::new(),
pipeline: PhysicsPipeline::new(),
integration_parameters: IntegrationParameters::default(),
gravity: rapier::math::Vector::Y * -9.81,
hooks: Box::new(()),
}
}
/// Create a snapshot of the current physics state.
pub fn snapshot(&self) -> PhysicsSnapshot {
PhysicsSnapshot::new(
0, // timestep_id - could be tracked if needed
&self.broad_phase,
&self.narrow_phase,
&self.islands,
&self.bodies,
&self.colliders,
&self.impulse_joints,
&self.multibody_joints,
)
.expect("Failed to create physics snapshot")
}
/// Restore physics state from a snapshot.
pub fn restore_snapshot(&mut self, snapshot: PhysicsSnapshot) {
let restored = snapshot
.restore()
.expect("Failed to restore physics snapshot");
self.broad_phase = restored.broad_phase;
self.narrow_phase = restored.narrow_phase;
self.islands = restored.island_manager;
self.bodies = restored.bodies;
self.colliders = restored.colliders;
self.impulse_joints = restored.impulse_joints;
self.multibody_joints = restored.multibody_joints;
}
}
pub struct PhysicsEvents {
pub collision_events: Receiver<CollisionEvent>,
pub contact_force_events: Receiver<ContactForceEvent>,
}
impl PhysicsEvents {
pub fn poll_all(&self) {
while self.collision_events.try_recv().is_ok() {}
while self.contact_force_events.try_recv().is_ok() {}
}
}