rapier2d/dynamics/island_manager/
manager.rs1use super::{Island, IslandsOptimizer};
2use crate::dynamics::{
3 ImpulseJointSet, MultibodyJointSet, RigidBodyChanges, RigidBodyHandle, RigidBodyIds,
4 RigidBodySet,
5};
6use crate::geometry::{ColliderSet, NarrowPhase};
7use crate::math::Real;
8use crate::prelude::SleepRootState;
9use crate::utils::DotProduct;
10use std::collections::VecDeque;
11use vec_map::VecMap;
12
13#[derive(Copy, Clone, Debug, PartialEq)]
15#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
16pub(super) struct SleepCandidate(RigidBodyHandle);
17
18#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
33#[derive(Clone, Default)]
34pub struct IslandManager {
35 pub(crate) islands: VecMap<Island>,
36 pub(crate) awake_islands: Vec<usize>,
37 pub(crate) free_islands: Vec<usize>,
39 pub(super) traversal_candidates: VecDeque<SleepCandidate>,
42 pub(super) traversal_timestamp: u32,
43 pub(super) optimizer: IslandsOptimizer,
44 #[cfg_attr(feature = "serde-serialize", serde(skip))]
45 pub(super) stack: Vec<RigidBodyHandle>, }
47
48impl IslandManager {
49 pub fn new() -> Self {
51 Self::default()
52 }
53
54 pub(crate) fn active_islands(&self) -> &[usize] {
55 &self.awake_islands
56 }
57
58 pub(crate) fn rigid_body_removed_or_disabled(
59 &mut self,
60 removed_handle: RigidBodyHandle,
61 removed_ids: &RigidBodyIds,
62 bodies: &mut RigidBodySet,
63 ) {
64 let Some(island) = self.islands.get_mut(removed_ids.active_island_id) else {
65 return;
67 };
68
69 if let Some(body) = bodies.get_mut_internal(removed_handle) {
71 body.ids.active_island_id = usize::MAX;
72 body.ids.active_set_id = usize::MAX;
73 }
74
75 let swapped_handle = island.bodies.last().copied().unwrap_or(removed_handle);
76 island.bodies.swap_remove(removed_ids.active_set_id);
77
78 if swapped_handle != removed_handle {
80 let swapped_body = bodies
81 .get_mut(swapped_handle)
82 .expect("Internal error: bodies must be removed from islands on at a times");
83 swapped_body.ids.active_set_id = removed_ids.active_set_id;
84 }
85
86 if island.bodies.is_empty() {
88 if let Some(awake_id) = island.id_in_awake_list {
89 self.awake_islands.swap_remove(awake_id);
91 if let Some(moved_id) = self.awake_islands.get(awake_id) {
93 self.islands[*moved_id].id_in_awake_list = Some(awake_id);
94 }
95 }
96 self.islands.remove(removed_ids.active_island_id);
97 self.free_islands.push(removed_ids.active_island_id);
98 }
99 }
100
101 pub(crate) fn interaction_started_or_stopped(
102 &mut self,
103 bodies: &mut RigidBodySet,
104 handle1: Option<RigidBodyHandle>,
105 handle2: Option<RigidBodyHandle>,
106 started: bool,
107 wake_up: bool,
108 ) {
109 match (handle1, handle2) {
110 (Some(handle1), Some(handle2)) => {
111 if wake_up {
112 self.wake_up(bodies, handle1, false);
113 self.wake_up(bodies, handle2, false);
114 }
115
116 if started {
117 if let (Some(rb1), Some(rb2)) = (bodies.get(handle1), bodies.get(handle2)) {
118 assert!(rb1.is_fixed() || rb1.ids.active_island_id != usize::MAX);
119 assert!(rb2.is_fixed() || rb2.ids.active_island_id != usize::MAX);
120
121 if !rb1.is_fixed()
123 && !rb2.is_fixed()
124 && rb1.ids.active_island_id != rb2.ids.active_island_id
125 {
126 self.merge_islands(
127 bodies,
128 rb1.ids.active_island_id,
129 rb2.ids.active_island_id,
130 );
131 }
132 }
133 }
134 }
135 (Some(handle1), None) => {
136 if wake_up {
137 self.wake_up(bodies, handle1, false);
139 }
140 }
141 (None, Some(handle2)) => {
142 if wake_up {
143 self.wake_up(bodies, handle2, false);
145 }
146 }
147 (None, None) => { }
148 }
149 }
150
151 pub(crate) fn island(&self, island_id: usize) -> &Island {
152 &self.islands[island_id]
153 }
154
155 #[inline]
157 pub fn active_bodies(&self) -> impl Iterator<Item = RigidBodyHandle> + '_ {
158 self.awake_islands
159 .iter()
160 .flat_map(|i| self.islands[*i].bodies.iter().copied())
161 }
162
163 pub(crate) fn rigid_body_updated(
164 &mut self,
165 handle: RigidBodyHandle,
166 bodies: &mut RigidBodySet,
167 ) {
168 let Some(rb) = bodies.get_mut(handle) else {
169 return;
170 };
171
172 if rb.is_fixed() {
173 return;
174 }
175
176 if rb.ids.active_island_id == usize::MAX {
178 let insert_in_last_island = self.awake_islands.last().map(|id| {
182 self.islands[*id].bodies.len() < self.optimizer.min_island_size
183 && self.islands[*id].is_sleeping() == rb.is_sleeping()
184 });
185 if !rb.is_sleeping() && insert_in_last_island == Some(true) {
188 let id = *self.awake_islands.last().unwrap_or_else(|| unreachable!());
189 let target_island = &mut self.islands[id];
190
191 rb.ids.active_island_id = id;
192 rb.ids.active_set_id = target_island.bodies.len();
193 target_island.bodies.push(handle);
194 } else {
195 let mut new_island = Island::singleton(handle, rb);
196 let id = self.free_islands.pop().unwrap_or(self.islands.len());
197
198 if !rb.is_sleeping() {
199 new_island.id_in_awake_list = Some(self.awake_islands.len());
200 self.awake_islands.push(id);
201 }
202
203 self.islands.insert(id, new_island);
204 rb.ids.active_island_id = id;
205 rb.ids.active_set_id = 0;
206 }
207 }
208
209 if (rb.changes.contains(RigidBodyChanges::SLEEP)
212 || rb.changes.contains(RigidBodyChanges::TYPE))
213 && rb.is_enabled()
214 && !rb.activation.sleeping
216 {
217 self.wake_up(bodies, handle, false);
218 }
219 }
220
221 pub(crate) fn update_islands(
222 &mut self,
223 dt: Real,
224 length_unit: Real,
225 bodies: &mut RigidBodySet,
226 colliders: &ColliderSet,
227 narrow_phase: &NarrowPhase,
228 impulse_joints: &ImpulseJointSet,
229 multibody_joints: &MultibodyJointSet,
230 ) {
231 for handle in self
235 .awake_islands
236 .iter()
237 .flat_map(|i| self.islands[*i].bodies.iter().copied())
238 {
239 let Some(rb) = bodies.get_mut_internal(handle) else {
240 continue;
242 };
243 let sq_linvel = rb.vels.linvel.length_squared();
244 let sq_angvel = rb.vels.angvel.gdot(rb.vels.angvel);
245 rb.activation
246 .update_energy(rb.body_type, length_unit, sq_linvel, sq_angvel, dt);
247
248 let can_sleep_now = rb.activation.is_eligible_for_sleep();
249
250 if can_sleep_now && rb.activation.sleep_root_state == SleepRootState::Unknown {
253 self.traversal_candidates.push_back(SleepCandidate(handle));
255 rb.activation.sleep_root_state = SleepRootState::TraversalPending;
256 } else if !can_sleep_now {
257 rb.activation.sleep_root_state = SleepRootState::Unknown;
258 }
259 }
260 let mut cost = 0;
263
264 const MAX_PER_FRAME_COST: usize = 1000; while let Some(sleep_root) = self.traversal_candidates.pop_front() {
269 cost += self.extract_sleeping_island(
270 bodies,
271 colliders,
272 impulse_joints,
273 multibody_joints,
274 narrow_phase,
275 sleep_root.0,
276 );
277
278 if cost > MAX_PER_FRAME_COST {
279 break;
281 }
282 }
283
284 self.update_optimizer(
285 bodies,
286 colliders,
287 impulse_joints,
288 multibody_joints,
289 narrow_phase,
290 );
291 }
296}