1use crate::alloc_prelude::*;
6use crate::math::{DIM, Real, Vector};
7use parry::utils::hashmap::HashMap;
8#[cfg(not(feature = "std"))]
9#[allow(unused_imports)]
10use simba::scalar::{ComplexField as _, RealField as _};
11
12use super::super::soft_body_builder::cell_faces;
13use super::super::{SoftBody, SoftBodyEdgeKind, SoftBodyParticle};
14use super::tearing::shared_others;
15
16#[derive(Copy, Clone, Debug, PartialEq, Eq)]
18pub(super) enum MeasureKind {
19 Cells,
21 Triangles,
23 Segments,
25}
26
27impl MeasureKind {
28 fn facet_others(self) -> usize {
31 match self {
32 MeasureKind::Cells => DIM - 1,
33 MeasureKind::Triangles => 1,
34 MeasureKind::Segments => 0,
35 }
36 }
37}
38
39#[derive(Clone, Debug)]
41pub(super) struct Fan {
42 pub kind: MeasureKind,
44 pub elements: Vec<u32>,
46 pub vertices: Vec<Vec<u32>>,
48 pub measures: Vec<Real>,
50 pub sides: Vec<usize>,
52 pub groups: Vec<usize>,
55 pub num_groups: usize,
57}
58
59impl Fan {
60 pub(super) fn assign_groups(&mut self, v: u32) {
63 let n = self.elements.len();
64 let mut parent: Vec<usize> = (0..n).collect();
65 fn find(parent: &mut [usize], mut i: usize) -> usize {
66 while parent[i] != i {
67 parent[i] = parent[parent[i]];
68 i = parent[i];
69 }
70 i
71 }
72 let needed = self.kind.facet_others();
73 for i in 0..n {
74 for j in i + 1..n {
75 if self.sides[i] == self.sides[j]
76 && shared_others(&self.vertices[i], &self.vertices[j], v) >= needed
77 {
78 let (ri, rj) = (find(&mut parent, i), find(&mut parent, j));
79 if ri != rj {
80 parent[ri.max(rj)] = ri.min(rj);
81 }
82 }
83 }
84 }
85 let mut group_of_root = vec![usize::MAX; n];
86 self.num_groups = 0;
87 for side in 0..2 {
88 for i in (0..n).filter(|&i| self.sides[i] == side) {
89 let root = find(&mut parent, i);
90 if group_of_root[root] == usize::MAX {
91 group_of_root[root] = self.num_groups;
92 self.num_groups += 1;
93 }
94 self.groups[i] = group_of_root[root];
95 }
96 }
97 }
98}
99
100#[derive(Clone, Debug, Default)]
102pub(super) struct SplitLog {
103 pub split_particles: Vec<(u32, u32)>,
105 pub removed_edges: Vec<[u32; 2]>,
107 pub inserted: Vec<[u32; 4]>,
110}
111
112fn replace(vertices: &mut [u32], from: u32, to: u32) {
114 for x in vertices.iter_mut() {
115 if *x == from {
116 *x = to;
117 }
118 }
119}
120
121impl SoftBody {
122 pub(super) fn measure_kind(&self) -> Option<MeasureKind> {
125 if !self.cells.is_empty() {
126 Some(MeasureKind::Cells)
127 } else if DIM == 3 && !self.boundary.is_empty() {
128 Some(MeasureKind::Triangles)
129 } else if self
130 .edges
131 .iter()
132 .any(|e| e.kind == SoftBodyEdgeKind::Structural)
133 {
134 Some(MeasureKind::Segments)
135 } else {
136 None
137 }
138 }
139
140 pub(super) fn for_each_measure_element(
142 &self,
143 kind: MeasureKind,
144 mut f: impl FnMut(u32, &[u32]),
145 ) {
146 match kind {
147 MeasureKind::Cells => {
148 for (i, c) in self.cells.iter().enumerate() {
149 f(i as u32, &c.vertices);
150 }
151 }
152 MeasureKind::Triangles => {
153 for (i, t) in self.boundary.iter().enumerate() {
154 f(i as u32, t);
155 }
156 }
157 MeasureKind::Segments => {
158 for (i, e) in self.edges.iter().enumerate() {
159 if e.kind == SoftBodyEdgeKind::Structural {
160 f(i as u32, &e.vertices);
161 }
162 }
163 }
164 }
165 }
166
167 pub fn rest_measure(&self) -> Real {
171 let Some(kind) = self.measure_kind() else {
172 return 0.0;
173 };
174 let mut total = 0.0;
175 self.for_each_measure_element(kind, |i, _| total += self.element_rest_measure(kind, i));
176 total
177 }
178
179 pub fn rest_measure_of(&self, particles: &[u32]) -> Real {
182 let Some(kind) = self.measure_kind() else {
183 return 0.0;
184 };
185 let mut total = 0.0;
186 self.for_each_measure_element(kind, |i, vertices| {
187 if vertices.iter().all(|v| particles.binary_search(v).is_ok()) {
188 total += self.element_rest_measure(kind, i);
189 }
190 });
191 total
192 }
193
194 pub(crate) fn rest_distance_to(&self, particles: &[u32], point: Vector) -> Real {
198 use parry::query::PointQuery;
199 let rest = |v: u32| self.particles[v as usize].rest_position;
200 let mut best = Real::MAX;
201 if let Some(kind) = self.measure_kind() {
202 self.for_each_measure_element(kind, |_, vertices| {
203 if !vertices.iter().all(|v| particles.binary_search(v).is_ok()) {
204 return;
205 }
206 let distance = match vertices.len() {
207 2 => parry::shape::Segment::new(rest(vertices[0]), rest(vertices[1]))
208 .distance_to_local_point(point, true),
209 3 => parry::shape::Triangle::new(
210 rest(vertices[0]),
211 rest(vertices[1]),
212 rest(vertices[2]),
213 )
214 .distance_to_local_point(point, true),
215 #[cfg(feature = "dim3")]
216 4 => parry::shape::Tetrahedron::new(
217 rest(vertices[0]),
218 rest(vertices[1]),
219 rest(vertices[2]),
220 rest(vertices[3]),
221 )
222 .distance_to_local_point(point, true),
223 _ => return,
224 };
225 best = best.min(distance);
226 });
227 }
228 if best == Real::MAX {
229 for &v in particles {
230 if let Some(p) = self.particles.get(v as usize) {
231 best = best.min((p.rest_position - point).length());
232 }
233 }
234 }
235 best
236 }
237
238 fn element_rest_measure(&self, kind: MeasureKind, i: u32) -> Real {
241 match kind {
242 MeasureKind::Cells => self.cells[i as usize].rest_volume.abs(),
243 MeasureKind::Triangles => {
244 #[cfg(feature = "dim3")]
245 {
246 let rest = |v: u32| self.particles[v as usize].initial_rest_position;
247 let t = self.boundary[i as usize];
248 (rest(t[1]) - rest(t[0]))
249 .cross(rest(t[2]) - rest(t[0]))
250 .length()
251 * 0.5
252 }
253 #[cfg(feature = "dim2")]
254 {
255 0.0
256 }
257 }
258 MeasureKind::Segments => self.edges[i as usize].initial_rest_length(),
259 }
260 }
261
262 pub(crate) fn measure_element_holds(&self, particles: &[u32]) -> bool {
264 let Some(kind) = self.measure_kind() else {
265 return false;
266 };
267 let mut found = false;
268 self.for_each_measure_element(kind, |_, vertices| {
269 found |= particles.iter().all(|p| vertices.contains(p));
270 });
271 found
272 }
273
274 pub(super) fn fan(&self, kind: MeasureKind, v: u32) -> Fan {
276 let mut elements = Vec::new();
277 let mut vertices = Vec::new();
278 self.for_each_measure_element(kind, |i, element| {
279 if element.contains(&v) {
280 elements.push(i);
281 vertices.push(element.to_vec());
282 }
283 });
284 let n = elements.len();
285 Fan {
286 kind,
287 measures: elements
288 .iter()
289 .map(|&i| self.element_rest_measure(kind, i))
290 .collect(),
291 elements,
292 vertices,
293 sides: vec![0; n],
294 groups: vec![0; n],
295 num_groups: (n > 0) as usize,
296 }
297 }
298
299 pub(super) fn split_particles(&mut self, candidates: &[u32], log: &mut SplitLog) {
303 let Some(kind) = self.measure_kind() else {
304 return;
305 };
306 for &v in candidates {
307 let mut fan = self.fan(kind, v);
308 if fan.elements.len() < 2 {
309 continue;
310 }
311 fan.assign_groups(v);
312 if fan.num_groups >= 2 {
313 self.split_fan(v, &fan, log);
314 }
315 }
316 }
317
318 pub(super) fn plane_fan(&self, v: u32, origin: Vector, normal: Vector) -> Option<Fan> {
322 if self.particles[v as usize].inv_mass == 0.0 {
324 return None;
325 }
326 let kind = self.measure_kind()?;
327 let mut fan = self.fan(kind, v);
328 let rest = |i: u32| self.particles[i as usize].rest_position;
329 for (side, vertices) in fan.sides.iter_mut().zip(&fan.vertices) {
330 let offset: Vector = vertices.iter().map(|&w| rest(w) - origin).sum();
331 *side = (offset.dot(normal) > 0.0) as usize;
332 }
333 if !fan.sides.contains(&0) || !fan.sides.contains(&1) {
334 return None;
335 }
336 fan.assign_groups(v);
337 Some(fan)
338 }
339
340 pub(super) fn min_piece(&self, kind: MeasureKind) -> usize {
344 self.material
345 .min_piece
346 .map_or(default_min_piece(kind), |n| n.max(1) as usize)
347 }
348
349 pub(super) fn opens_without_confetti(&self, v: u32, fan: &Fan) -> bool {
353 let min = self.min_piece(fan.kind);
354 (0..fan.num_groups).all(|g| {
355 let seeds: Vec<u32> = (0..fan.elements.len())
356 .filter(|&i| fan.groups[i] == g)
357 .map(|i| fan.elements[i])
358 .collect();
359 self.reachable_elements(fan.kind, &seeds, v, min) >= min
360 })
361 }
362
363 fn reachable_elements(
366 &self,
367 kind: MeasureKind,
368 seeds: &[u32],
369 pivot: u32,
370 limit: usize,
371 ) -> usize {
372 fn facets(vertices: &[u32], pivot: u32, mut f: impl FnMut([u32; 3])) {
375 for skip in 0..vertices.len() {
376 let mut key = [u32::MAX; 3];
377 let mut k = 0;
378 for (i, &w) in vertices.iter().enumerate() {
379 if i != skip {
380 key[k] = w;
381 k += 1;
382 }
383 }
384 if !key[..k].contains(&pivot) {
385 key[..k].sort_unstable();
386 f(key);
387 }
388 }
389 }
390 let mut by_facet: HashMap<[u32; 3], Vec<u32>> = HashMap::default();
392 let mut elements: HashMap<u32, Vec<u32>> = HashMap::default();
393 self.for_each_measure_element(kind, |i, vertices| {
394 elements.insert(i, vertices.to_vec());
395 facets(vertices, pivot, |key| {
396 by_facet.entry(key).or_default().push(i)
397 });
398 });
399 let mut seen: HashMap<u32, ()> = HashMap::default();
400 let mut stack: Vec<u32> = seeds.to_vec();
401 for &s in seeds {
402 seen.insert(s, ());
403 }
404 while let Some(e) = stack.pop() {
405 if seen.len() >= limit {
406 return seen.len();
407 }
408 facets(&elements[&e], pivot, |key| {
409 if let Some(neighbors) = by_facet.get(&key) {
410 for &n in neighbors {
411 if !seen.contains_key(&n) {
412 seen.insert(n, ());
413 stack.push(n);
414 }
415 }
416 }
417 });
418 }
419 seen.len()
420 }
421
422 pub(super) fn split_fan(&mut self, v: u32, fan: &Fan, log: &mut SplitLog) -> bool {
425 if fan.num_groups < 2 || self.particles[v as usize].inv_mass == 0.0 {
427 return false;
428 }
429 self.split_vertex(v, fan, log);
430 true
431 }
432
433 fn group_toward(&self, v: u32, fan: &Fan, vertices: &[u32]) -> usize {
437 let mut best: Option<usize> = None;
438 for (i, fv) in fan.vertices.iter().enumerate() {
439 if fv.iter().any(|x| *x != v && vertices.contains(x)) {
440 best = Some(best.map_or(fan.groups[i], |b| b.min(fan.groups[i])));
441 }
442 }
443 if let Some(g) = best {
444 return g;
445 }
446 let rest = |i: u32| self.particles[i as usize].rest_position;
447 let mut dir = Vector::ZERO;
448 for &w in vertices.iter().filter(|&&w| w != v) {
449 dir += rest(w) - rest(v);
450 }
451 let mut best_score = -Real::MAX;
452 let mut best_group = 0;
453 for (i, fv) in fan.vertices.iter().enumerate() {
454 for &w in fv.iter().filter(|&&w| w != v) {
455 let d = rest(w) - rest(v);
456 let score = d.dot(dir) / (d.length() * dir.length()).max(1.0e-12);
457 if score > best_score {
458 best_score = score;
459 best_group = fan.groups[i];
460 }
461 }
462 }
463 best_group
464 }
465
466 fn share_measure_element(&self, kind: MeasureKind, x: u32, y: u32) -> bool {
468 let mut found = false;
469 self.for_each_measure_element(kind, |_, vertices| {
470 found |= vertices.contains(&x) && vertices.contains(&y);
471 });
472 found
473 }
474
475 fn split_vertex(&mut self, v: u32, fan: &Fan, log: &mut SplitLog) {
479 let kind = fan.kind;
480 let n = fan.elements.len();
481 let mut weights = vec![0.0; fan.num_groups];
482 for (&g, &measure) in fan.groups.iter().zip(&fan.measures) {
483 weights[g] += measure;
484 }
485 let total: Real = weights.iter().sum();
486 let source = self.particles[v as usize];
487 let mut copies: Vec<u32> = Vec::with_capacity(fan.num_groups);
488 for (g, weight) in weights.iter().enumerate() {
489 let mass = if total > 0.0 {
490 source.mass * weight / total
491 } else {
492 source.mass / fan.num_groups as Real
493 };
494 if g == 0 {
495 let p = &mut self.particles[v as usize];
496 p.mass = mass;
497 if p.inv_mass != 0.0 {
498 p.inv_mass = crate::utils::inv(mass);
499 }
500 copies.push(v);
501 } else {
502 self.particles.push(SoftBodyParticle {
504 mass,
505 inv_mass: crate::utils::inv(mass),
506 next_position: None,
507 split_root: source.split_root(v),
508 ..source
509 });
510 let copy = self.particles.len() as u32 - 1;
511 log.split_particles.push((copy, v));
512 copies.push(copy);
513 }
514 }
515
516 let mut ring: HashMap<u32, Vec<usize>> = HashMap::default();
518 for (vertices, &g) in fan.vertices.iter().zip(&fan.groups) {
519 for &w in vertices.iter().filter(|&&w| w != v) {
520 let groups = ring.entry(w).or_default();
521 if let Err(pos) = groups.binary_search(&g) {
522 groups.insert(pos, g);
523 }
524 }
525 }
526 let mut crack_facets: Vec<(usize, usize)> = Vec::new();
528 if kind == MeasureKind::Cells {
529 for i in 0..n {
530 for j in i + 1..n {
531 if fan.groups[i] != fan.groups[j]
532 && shared_others(&fan.vertices[i], &fan.vertices[j], v) == DIM - 1
533 {
534 crack_facets.push((i, j));
535 }
536 }
537 }
538 }
539
540 for (i, &e) in fan.elements.iter().enumerate() {
541 let g = fan.groups[i];
542 if g == 0 {
543 continue;
544 }
545 let target: &mut [u32] = match kind {
546 MeasureKind::Cells => &mut self.cells[e as usize].vertices,
547 MeasureKind::Triangles => &mut self.boundary[e as usize],
548 MeasureKind::Segments => &mut self.edges[e as usize].vertices,
549 };
550 replace(target, v, copies[g]);
551 }
552
553 let is_measure = |e: &super::super::SoftBodyEdge| {
556 kind == MeasureKind::Segments && e.kind == SoftBodyEdgeKind::Structural
557 };
558 let mut new_edges = Vec::new();
559 for ei in 0..self.edges.len() {
560 let edge = self.edges[ei];
561 if !edge.vertices.contains(&v) || is_measure(&edge) {
562 continue;
563 }
564 let x = if edge.vertices[0] == v {
565 edge.vertices[1]
566 } else {
567 edge.vertices[0]
568 };
569 let groups = ring.get(&x).map(Vec::as_slice).unwrap_or(&[]);
570 let g = match groups.first() {
571 Some(&g) => g,
572 None => self.group_toward(v, fan, &edge.vertices),
573 };
574 replace(&mut self.edges[ei].vertices, v, copies[g]);
575 for &other in groups.iter().skip(1) {
576 let mut copy = self.edges[ei];
577 replace(&mut copy.vertices, copies[g], copies[other]);
578 copy.impulse = 0.0;
579 new_edges.push(copy);
580 }
581 }
582 self.edges.extend(new_edges);
583
584 let mut straddling = vec![false; self.edges.len()];
587 for (ei, e) in self.edges.iter().enumerate() {
588 if is_measure(e) || e.vertices.iter().any(|w| copies.contains(w)) {
589 continue;
590 }
591 let [x, y] = e.vertices;
592 let (Some(gx), Some(gy)) = (ring.get(&x), ring.get(&y)) else {
593 continue;
594 };
595 if gx.iter().all(|g| gy.binary_search(g).is_err())
596 && !self.share_measure_element(kind, x, y)
597 {
598 straddling[ei] = true;
599 log.removed_edges.push(e.vertices);
600 }
601 }
602 if straddling.contains(&true) {
603 let mut keep = straddling.iter().map(|s| !s);
604 self.edges.retain(|_| keep.next().unwrap());
605 }
606
607 #[cfg(feature = "dim3")]
608 {
609 let holder = |t: [u32; 3]| {
611 fan.vertices
612 .iter()
613 .position(|fv| t.iter().all(|w| fv.contains(w)))
614 };
615 let mut removed = vec![false; self.dihedrals.len()];
616 for di in 0..self.dihedrals.len() {
617 let d = self.dihedrals[di].vertices;
618 if !d.contains(&v) {
619 continue;
620 }
621 let g = match (holder([d[0], d[1], d[2]]), holder([d[0], d[1], d[3]])) {
622 (Some(i), Some(j)) if fan.groups[i] != fan.groups[j] => {
624 removed[di] = true;
625 continue;
626 }
627 (Some(i), _) | (None, Some(i)) => fan.groups[i],
628 (None, None) => self.group_toward(v, fan, &d),
629 };
630 replace(&mut self.dihedrals[di].vertices, v, copies[g]);
631 }
632 if removed.contains(&true) {
633 let mut keep = removed.iter().map(|r| !r);
634 self.dihedrals.retain(|_| keep.next().unwrap());
635 }
636 }
637
638 if kind != MeasureKind::Triangles {
639 for si in 0..self.boundary.len() {
642 let element = self.boundary[si];
643 if !element.contains(&v) {
644 continue;
645 }
646 let holder = fan
647 .vertices
648 .iter()
649 .position(|fv| element.iter().all(|x| fv.contains(x)));
650 let g = match holder {
651 Some(i) => fan.groups[i],
652 None => self.group_toward(v, fan, &element),
653 };
654 replace(&mut self.boundary[si], v, copies[g]);
655 }
656 }
657 for &(i, j) in &crack_facets {
658 for k in [i, j] {
659 let cell = self.cells[fan.elements[k] as usize].vertices;
660 let copy = copies[fan.groups[k]];
661 let on_facet = |w: &u32| {
662 *w == copy
663 || (*w != v && fan.vertices[i].contains(w) && fan.vertices[j].contains(w))
664 };
665 if let Some(face) = cell_faces(cell)
666 .into_iter()
667 .find(|face| face.iter().all(on_facet))
668 {
669 self.boundary.push(face);
670 }
671 }
672 }
673 }
674
675 pub(super) fn remove_straddlers_across_pieces(&mut self, log: &mut SplitLog) {
679 let Some(kind) = self.measure_kind() else {
680 return;
681 };
682 let n = self.particles.len();
683 let mut parent: Vec<u32> = (0..n as u32).collect();
684 let mut supported = vec![false; n];
685 fn find(parent: &mut [u32], mut i: u32) -> u32 {
686 while parent[i as usize] != i {
687 let up = parent[parent[i as usize] as usize];
688 parent[i as usize] = up;
689 i = up;
690 }
691 i
692 }
693 self.for_each_measure_element(kind, |_, vertices| {
694 for &w in vertices {
695 supported[w as usize] = true;
696 }
697 for w in vertices.windows(2) {
698 let (a, b) = (find(&mut parent, w[0]), find(&mut parent, w[1]));
699 if a != b {
700 parent[a.max(b) as usize] = a.min(b);
701 }
702 }
703 });
704 let roots: Vec<u32> = (0..n as u32).map(|i| find(&mut parent, i)).collect();
705 let spans = |vertices: &[u32]| {
706 vertices.iter().all(|&w| supported[w as usize])
707 && vertices
708 .iter()
709 .any(|&w| roots[w as usize] != roots[vertices[0] as usize])
710 };
711
712 let removed: Vec<bool> = self
713 .edges
714 .iter()
715 .map(|e| {
716 !(kind == MeasureKind::Segments && e.kind == SoftBodyEdgeKind::Structural)
717 && spans(&e.vertices)
718 })
719 .collect();
720 if removed.contains(&true) {
721 for (e, _) in self.edges.iter().zip(&removed).filter(|(_, r)| **r) {
722 log.removed_edges.push(e.vertices);
723 }
724 let mut keep = removed.iter().map(|r| !r);
725 self.edges.retain(|_| keep.next().unwrap());
726 }
727 #[cfg(feature = "dim3")]
728 self.dihedrals.retain(|d| !spans(&d.vertices));
729 if kind != MeasureKind::Triangles {
730 self.boundary.retain(|s| !spans(s));
731 }
732 }
733}
734
735pub(super) const MIN_PIECE_TRIANGLES: usize = 10;
737pub(super) const MIN_PIECE_CELLS: usize = if DIM == 2 { 3 } else { 6 };
740pub(super) const MIN_PIECE_SEGMENTS: usize = 3;
742
743pub(super) fn default_min_piece(kind: MeasureKind) -> usize {
746 match kind {
747 MeasureKind::Cells => MIN_PIECE_CELLS,
748 MeasureKind::Triangles => MIN_PIECE_TRIANGLES,
749 MeasureKind::Segments => MIN_PIECE_SEGMENTS,
750 }
751}