use crate::alloc_prelude::*;
use crate::dynamics::{ImpulseJointHandle, RigidBodyHandle};
use crate::math::{DIM, Real};
use super::super::SoftBodyHandle;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SoftClusterSplit {
pub source_cluster: u32,
pub soft_body: SoftBodyHandle,
pub cluster: u32,
pub proxy: RigidBodyHandle,
pub keeps_proxy: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SoftBodyPiece {
pub soft_body: SoftBodyHandle,
pub particles: Vec<u32>,
pub clusters: Vec<[u32; 2]>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SoftJointMove {
pub joint: ImpulseJointHandle,
pub from: RigidBodyHandle,
pub to: RigidBodyHandle,
}
#[derive(Clone, Debug, Default)]
pub struct SoftBodyTearEvent {
pub soft_body: SoftBodyHandle,
pub torn_edges: Vec<[u32; 2]>,
pub torn_cells: Vec<[u32; DIM + 1]>,
pub removed_edges: Vec<[u32; 2]>,
pub split_particles: Vec<(u32, u32)>,
pub inserted_particles: Vec<u32>,
pub pieces: Vec<SoftBodyPiece>,
pub clusters: Vec<SoftClusterSplit>,
pub moved_joints: Vec<SoftJointMove>,
}
impl SoftBodyTearEvent {
pub fn bodies(&self) -> impl Iterator<Item = SoftBodyHandle> + '_ {
let whole = self.pieces.is_empty().then_some(self.soft_body);
whole
.into_iter()
.chain(self.pieces.iter().map(|piece| piece.soft_body))
}
pub fn particle_destination(&self, particle: u32) -> Option<(SoftBodyHandle, u32)> {
if self.pieces.is_empty() {
return Some((self.soft_body, particle));
}
self.pieces.iter().find_map(|piece| {
piece
.particles
.binary_search(&particle)
.ok()
.map(|i| (piece.soft_body, i as u32))
})
}
pub fn seeds(&self) -> Vec<[u32; 2]> {
let mut seeds: Vec<[u32; 2]> = self
.split_particles
.iter()
.map(|&(copy, source)| [copy, source])
.collect();
seeds.extend(
self.inserted_particles
.chunks_exact(2)
.map(|pair| [pair[0], pair[1]]),
);
seeds
}
}
pub(super) const CATASTROPHIC_STRESS: Real = 2.0;