Skip to main content

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}