rapier2d/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))]
24#[derive(Clone, Default)]
25pub struct IslandManager {
26 pub(crate) active_set: Vec<RigidBodyHandle>,
27 pub(crate) active_islands: Vec<usize>,
28 pub(crate) active_islands_additional_solver_iterations: Vec<usize>,
29 active_set_timestamp: u32,
30 #[cfg_attr(feature = "serde-serialize", serde(skip))]
31 can_sleep: Vec<RigidBodyHandle>, #[cfg_attr(feature = "serde-serialize", serde(skip))]
33 stack: Vec<RigidBodyHandle>, }
35
36impl IslandManager {
37 pub fn new() -> Self {
39 Self {
40 active_set: vec![],
41 active_islands: vec![],
42 active_islands_additional_solver_iterations: vec![],
43 active_set_timestamp: 0,
44 can_sleep: vec![],
45 stack: vec![],
46 }
47 }
48
49 pub(crate) fn num_islands(&self) -> usize {
50 self.active_islands.len().saturating_sub(1)
51 }
52
53 pub fn cleanup_removed_rigid_bodies(&mut self, bodies: &mut RigidBodySet) {
55 let mut i = 0;
56
57 while i < self.active_set.len() {
58 let handle = self.active_set[i];
59 if bodies.get(handle).is_none() {
60 self.active_set.swap_remove(i);
62
63 if i < self.active_set.len() {
64 if let Some(swapped_rb) = bodies.get_mut_internal(self.active_set[i]) {
66 swapped_rb.ids.active_set_id = i;
67 }
68 }
69 } else {
70 i += 1;
71 }
72 }
73 }
74
75 pub(crate) fn rigid_body_removed(
76 &mut self,
77 removed_handle: RigidBodyHandle,
78 removed_ids: &RigidBodyIds,
79 bodies: &mut RigidBodySet,
80 ) {
81 if self.active_set.get(removed_ids.active_set_id) == Some(&removed_handle) {
82 self.active_set.swap_remove(removed_ids.active_set_id);
83
84 if let Some(replacement) = self
85 .active_set
86 .get(removed_ids.active_set_id)
87 .and_then(|h| bodies.get_mut_internal(*h))
88 {
89 replacement.ids.active_set_id = removed_ids.active_set_id;
90 }
91 }
92 }
93
94 pub fn wake_up(&mut self, bodies: &mut RigidBodySet, handle: RigidBodyHandle, strong: bool) {
117 if bodies.get(handle).map(|rb| rb.body_type()) == Some(RigidBodyType::Dynamic) {
121 let rb = bodies.index_mut_internal(handle);
122
123 if !rb.changes.contains(RigidBodyChanges::SLEEP) {
126 rb.activation.wake_up(strong);
127
128 if rb.is_enabled() && self.active_set.get(rb.ids.active_set_id) != Some(&handle) {
129 rb.ids.active_set_id = self.active_set.len();
130 self.active_set.push(handle);
131 }
132 }
133 }
134 }
135
136 pub(crate) fn active_island(&self, island_id: usize) -> &[RigidBodyHandle] {
137 let island_range = self.active_islands[island_id]..self.active_islands[island_id + 1];
138 &self.active_set[island_range]
139 }
140
141 pub(crate) fn active_island_additional_solver_iterations(&self, island_id: usize) -> usize {
142 self.active_islands_additional_solver_iterations[island_id]
143 }
144
145 #[inline]
147 pub fn active_bodies(&self) -> &[RigidBodyHandle] {
148 &self.active_set
149 }
150
151 #[cfg(feature = "parallel")]
152 #[allow(dead_code)] pub(crate) fn active_island_range(&self, island_id: usize) -> std::ops::Range<usize> {
154 self.active_islands[island_id]..self.active_islands[island_id + 1]
155 }
156
157 pub(crate) fn update_active_set_with_contacts(
158 &mut self,
159 dt: Real,
160 length_unit: Real,
161 bodies: &mut RigidBodySet,
162 colliders: &ColliderSet,
163 narrow_phase: &NarrowPhase,
164 impulse_joints: &ImpulseJointSet,
165 multibody_joints: &MultibodyJointSet,
166 min_island_size: usize,
167 ) {
168 assert!(
169 min_island_size > 0,
170 "The minimum island size must be at least 1."
171 );
172
173 self.active_set_timestamp += 1;
177 self.stack.clear();
178 self.can_sleep.clear();
179
180 for h in self.active_set.drain(..).rev() {
185 let can_sleep = &mut self.can_sleep;
186 let stack = &mut self.stack;
187
188 let rb = bodies.index_mut_internal(h);
189 let sq_linvel = rb.vels.linvel.norm_squared();
190 let sq_angvel = rb.vels.angvel.gdot(rb.vels.angvel);
191
192 update_energy(
193 &mut rb.activation,
194 rb.body_type,
195 length_unit,
196 sq_linvel,
197 sq_angvel,
198 dt,
199 );
200
201 if rb.activation.time_since_can_sleep >= rb.activation.time_until_sleep {
202 rb.activation.sleeping = true;
206 can_sleep.push(h);
207 } else {
208 stack.push(h);
209 }
210 }
211
212 #[inline]
214 fn push_contacting_bodies(
215 rb_colliders: &RigidBodyColliders,
216 colliders: &ColliderSet,
217 narrow_phase: &NarrowPhase,
218 stack: &mut Vec<RigidBodyHandle>,
219 ) {
220 for collider_handle in &rb_colliders.0 {
221 for inter in narrow_phase.contact_pairs_with(*collider_handle) {
222 for manifold in &inter.manifolds {
223 if !manifold.data.solver_contacts.is_empty() {
224 let other = crate::utils::select_other(
225 (inter.collider1, inter.collider2),
226 *collider_handle,
227 );
228 if let Some(other_body) = colliders[other].parent {
229 stack.push(other_body.handle);
230 }
231 break;
232 }
233 }
234 }
235 }
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
262 || !rb.is_dynamic_or_kinematic()
263 {
264 continue;
267 }
268
269 if self.stack.len() < island_marker {
270 if additional_solver_iterations != rb.additional_solver_iterations
271 || self.active_set.len() - *self.active_islands.last().unwrap()
272 >= min_island_size
273 {
274 self.active_islands_additional_solver_iterations
276 .push(additional_solver_iterations);
277 self.active_islands.push(self.active_set.len());
278 additional_solver_iterations = 0;
279 }
280
281 island_marker = self.stack.len();
282 }
283
284 additional_solver_iterations =
285 additional_solver_iterations.max(rb.additional_solver_iterations);
286
287 push_contacting_bodies(&rb.colliders, colliders, narrow_phase, &mut self.stack);
290
291 for inter in impulse_joints.attached_enabled_joints(handle) {
292 let other = crate::utils::select_other((inter.0, inter.1), handle);
293 self.stack.push(other);
294 }
295
296 for other in multibody_joints.bodies_attached_with_enabled_joint(handle) {
297 self.stack.push(other);
298 }
299
300 rb.activation.wake_up(false);
301 rb.ids.active_island_id = self.active_islands.len() - 1;
302 rb.ids.active_set_id = self.active_set.len();
303 rb.ids.active_set_offset =
304 (rb.ids.active_set_id - self.active_islands[rb.ids.active_island_id]) as u32;
305 rb.ids.active_set_timestamp = self.active_set_timestamp;
306
307 self.active_set.push(handle);
308 }
309
310 self.active_islands_additional_solver_iterations
311 .push(additional_solver_iterations);
312 self.active_islands.push(self.active_set.len());
313 for handle in &self.can_sleep {
321 let rb = bodies.index_mut_internal(*handle);
322 if rb.activation.sleeping {
323 rb.vels = RigidBodyVelocity::zero();
324 rb.activation.sleep();
325 }
326 }
327 }
328}
329
330fn update_energy(
331 activation: &mut RigidBodyActivation,
332 body_type: RigidBodyType,
333 length_unit: Real,
334 sq_linvel: Real,
335 sq_angvel: Real,
336 dt: Real,
337) {
338 let can_sleep = match body_type {
339 RigidBodyType::Dynamic => {
340 let linear_threshold = activation.normalized_linear_threshold * length_unit;
341 sq_linvel < linear_threshold * linear_threshold.abs()
342 && sq_angvel < activation.angular_threshold * activation.angular_threshold.abs()
343 }
344 RigidBodyType::KinematicPositionBased | RigidBodyType::KinematicVelocityBased => {
345 sq_linvel == 0.0 && sq_angvel == 0.0
348 }
349 RigidBodyType::Fixed => true,
350 };
351
352 if can_sleep {
353 activation.time_since_can_sleep += dt;
354 } else {
355 activation.time_since_can_sleep = 0.0;
356 }
357}