rapier3d/dynamics/soft_body/soft_body_builder/soft_body_builder.rs
1//! The particle settings, the builder struct and its `Default` and `From` impls.
2
3use crate::alloc_prelude::*;
4use crate::dynamics::SpringCoefficients;
5use crate::geometry::ColliderBuilder;
6use crate::math::{DIM, Real, Vector};
7#[cfg(not(feature = "std"))]
8#[allow(unused_imports)]
9use simba::scalar::{ComplexField as _, RealField as _};
10
11use super::super::{SoftBody, SoftBodyCellModel, SoftBodyMaterial};
12
13/// The dynamics settings shared by every particle of a soft body.
14#[derive(Copy, Clone, Debug)]
15#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
16pub struct SoftBodyParticleSettings {
17 /// Linear damping of the particles (air friction).
18 pub linear_damping: Real,
19 /// Gravity scale of the particles.
20 pub gravity_scale: Real,
21 /// Extra solver substeps requested for the particles (and everything they touch).
22 pub additional_solver_iterations: usize,
23 /// Extra internal PGS iterations per substep for the particles and everything they touch, on
24 /// top of `IntegrationParameters::num_internal_pgs_iterations`; stamped on the root proxy each
25 /// step (see [`crate::dynamics::RigidBody::set_additional_pgs_iterations`]) (default: `3`).
26 pub additional_pgs_iterations: usize,
27 /// Whether the soft body may fall asleep.
28 pub can_sleep: bool,
29 /// Dominance group of the soft body (see [`crate::dynamics::RigidBody::dominance_group`]).
30 pub dominance_group: i8,
31}
32
33impl Default for SoftBodyParticleSettings {
34 fn default() -> Self {
35 Self {
36 linear_damping: 0.0,
37 gravity_scale: 1.0,
38 additional_solver_iterations: 0,
39 additional_pgs_iterations: 3,
40 can_sleep: true,
41 dominance_group: 0,
42 }
43 }
44}
45
46/// A builder for [`crate::dynamics::SoftBody`]s: particles are given in world space and elements
47/// reference particles by index. The generators ([`Self::rope`], plus `cloth`/`cuboid`/`sphere`
48/// in 3D and `polygon`/`disk`/`grid` in 2D) make complete bodies; the setters build any body.
49#[derive(Clone, Debug)]
50pub struct SoftBodyBuilder {
51 /// World-space particle positions.
52 pub positions: Vec<Vector>,
53 /// Per-particle masses (empty = uniform `particle_mass`).
54 pub masses: Vec<Real>,
55 /// Uniform particle mass, used when `masses` is empty.
56 pub particle_mass: Real,
57 /// Indices of the pinned particles.
58 pub pinned: Vec<u32>,
59 /// Structural edges (particle index pairs).
60 pub edges: Vec<[u32; 2]>,
61 /// Bending edges (particle index pairs).
62 pub bend_edges: Vec<[u32; 2]>,
63 /// Edges that only resist stretching, never compression (indices into the concatenation of
64 /// `edges` then `bend_edges`).
65 pub tension_only_edges: Vec<u32>,
66 /// Per-edge softness overrides (indices into the concatenation of `edges` then
67 /// `bend_edges`); the material's softness applies to the others.
68 pub edge_softness: Vec<(u32, SpringCoefficients<Real>)>,
69 /// Per-edge tear-threshold multipliers (indices into the concatenation of `edges` then
70 /// `bend_edges`, see [`crate::dynamics::SoftBodyEdge::tear_resistance`]); `1.0` for the others.
71 pub edge_tear_resistance: Vec<(u32, Real)>,
72 /// Dihedral bending constraints: shared edge then the two opposite vertices.
73 #[cfg(feature = "dim3")]
74 pub dihedrals: Vec<[u32; 4]>,
75 /// Simplex cells (triangles in 2D, tetrahedra in 3D).
76 pub cells: Vec<[u32; DIM + 1]>,
77 /// Boundary elements (segments in 2D, triangles in 3D), oriented outward. Derived from the
78 /// cells when empty.
79 pub surface: Vec<[u32; DIM]>,
80 /// The material.
81 pub material: SoftBodyMaterial,
82 /// The constitutive model of the cells.
83 pub cell_model: SoftBodyCellModel,
84 /// Which solver simulates the body's elasticity.
85 #[cfg(feature = "fem")]
86 pub solver: super::SoftBodySolver,
87 /// Whether area/volume preservation is enabled (one constraint per piece of material enclosed
88 /// by a closed surface).
89 pub volume_preservation: bool,
90 /// Target volume multiplier (`> 1` inflates the body).
91 pub volume_factor: Real,
92 /// Whether shape matching is enabled.
93 pub shape_matching: bool,
94 /// Whether the body's surface collides with itself.
95 pub self_contacts: bool,
96 /// Whether the default collision surface's shape is built with parry's `ORIENTED` flag
97 /// (see [`Self::oriented`]); `None`: when the surface is closed.
98 pub oriented: Option<bool>,
99 /// Thickness of the particles: the contact skin of the body's surface collider.
100 pub particle_radius: Real,
101 /// Template of the colliders of the body's collision meshes (their shape is the mesh's own);
102 /// `None` disables collisions.
103 pub collider_template: Option<ColliderBuilder>,
104 /// Mesh held by the cells, if any: `(vertices, elements)` in world space, bound to the
105 /// cells at build time.
106 pub skin: Option<(Vec<Vector>, Vec<[u32; DIM]>)>,
107 /// The segments the body collides through when it has no surface: a rope or a wire (3D
108 /// only; in 2D the surface is already made of segments).
109 #[cfg(feature = "dim3")]
110 pub wire: Vec<[u32; 2]>,
111 /// Whether the body meets the world through its skin rather than through its cells' boundary
112 /// (off by default, and no effect without a skin).
113 pub skin_collision: bool,
114 /// Dynamics settings of the particles.
115 pub particle_settings: SoftBodyParticleSettings,
116 /// User data of the soft body.
117 pub user_data: u128,
118}
119
120impl Default for SoftBodyBuilder {
121 fn default() -> Self {
122 Self::new(Vec::new())
123 }
124}
125
126impl From<SoftBodyBuilder> for SoftBody {
127 fn from(builder: SoftBodyBuilder) -> Self {
128 builder.build()
129 }
130}