rapier3d/dynamics/
island_manager.rs1use crate::dynamics::{
2 ImpulseJointSet, MultibodyJointSet, RigidBodyActivation, RigidBodyChanges, RigidBodyColliders,
3 RigidBodyHandle, RigidBodyIds, RigidBodySet, RigidBodyType, RigidBodyVelocity,
4};
5use crate::geometry::{ColliderSet, NarrowPhase};
6use crate::math::Real;
7use crate::utils::SimdDot;
8
9#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
12#[derive(Clone, Default)]
13pub struct IslandManager {
14 pub(crate) active_dynamic_set: Vec<RigidBodyHandle>,
15 pub(crate) active_kinematic_set: Vec<RigidBodyHandle>,
16 pub(crate) active_islands: Vec<usize>,
17 pub(crate) active_islands_additional_solver_iterations: Vec<usize>,
18 active_set_timestamp: u32,
19 #[cfg_attr(feature = "serde-serialize", serde(skip))]
20 can_sleep: Vec<RigidBodyHandle>, #[cfg_attr(feature = "serde-serialize", serde(skip))]
22 stack: Vec<RigidBodyHandle>, }
24
25impl IslandManager {
26 pub fn new() -> Self {
28 Self {
29 active_dynamic_set: vec![],
30 active_kinematic_set: vec![],
31 active_islands: vec![],
32 active_islands_additional_solver_iterations: vec![],
33 active_set_timestamp: 0,
34 can_sleep: vec![],
35 stack: vec![],
36 }
37 }
38
39 pub(crate) fn num_islands(&self) -> usize {
40 self.active_islands.len().saturating_sub(1)
41 }
42
43 pub fn cleanup_removed_rigid_bodies(&mut self, bodies: &mut RigidBodySet) {
45 let mut active_sets = [&mut self.active_kinematic_set, &mut self.active_dynamic_set];
46
47 for active_set in &mut active_sets {
48 let mut i = 0;
49
50 while i < active_set.len() {
51 let handle = active_set[i];
52 if bodies.get(handle).is_none() {
53 active_set.swap_remove(i);
55
56 if i < active_set.len() {
57 if let Some(swapped_rb) = bodies.get_mut_internal(active_set[i]) {
59 swapped_rb.ids.active_set_id = i;
60 }
61 }
62 } else {
63 i += 1;
64 }
65 }
66 }
67 }
68
69 pub(crate) fn rigid_body_removed(
70 &mut self,
71 removed_handle: RigidBodyHandle,
72 removed_ids: &RigidBodyIds,
73 bodies: &mut RigidBodySet,
74 ) {
75 let mut active_sets = [&mut self.active_kinematic_set, &mut self.active_dynamic_set];
76
77 for active_set in &mut active_sets {
78 if active_set.get(removed_ids.active_set_id) == Some(&removed_handle) {
79 active_set.swap_remove(removed_ids.active_set_id);
80
81 if let Some(replacement) = active_set
82 .get(removed_ids.active_set_id)
83 .and_then(|h| bodies.get_mut_internal(*h))
84 {
85 replacement.ids.active_set_id = removed_ids.active_set_id;
86 }
87 }
88 }
89 }
90
91 pub fn wake_up(&mut self, bodies: &mut RigidBodySet, handle: RigidBodyHandle, strong: bool) {
96 if bodies.get(handle).map(|rb| rb.body_type()) == Some(RigidBodyType::Dynamic) {
100 let rb = bodies.index_mut_internal(handle);
101
102 if !rb.changes.contains(RigidBodyChanges::SLEEP) {
105 rb.activation.wake_up(strong);
106
107 if rb.is_enabled()
108 && self.active_dynamic_set.get(rb.ids.active_set_id) != Some(&handle)
109 {
110 rb.ids.active_set_id = self.active_dynamic_set.len();
111 self.active_dynamic_set.push(handle);
112 }
113 }
114 }
115 }
116
117 pub fn active_kinematic_bodies(&self) -> &[RigidBodyHandle] {
119 &self.active_kinematic_set[..]
120 }
121
122 pub fn active_dynamic_bodies(&self) -> &[RigidBodyHandle] {
124 &self.active_dynamic_set[..]
125 }
126
127 pub(crate) fn active_island(&self, island_id: usize) -> &[RigidBodyHandle] {
128 let island_range = self.active_islands[island_id]..self.active_islands[island_id + 1];
129 &self.active_dynamic_set[island_range]
130 }
131
132 pub(crate) fn active_island_additional_solver_iterations(&self, island_id: usize) -> usize {
133 self.active_islands_additional_solver_iterations[island_id]
134 }
135
136 #[inline(always)]
137 pub(crate) fn iter_active_bodies(&self) -> impl Iterator<Item = RigidBodyHandle> + '_ {
138 self.active_dynamic_set
139 .iter()
140 .copied()
141 .chain(self.active_kinematic_set.iter().copied())
142 }
143
144 #[cfg(feature = "parallel")]
145 #[allow(dead_code)] pub(crate) fn active_island_range(&self, island_id: usize) -> std::ops::Range<usize> {
147 self.active_islands[island_id]..self.active_islands[island_id + 1]
148 }
149
150 pub(crate) fn update_active_set_with_contacts(
151 &mut self,
152 dt: Real,
153 length_unit: Real,
154 bodies: &mut RigidBodySet,
155 colliders: &ColliderSet,
156 narrow_phase: &NarrowPhase,
157 impulse_joints: &ImpulseJointSet,
158 multibody_joints: &MultibodyJointSet,
159 min_island_size: usize,
160 ) {
161 assert!(
162 min_island_size > 0,
163 "The minimum island size must be at least 1."
164 );
165
166 self.active_set_timestamp += 1;
170 self.stack.clear();
171 self.can_sleep.clear();
172
173 for h in self.active_dynamic_set.drain(..).rev() {
178 let can_sleep = &mut self.can_sleep;
179 let stack = &mut self.stack;
180
181 let rb = bodies.index_mut_internal(h);
182 let sq_linvel = rb.vels.linvel.norm_squared();
183 let sq_angvel = rb.vels.angvel.gdot(rb.vels.angvel);
184
185 update_energy(length_unit, &mut rb.activation, sq_linvel, sq_angvel, dt);
186
187 if rb.activation.time_since_can_sleep >= rb.activation.time_until_sleep {
188 rb.activation.sleeping = true;
192 can_sleep.push(h);
193 } else {
194 stack.push(h);
195 }
196 }
197
198 #[inline(always)]
200 fn push_contacting_bodies(
201 rb_colliders: &RigidBodyColliders,
202 colliders: &ColliderSet,
203 narrow_phase: &NarrowPhase,
204 stack: &mut Vec<RigidBodyHandle>,
205 ) {
206 for collider_handle in &rb_colliders.0 {
207 for inter in narrow_phase.contact_pairs_with(*collider_handle) {
208 for manifold in &inter.manifolds {
209 if !manifold.data.solver_contacts.is_empty() {
210 let other = crate::utils::select_other(
211 (inter.collider1, inter.collider2),
212 *collider_handle,
213 );
214 if let Some(other_body) = colliders[other].parent {
215 stack.push(other_body.handle);
216 }
217 break;
218 }
219 }
220 }
221 }
222 }
223
224 for h in self.active_kinematic_set.iter() {
227 let rb = &bodies[*h];
228
229 if rb.vels.is_zero() {
230 continue;
233 }
234
235 push_contacting_bodies(&rb.colliders, colliders, narrow_phase, &mut self.stack);
236 }
237
238 self.active_islands_additional_solver_iterations.clear();
244 self.active_islands.clear();
245 self.active_islands.push(0);
246
247 let mut island_marker = self.stack.len().saturating_sub(1);
249
250 let mut additional_solver_iterations = 0;
257
258 while let Some(handle) = self.stack.pop() {
259 let rb = bodies.index_mut_internal(handle);
260
261 if rb.ids.active_set_timestamp == self.active_set_timestamp || !rb.is_dynamic() {
262 continue;
265 }
266
267 if self.stack.len() < island_marker {
268 if additional_solver_iterations != rb.additional_solver_iterations
269 || self.active_dynamic_set.len() - *self.active_islands.last().unwrap()
270 >= min_island_size
271 {
272 self.active_islands_additional_solver_iterations
274 .push(additional_solver_iterations);
275 self.active_islands.push(self.active_dynamic_set.len());
276 additional_solver_iterations = 0;
277 }
278
279 island_marker = self.stack.len();
280 }
281
282 additional_solver_iterations =
283 additional_solver_iterations.max(rb.additional_solver_iterations);
284
285 push_contacting_bodies(&rb.colliders, colliders, narrow_phase, &mut self.stack);
288
289 for inter in impulse_joints.attached_enabled_joints(handle) {
290 let other = crate::utils::select_other((inter.0, inter.1), handle);
291 self.stack.push(other);
292 }
293
294 for other in multibody_joints.bodies_attached_with_enabled_joint(handle) {
295 self.stack.push(other);
296 }
297
298 rb.activation.wake_up(false);
299 rb.ids.active_island_id = self.active_islands.len() - 1;
300 rb.ids.active_set_id = self.active_dynamic_set.len();
301 rb.ids.active_set_offset =
302 rb.ids.active_set_id - self.active_islands[rb.ids.active_island_id];
303 rb.ids.active_set_timestamp = self.active_set_timestamp;
304
305 self.active_dynamic_set.push(handle);
306 }
307
308 self.active_islands_additional_solver_iterations
309 .push(additional_solver_iterations);
310 self.active_islands.push(self.active_dynamic_set.len());
311 for handle in &self.can_sleep {
319 let rb = bodies.index_mut_internal(*handle);
320 if rb.activation.sleeping {
321 rb.vels = RigidBodyVelocity::zero();
322 rb.activation.sleep();
323 }
324 }
325 }
326}
327
328fn update_energy(
329 length_unit: Real,
330 activation: &mut RigidBodyActivation,
331 sq_linvel: Real,
332 sq_angvel: Real,
333 dt: Real,
334) {
335 let linear_threshold = activation.normalized_linear_threshold * length_unit;
336 if sq_linvel < linear_threshold * linear_threshold.abs()
337 && sq_angvel < activation.angular_threshold * activation.angular_threshold.abs()
338 {
339 activation.time_since_can_sleep += dt;
340 } else {
341 activation.time_since_can_sleep = 0.0;
342 }
343}