use rapier3d::prelude::*;
use super::destructible::SplitCohort;
#[derive(Clone, Copy, Debug)]
pub struct ResimulationOptions {
pub enabled: bool,
pub max_passes: usize,
}
impl Default for ResimulationOptions {
fn default() -> Self {
Self {
enabled: false,
max_passes: 0,
}
}
}
#[derive(Clone, Copy, Debug)]
struct BodySnapshot {
handle: RigidBodyHandle,
position: Isometry<Real>,
linvel: Vector<Real>,
angvel: AngVector<Real>,
linear_damping: Real,
angular_damping: Real,
user_force: Vector<Real>,
user_torque: AngVector<Real>,
sleeping: bool,
enabled: bool,
}
#[derive(Clone, Debug, Default)]
pub struct BodySnapshots {
bodies: Vec<BodySnapshot>,
}
impl BodySnapshots {
pub fn capture(set: &RigidBodySet) -> Self {
let bodies = set
.iter()
.map(|(handle, body)| BodySnapshot {
handle,
position: *body.position(),
linvel: *body.linvel(),
angvel: *body.angvel(),
linear_damping: body.linear_damping(),
angular_damping: body.angular_damping(),
user_force: body.user_force(),
user_torque: body.user_torque(),
sleeping: body.is_sleeping(),
enabled: body.is_enabled(),
})
.collect();
Self { bodies }
}
pub fn restore(&self, set: &mut RigidBodySet) {
for snapshot in &self.bodies {
let Some(body) = set.get_mut(snapshot.handle) else {
continue;
};
body.set_enabled(snapshot.enabled);
body.set_position(snapshot.position, true);
if !body.is_fixed() {
body.set_linvel(snapshot.linvel, true);
body.set_angvel(snapshot.angvel, true);
body.set_linear_damping(snapshot.linear_damping);
body.set_angular_damping(snapshot.angular_damping);
body.reset_forces(true);
body.reset_torques(true);
if snapshot.user_force.norm_squared() > 0.0 {
body.add_force(snapshot.user_force, true);
}
if snapshot.user_torque.norm_squared() > 0.0 {
body.add_torque(snapshot.user_torque, true);
}
}
if snapshot.sleeping {
body.sleep();
} else {
body.wake_up(true);
}
}
}
pub fn restore_split_children(&self, set: &mut RigidBodySet, split_cohorts: &[SplitCohort]) {
for cohort in split_cohorts {
for &target_handle in &cohort.target_bodies {
let Some(source_handle) = cohort
.target_sources
.iter()
.find_map(|(target, source)| (*target == target_handle).then_some(*source))
else {
continue;
};
let Some(source_snapshot) = self
.bodies
.iter()
.find(|snapshot| snapshot.handle == source_handle)
.copied()
else {
continue;
};
let Some(target_body) = set.get_mut(target_handle) else {
continue;
};
target_body.set_enabled(source_snapshot.enabled);
target_body.set_position(source_snapshot.position, true);
if !target_body.is_fixed() {
target_body.set_linvel(source_snapshot.linvel, true);
target_body.set_angvel(source_snapshot.angvel, true);
target_body.set_linear_damping(source_snapshot.linear_damping);
target_body.set_angular_damping(source_snapshot.angular_damping);
target_body.reset_forces(true);
target_body.reset_torques(true);
if source_snapshot.user_force.norm_squared() > 0.0 {
target_body.add_force(source_snapshot.user_force, true);
}
if source_snapshot.user_torque.norm_squared() > 0.0 {
target_body.add_torque(source_snapshot.user_torque, true);
}
}
if source_snapshot.sleeping {
target_body.sleep();
} else {
target_body.wake_up(true);
}
}
}
}
}