rapier3d/dynamics/soft_body/soft_body_set/
soft_body_set_insert_remove.rs1use super::soft_body_set_proxies::{spawn_mesh_collider, spawn_proxy};
3use super::{SoftBodyIslandEvent, SoftBodySet};
4use crate::alloc_prelude::*;
5use crate::dynamics::soft_body::{SoftBody, SoftBodyCluster, SoftBodyHandle, SoftMeshId};
6use crate::dynamics::{
7 ImpulseJointSet, IslandManager, MultibodyJointSet, RigidBodyHandle, RigidBodySet,
8 SoftBodyBuilder,
9};
10use crate::geometry::ColliderSet;
11use crate::math::{Pose, Rotation};
12
13impl SoftBodySet {
14 pub fn insert(
18 &mut self,
19 soft_body_builder: SoftBodyBuilder,
20 bodies: &mut RigidBodySet,
21 colliders: &mut ColliderSet,
22 ) -> SoftBodyHandle {
23 let mut soft_body = soft_body_builder.build();
24 soft_body.sleeping = false;
25 soft_body.enabled = true;
26 soft_body.positions_modified = false;
27 soft_body.attachments_modified = !soft_body.attachments.is_empty();
29 let handle = SoftBodyHandle(self.bodies.insert_with(|_| SoftBody {
31 particles: Vec::new(),
32 clusters: Vec::new(),
33 cluster_refs: Vec::new(),
34 root_body: RigidBodyHandle::invalid(),
35 attachments: Vec::new(),
36 sleeping: false,
37 enabled: true,
38 positions_modified: false,
39 attachments_modified: false,
40 edges: Vec::new(),
41 #[cfg(feature = "dim3")]
42 dihedrals: Vec::new(),
43 cells: Vec::new(),
44 boundary: Vec::new(),
45 boundary_closed: false,
46 boundary_element_cells: Vec::new(),
47 material: soft_body.material,
48 cell_model: soft_body.cell_model,
49 #[cfg(feature = "fem")]
50 solver: soft_body.solver,
51 volume_preservation: false,
52 volume_pieces: Vec::new(),
53 volume_factor: 1.0,
54 rest_com: soft_body.rest_com,
55 particle_radius: soft_body.particle_radius,
56 particle_settings: soft_body.particle_settings,
57 num_colors: 0,
58 has_overflow_color: false,
59 modified: false,
60 plastic_flowing: false,
61 rest_fit_pending: false,
62 sleep_speed: 0.0,
63 tearing_pending: false,
64 topology_version: 0,
65 contact_approach_speeds: [None; 2],
66 contact_approach_step_open: false,
67 contact_load: 0.0,
68 load_extra_substeps: 0,
69 origin: None,
70 pieces: Vec::new(),
71 user_data: 0,
72 }));
73
74 soft_body.root_body = spawn_proxy(
75 &soft_body.particle_settings,
76 soft_body.user_data,
77 handle,
78 0,
79 bodies,
80 );
81 let meshes = soft_body_builder.build_meshes(&soft_body);
82 soft_body.clusters = alloc::vec![SoftBodyCluster {
83 particles: (0..soft_body.particles.len() as u32).collect(),
84 proxy: soft_body.root_body,
85 rotation: Rotation::IDENTITY,
86 cell: u32::MAX,
87 shape_matching: soft_body_builder.shape_matching,
88 shape_matching_target: None,
89 prev_shape_matching_target: None,
90 last_gather: Default::default(),
91 shape_impulses: Vec::new(),
92 meshes: meshes.into_iter().map(Some).collect(),
93 }];
94 soft_body.cluster_refs = alloc::vec![1; soft_body.particles.len()];
95 Self::update_cluster_proxies(&mut soft_body, bodies, colliders);
97 let frame = bodies
98 .get(soft_body.root_body)
99 .map(|rb| rb.pos.position)
100 .unwrap_or(Pose::IDENTITY);
101
102 if let Some(template) = soft_body_builder.collider_template.as_ref() {
106 let mut clusters = core::mem::take(&mut soft_body.clusters);
107 for (ci, cluster) in clusters.iter_mut().enumerate() {
108 for (mi, mesh) in cluster.meshes.iter_mut().enumerate() {
109 let Some(mesh) = mesh else { continue };
110 mesh.set_id(SoftMeshId {
111 cluster: ci as u32,
112 mesh: mi as u32,
113 });
114 if !mesh.collision_enabled() {
115 continue;
116 }
117 let Some(co_handle) = spawn_mesh_collider(
118 template,
119 handle,
120 mesh,
121 &soft_body,
122 cluster.proxy,
123 &frame,
124 bodies,
125 colliders,
126 ) else {
127 mesh.collision_enabled = false;
130 continue;
131 };
132 mesh.collider = co_handle;
133 }
134 }
135 soft_body.clusters = clusters;
136 }
137
138 *self.bodies.get_mut(handle.0).unwrap() = soft_body;
139 self.island_events.push(SoftBodyIslandEvent { handle });
140 handle
141 }
142
143 pub fn remove(
145 &mut self,
146 handle: SoftBodyHandle,
147 islands: &mut IslandManager,
148 bodies: &mut RigidBodySet,
149 colliders: &mut ColliderSet,
150 impulse_joints: &mut ImpulseJointSet,
151 multibody_joints: &mut MultibodyJointSet,
152 ) -> Option<SoftBody> {
153 let soft_body = self.bodies.remove(handle.0)?;
154 islands.persistent.unlink_soft_body_attachments(handle);
156 islands.persistent.unlink_soft_body_proxy_chain(handle);
157 self.attached_to_stale |= !soft_body.attachments.is_empty();
158 for cluster in &soft_body.clusters {
159 if cluster.is_live() {
160 bodies.remove(
162 cluster.proxy,
163 islands,
164 colliders,
165 impulse_joints,
166 multibody_joints,
167 self,
168 true,
169 );
170 }
171 }
172 Some(soft_body)
173 }
174}