rapier3d/dynamics/soft_body/
soft_body_meshes.rs1use super::{SoftBody, SoftBodyCell, SoftCollisionMesh, SoftMeshId};
3use crate::alloc_prelude::*;
4use crate::math::{DIM, Vector};
5
6impl SoftBody {
7 pub fn meshes(&self) -> impl Iterator<Item = &SoftCollisionMesh> {
10 self.clusters
11 .iter()
12 .filter(|cluster| cluster.is_live())
13 .flat_map(|cluster| cluster.meshes())
14 }
15
16 pub fn mesh(&self, id: SoftMeshId) -> Option<&SoftCollisionMesh> {
18 self.clusters
19 .get(id.cluster as usize)
20 .filter(|cluster| cluster.is_live())
21 .and_then(|cluster| cluster.mesh(id.mesh))
22 }
23
24 pub fn mesh_of(&self, collider: crate::geometry::ColliderHandle) -> Option<&SoftCollisionMesh> {
26 self.meshes().find(|mesh| mesh.collider() == collider)
27 }
28
29 pub fn collision_mesh(&self) -> Option<&SoftCollisionMesh> {
31 self.meshes().find(|mesh| mesh.collision_enabled())
32 }
33
34 pub(crate) fn meshes_mut(&mut self) -> impl Iterator<Item = &mut SoftCollisionMesh> {
37 self.clusters.iter_mut().flat_map(|c| c.meshes_mut())
38 }
39
40 pub(crate) fn refresh_vertex_caches(&mut self) {
43 let particles = &self.particles;
44 for cluster in &mut self.clusters {
45 for mesh in cluster.meshes_mut() {
46 mesh.refresh_vertex_cache(particles);
47 }
48 }
49 }
50
51 pub(crate) fn mesh_mut(&mut self, id: SoftMeshId) -> Option<&mut SoftCollisionMesh> {
52 self.clusters
53 .get_mut(id.cluster as usize)?
54 .meshes
55 .get_mut(id.mesh as usize)?
56 .as_mut()
57 }
58
59 pub(crate) fn mesh_of_mut(
61 &mut self,
62 collider: crate::geometry::ColliderHandle,
63 ) -> Option<&mut SoftCollisionMesh> {
64 self.clusters
65 .iter_mut()
66 .flat_map(|cluster| cluster.meshes.iter_mut().flatten())
67 .find(|mesh| mesh.collider() == collider)
68 }
69
70 pub(crate) fn bind_mesh(
73 &self,
74 cluster: u32,
75 binding: &super::SoftMeshBinding,
76 vertices: Vec<Vector>,
77 indices: Vec<[u32; DIM]>,
78 ) -> Result<SoftCollisionMesh, super::SoftBindingError> {
79 use super::{SoftBindingError, SoftMeshBindingMode, SoftMeshMapping};
80 let cluster = self
81 .cluster(cluster)
82 .ok_or(SoftBindingError::NotAClusterProxy)?;
83 let in_cluster = |particle: u32| cluster.particles().binary_search(&particle).is_ok();
84
85 let mapping = match &binding.mode {
86 SoftMeshBindingMode::Direct { particles } => {
87 if particles.len() != vertices.len() {
88 return Err(SoftBindingError::DegenerateMesh);
89 }
90 for (vertex, &particle) in particles.iter().enumerate() {
91 if particle as usize >= self.particles.len() || !in_cluster(particle) {
92 return Err(SoftBindingError::VertexOutsideCluster {
93 vertex: vertex as u32,
94 particle,
95 });
96 }
97 }
98 SoftMeshMapping::Direct {
99 particles: particles.clone(),
100 }
101 }
102 SoftMeshBindingMode::DirectByPosition { eps } => {
103 let mut particles = Vec::with_capacity(vertices.len());
104 for (vertex, position) in vertices.iter().enumerate() {
105 let closest = cluster
106 .particles()
107 .iter()
108 .map(|&p| {
109 (
110 p,
111 (self.particles[p as usize].position - *position).length(),
112 )
113 })
114 .filter(|(_, d)| *d <= *eps)
115 .min_by(|a, b| a.1.total_cmp(&b.1));
116 let (particle, _) = closest.ok_or(SoftBindingError::UnmatchedVertex {
117 vertex: vertex as u32,
118 })?;
119 particles.push(particle);
120 }
121 SoftMeshMapping::Direct { particles }
122 }
123 SoftMeshBindingMode::Skinned => {
124 let cells: Vec<usize> = (0..self.cells.len())
127 .filter(|&c| self.cells[c].vertices.iter().all(|v| in_cluster(*v)))
128 .collect();
129 let owned: Vec<SoftBodyCell> = cells.iter().map(|&c| self.cells[c]).collect();
130 let positions: Vec<Vector> = self.particles.iter().map(|p| p.position).collect();
133 let bindings =
134 super::collision_mesh::bind_to_cells(&vertices, &indices, &owned, &positions)
135 .ok_or(SoftBindingError::UnboundVertex { vertex: 0 })?;
136 SoftMeshMapping::Skinned {
138 bindings: bindings
139 .into_iter()
140 .map(|mut binding| {
141 binding.cell = cells[binding.cell as usize] as u32;
142 binding
143 })
144 .collect(),
145 }
146 }
147 };
148
149 Ok(SoftCollisionMesh::new(
150 mapping,
151 indices,
152 vertices,
153 self,
154 binding.self_contacts,
155 ))
156 }
157
158 pub(crate) fn push_mesh(&mut self, cluster: u32, mut mesh: SoftCollisionMesh) -> SoftMeshId {
160 let meshes = &mut self.clusters[cluster as usize].meshes;
161 let slot = meshes
162 .iter()
163 .position(|slot| slot.is_none())
164 .unwrap_or(meshes.len());
165 let id = SoftMeshId {
166 cluster,
167 mesh: slot as u32,
168 };
169 mesh.set_id(id);
170 if slot == meshes.len() {
171 meshes.push(Some(mesh));
172 } else {
173 meshes[slot] = Some(mesh);
174 }
175 self.modified = true;
176 id
177 }
178
179 pub(crate) fn set_mesh_collider(
181 &mut self,
182 id: SoftMeshId,
183 collider: crate::geometry::ColliderHandle,
184 ) {
185 if let Some(mesh) = self.mesh_mut(id) {
186 mesh.collider = collider;
187 }
188 }
189
190 pub(crate) fn remove_mesh(&mut self, id: SoftMeshId) -> Option<SoftCollisionMesh> {
192 self.clusters
193 .get_mut(id.cluster as usize)?
194 .meshes
195 .get_mut(id.mesh as usize)?
196 .take()
197 }
198
199 pub(crate) fn for_each_mesh_mut(
201 &mut self,
202 mut f: impl FnMut(&SoftBody, &mut SoftCollisionMesh),
203 ) {
204 let mut clusters = core::mem::take(&mut self.clusters);
205 for cluster in &mut clusters {
206 for mesh in cluster.meshes.iter_mut().flatten() {
207 f(self, mesh);
208 }
209 }
210 self.clusters = clusters;
211 }
212
213 pub(crate) fn update_surface_flags(&mut self) {
215 for p in &mut self.particles {
216 p.on_surface = false;
217 }
218 for element in &self.boundary {
219 for &v in element {
220 if let Some(p) = self.particles.get_mut(v as usize) {
221 p.on_surface = true;
222 }
223 }
224 }
225 }
226
227 pub(crate) fn update_meshes(&mut self) {
229 self.for_each_mesh_mut(|body, mesh| mesh.update(&body.cells, &body.particles));
230 }
231
232 pub(crate) fn rebuild_mesh_tables(&mut self) {
234 self.for_each_mesh_mut(|body, mesh| mesh.rebuild_tables(body));
235 }
236}