rapier3d/dynamics/soft_body/soft_body_builder/
soft_body_builder_settings.rs1use crate::alloc_prelude::*;
4use crate::dynamics::SpringCoefficients;
5use crate::geometry::ColliderBuilder;
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::{SoftBodyCellModel, SoftBodyMaterial};
13use super::{SoftBodyBuilder, SoftBodyParticleSettings};
14
15impl SoftBodyBuilder {
16 pub fn particle_positions(&self) -> &[Vector] {
22 &self.positions
23 }
24
25 pub fn positions(mut self, positions: Vec<Vector>) -> Self {
27 self.positions = positions;
28 self
29 }
30
31 pub fn particle_mass(mut self, mass: Real) -> Self {
33 self.particle_mass = mass;
34 self.masses.clear();
35 self
36 }
37
38 pub fn mass(mut self, mass: Real) -> Self {
40 self.particle_mass = mass / self.positions.len().max(1) as Real;
41 self.masses.clear();
42 self
43 }
44
45 pub fn masses(mut self, masses: Vec<Real>) -> Self {
47 self.masses = masses;
48 self
49 }
50
51 pub fn pinned_particles(mut self, pinned: impl IntoIterator<Item = u32>) -> Self {
54 self.pinned.extend(pinned);
55 self
56 }
57
58 pub fn edges(mut self, edges: Vec<[u32; 2]>) -> Self {
60 self.edges = edges;
61 self
62 }
63
64 pub fn add_edges(mut self, edges: impl IntoIterator<Item = [u32; 2]>) -> Self {
67 let inserted: Vec<[u32; 2]> = edges.into_iter().collect();
68 let shift = inserted.len() as u32;
71 let first_bend = self.edges.len() as u32;
72 for i in &mut self.tension_only_edges {
73 if *i >= first_bend {
74 *i += shift;
75 }
76 }
77 for (i, _) in &mut self.edge_softness {
78 if *i >= first_bend {
79 *i += shift;
80 }
81 }
82 for (i, _) in &mut self.edge_tear_resistance {
83 if *i >= first_bend {
84 *i += shift;
85 }
86 }
87 self.edges.extend(inserted);
88 self
89 }
90
91 pub fn append(mut self, other: SoftBodyBuilder) -> Self {
95 let offset = self.positions.len() as u32;
96 if !self.masses.is_empty() || !other.masses.is_empty() {
98 if self.masses.is_empty() {
99 self.masses = vec![self.particle_mass; self.positions.len()];
100 }
101 if other.masses.is_empty() {
102 self.masses.extend(core::iter::repeat_n(
103 other.particle_mass,
104 other.positions.len(),
105 ));
106 } else {
107 self.masses.extend_from_slice(&other.masses);
108 }
109 }
110 let (self_edges, self_bends) = (self.edges.len() as u32, self.bend_edges.len() as u32);
112 let (other_edges, other_bends) = (other.edges.len() as u32, other.bend_edges.len() as u32);
113 let remap_self = |i: u32| if i < self_edges { i } else { i + other_edges };
114 let remap_other = |i: u32| {
115 if i < other_edges {
116 i + self_edges
117 } else {
118 i - other_edges + self_edges + other_edges + self_bends
119 }
120 };
121 for i in &mut self.tension_only_edges {
122 *i = remap_self(*i);
123 }
124 for (i, _) in &mut self.edge_softness {
125 *i = remap_self(*i);
126 }
127 for (i, _) in &mut self.edge_tear_resistance {
128 *i = remap_self(*i);
129 }
130 self.tension_only_edges
131 .extend(other.tension_only_edges.iter().map(|&i| remap_other(i)));
132 self.edge_softness.extend(
133 other
134 .edge_softness
135 .iter()
136 .map(|&(i, c)| (remap_other(i), c)),
137 );
138 self.edge_tear_resistance.extend(
139 other
140 .edge_tear_resistance
141 .iter()
142 .map(|&(i, r)| (remap_other(i), r)),
143 );
144 let _ = other_bends;
145 let shift = |v: &[u32]| -> Vec<u32> { v.iter().map(|&i| i + offset).collect() };
146 self.positions.extend_from_slice(&other.positions);
147 self.pinned.extend(shift(&other.pinned));
148 self.edges
149 .extend(other.edges.iter().map(|e| [e[0] + offset, e[1] + offset]));
150 self.bend_edges.extend(
151 other
152 .bend_edges
153 .iter()
154 .map(|e| [e[0] + offset, e[1] + offset]),
155 );
156 #[cfg(feature = "dim3")]
157 self.dihedrals.extend(
158 other
159 .dihedrals
160 .iter()
161 .map(|d| [d[0] + offset, d[1] + offset, d[2] + offset, d[3] + offset]),
162 );
163 self.cells
164 .extend(other.cells.iter().map(|c| c.map(|i| i + offset)));
165 self.surface
166 .extend(other.surface.iter().map(|s| s.map(|i| i + offset)));
167 self
168 }
169
170 pub fn bend_edges(mut self, edges: Vec<[u32; 2]>) -> Self {
172 self.bend_edges = edges;
173 self
174 }
175
176 pub fn tension_only(mut self) -> Self {
178 self.tension_only_edges = (0..(self.edges.len() + self.bend_edges.len()) as u32).collect();
179 self
180 }
181
182 #[cfg(feature = "dim3")]
184 pub fn dihedrals(mut self, dihedrals: Vec<[u32; 4]>) -> Self {
185 self.dihedrals = dihedrals;
186 self
187 }
188
189 pub fn cells(mut self, cells: Vec<[u32; DIM + 1]>) -> Self {
192 self.cells = cells;
193 self
194 }
195
196 pub fn translated(mut self, translation: Vector) -> Self {
201 for position in &mut self.positions {
202 *position += translation;
203 }
204 if let Some((vertices, _)) = &mut self.skin {
205 for vertex in vertices {
206 *vertex += translation;
207 }
208 }
209 self
210 }
211
212 pub fn skin(mut self, vertices: Vec<Vector>, indices: Vec<[u32; DIM]>) -> Self {
216 self.skin = Some((vertices, indices));
217 self
218 }
219
220 pub fn skin_collision(mut self, enabled: bool) -> Self {
224 self.skin_collision = enabled;
225 self
226 }
227
228 #[cfg(feature = "dim3")]
232 pub fn wire(mut self, segments: Vec<[u32; 2]>) -> Self {
233 self.wire = segments;
234 self
235 }
236
237 pub fn surface(mut self, surface: Vec<[u32; DIM]>) -> Self {
241 self.surface = surface;
242 self
243 }
244
245 pub fn material(mut self, material: SoftBodyMaterial) -> Self {
247 self.material = material;
248 self
249 }
250
251 pub fn softness(mut self, softness: SpringCoefficients<Real>) -> Self {
253 self.material = SoftBodyMaterial::uniform(softness);
254 self
255 }
256
257 pub fn tear_strain(mut self, strain: Real) -> Self {
259 self.material.tear_strain = Some(strain);
260 self
261 }
262
263 pub fn tear_force(mut self, force: Real) -> Self {
265 self.material.tear_force = Some(force);
266 self
267 }
268
269 pub fn min_piece(mut self, elements: u32) -> Self {
272 self.material.min_piece = Some(elements);
273 self
274 }
275
276 pub fn tear_smoothing(mut self, seconds: Real) -> Self {
279 self.material.tear_smoothing = seconds;
280 self
281 }
282
283 pub fn interior_strength(mut self, strength: Real) -> Self {
285 self.material.interior_strength = strength;
286 self
287 }
288
289 pub fn edge_tear_resistance(mut self, edges: impl IntoIterator<Item = (u32, Real)>) -> Self {
293 self.edge_tear_resistance.extend(edges);
294 self
295 }
296
297 pub fn cell_model(mut self, model: SoftBodyCellModel) -> Self {
299 self.cell_model = model;
300 self
301 }
302
303 #[cfg(feature = "fem")]
305 pub fn solver(mut self, solver: super::SoftBodySolver) -> Self {
306 self.solver = solver;
307 self
308 }
309
310 pub fn volume_preservation(mut self, enabled: bool) -> Self {
313 self.volume_preservation = enabled;
314 self
315 }
316
317 pub fn volume_factor(mut self, factor: Real) -> Self {
319 self.volume_factor = factor;
320 self
321 }
322
323 pub fn shape_matching(mut self, enabled: bool) -> Self {
325 self.shape_matching = enabled;
326 self
327 }
328
329 pub fn self_contacts(mut self, enabled: bool) -> Self {
331 self.self_contacts = enabled;
332 self
333 }
334
335 pub fn oriented(mut self, oriented: bool) -> Self {
342 self.oriented = Some(oriented);
343 self
344 }
345
346 pub fn particle_radius(mut self, radius: Real) -> Self {
348 self.particle_radius = radius;
349 self
350 }
351
352 pub fn surface_collider(mut self, collider: ColliderBuilder) -> Self {
356 self.collider_template = Some(collider);
357 self
358 }
359
360 pub fn no_surface_collider(mut self) -> Self {
363 self.collider_template = None;
364 self
365 }
366
367 pub fn particle_settings(mut self, settings: SoftBodyParticleSettings) -> Self {
369 self.particle_settings = settings;
370 self
371 }
372
373 pub fn linear_damping(mut self, damping: Real) -> Self {
375 self.particle_settings.linear_damping = damping;
376 self
377 }
378
379 pub fn gravity_scale(mut self, scale: Real) -> Self {
381 self.particle_settings.gravity_scale = scale;
382 self
383 }
384
385 pub fn additional_solver_iterations(mut self, iterations: usize) -> Self {
387 self.particle_settings.additional_solver_iterations = iterations;
388 self
389 }
390
391 pub fn additional_pgs_iterations(mut self, iterations: usize) -> Self {
396 self.particle_settings.additional_pgs_iterations = iterations;
397 self
398 }
399
400 pub fn can_sleep(mut self, can_sleep: bool) -> Self {
402 self.particle_settings.can_sleep = can_sleep;
403 self
404 }
405
406 pub fn user_data(mut self, data: u128) -> Self {
408 self.user_data = data;
409 self
410 }
411
412 pub fn surface_edges(&self) -> Vec<[u32; 2]> {
418 let mut seen: HashMap<[u32; 2], ()> = HashMap::default();
419 let mut edges = Vec::new();
420 for element in &self.surface {
421 for k in 0..DIM {
422 let a = element[k];
423 let b = element[(k + 1) % DIM];
424 let key = [a.min(b), a.max(b)];
425 if seen.insert(key, ()).is_none() {
426 edges.push(key);
427 }
428 }
429 }
430 edges
431 }
432
433 pub fn cell_edges(&self) -> Vec<[u32; 2]> {
435 let mut seen: HashMap<[u32; 2], ()> = HashMap::default();
436 let mut edges = Vec::new();
437 for cell in &self.cells {
438 for i in 0..DIM + 1 {
439 for j in i + 1..DIM + 1 {
440 let key = [cell[i].min(cell[j]), cell[i].max(cell[j])];
441 if seen.insert(key, ()).is_none() {
442 edges.push(key);
443 }
444 }
445 }
446 }
447 edges
448 }
449
450 #[cfg(feature = "dim3")]
452 pub fn surface_dihedrals(&self) -> Vec<[u32; 4]> {
453 let mut opposite: HashMap<[u32; 2], (u32, Option<u32>)> = HashMap::default();
455 let mut order = Vec::new();
456 for tri in &self.surface {
457 for k in 0..3 {
458 let a = tri[k];
459 let b = tri[(k + 1) % 3];
460 let c = tri[(k + 2) % 3];
461 let key = [a.min(b), a.max(b)];
462 match opposite.get_mut(&key) {
463 None => {
464 opposite.insert(key, (c, None));
465 order.push(key);
466 }
467 Some((_, second)) => {
468 if second.is_none() {
469 *second = Some(c);
470 }
471 }
472 }
473 }
474 }
475 order
476 .into_iter()
477 .filter_map(|key| {
478 let (c, d) = opposite[&key];
479 d.map(|d| [key[0], key[1], c, d])
480 })
481 .collect()
482 }
483}