1use crate::math::Fix128;
16use crate::solver::RigidBody;
17
18#[cfg(not(feature = "std"))]
19use alloc::vec;
20#[cfg(not(feature = "std"))]
21use alloc::vec::Vec;
22
23#[derive(Clone, Copy, Debug, PartialEq, Eq)]
25pub enum SleepState {
26 Awake,
28 Sleeping,
30}
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
34pub struct SleepData {
35 pub state: SleepState,
37 pub idle_frames: u32,
39}
40
41impl SleepData {
42 #[must_use]
44 pub const fn new() -> Self {
45 Self {
46 state: SleepState::Awake,
47 idle_frames: 0,
48 }
49 }
50
51 #[inline]
53 #[must_use]
54 pub fn is_sleeping(&self) -> bool {
55 self.state == SleepState::Sleeping
56 }
57
58 #[inline]
60 pub fn wake(&mut self) {
61 self.state = SleepState::Awake;
62 self.idle_frames = 0;
63 }
64}
65
66impl Default for SleepData {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72#[derive(Clone, Copy, Debug, PartialEq, Eq)]
74pub struct SleepConfig {
75 pub linear_threshold: Fix128,
77 pub angular_threshold: Fix128,
79 pub frames_to_sleep: u32,
81}
82
83impl Default for SleepConfig {
84 fn default() -> Self {
85 Self {
86 linear_threshold: Fix128::from_ratio(1, 100), angular_threshold: Fix128::from_ratio(1, 100), frames_to_sleep: 60, }
90 }
91}
92
93#[derive(Clone, Debug)]
95pub struct Island {
96 pub bodies: Vec<usize>,
98 pub all_sleeping: bool,
100}
101
102pub struct IslandManager {
104 parent: Vec<usize>,
106 rank: Vec<u32>,
108 pub sleep_data: Vec<SleepData>,
110 pub config: SleepConfig,
112}
113
114impl IslandManager {
115 #[must_use]
117 pub fn new(num_bodies: usize, config: SleepConfig) -> Self {
118 let mut parent = Vec::with_capacity(num_bodies);
119 let rank = vec![0u32; num_bodies];
120 let sleep_data = vec![SleepData::new(); num_bodies];
121 for i in 0..num_bodies {
122 parent.push(i);
123 }
124 Self {
125 parent,
126 rank,
127 sleep_data,
128 config,
129 }
130 }
131
132 pub fn resize(&mut self, num_bodies: usize) {
134 while self.parent.len() < num_bodies {
135 let idx = self.parent.len();
136 self.parent.push(idx);
137 self.rank.push(0);
138 self.sleep_data.push(SleepData::new());
139 }
140 }
141
142 pub fn reset_unions(&mut self) {
144 for i in 0..self.parent.len() {
145 self.parent[i] = i;
146 self.rank[i] = 0;
147 }
148 }
149
150 pub fn find(&mut self, mut x: usize) -> usize {
152 while self.parent[x] != x {
153 self.parent[x] = self.parent[self.parent[x]]; x = self.parent[x];
155 }
156 x
157 }
158
159 pub fn union(&mut self, a: usize, b: usize) {
161 let ra = self.find(a);
162 let rb = self.find(b);
163 if ra == rb {
164 return;
165 }
166 match self.rank[ra].cmp(&self.rank[rb]) {
168 core::cmp::Ordering::Less => self.parent[ra] = rb,
169 core::cmp::Ordering::Greater => self.parent[rb] = ra,
170 core::cmp::Ordering::Equal => {
171 self.parent[rb] = ra;
172 self.rank[ra] += 1;
173 }
174 }
175 }
176
177 pub fn build_islands(&mut self) -> Vec<Island> {
179 let n = self.parent.len();
180 let mut island_map: Vec<Option<usize>> = vec![None; n];
181 let mut islands: Vec<Island> = Vec::new();
182
183 for i in 0..n {
184 let root = self.find(i);
185 let island_idx = island_map[root].unwrap_or_else(|| {
186 let idx = islands.len();
187 island_map[root] = Some(idx);
188 islands.push(Island {
189 bodies: Vec::new(),
190 all_sleeping: true,
191 });
192 idx
193 });
194 islands[island_idx].bodies.push(i);
195 if !self.sleep_data[i].is_sleeping() {
196 islands[island_idx].all_sleeping = false;
197 }
198 }
199
200 islands
201 }
202
203 pub fn update_sleep(&mut self, bodies: &[RigidBody]) {
205 for (i, body) in bodies.iter().enumerate() {
206 if i >= self.sleep_data.len() {
207 break;
208 }
209 self.update_sleep_body(i, body);
210 }
211 }
212
213 pub(crate) fn update_sleep_body(&mut self, i: usize, body: &RigidBody) {
215 if body.is_static() {
217 self.sleep_data[i].state = SleepState::Sleeping;
218 return;
219 }
220
221 let linear_speed = body.velocity.length();
222 let angular_speed = body.angular_velocity.length();
223
224 let is_idle = linear_speed < self.config.linear_threshold
225 && angular_speed < self.config.angular_threshold;
226
227 if is_idle {
228 self.mark_idle(i);
229 } else {
230 self.sleep_data[i].state = SleepState::Awake;
231 self.sleep_data[i].idle_frames = 0;
232 }
233 }
234
235 pub(crate) fn update_sleep_idle(&mut self, i: usize, is_static: bool) {
238 if is_static {
239 self.sleep_data[i].state = SleepState::Sleeping;
240 } else {
241 self.mark_idle(i);
242 }
243 }
244
245 #[inline]
246 fn mark_idle(&mut self, i: usize) {
247 self.sleep_data[i].idle_frames += 1;
248 if self.sleep_data[i].idle_frames >= self.config.frames_to_sleep {
249 self.sleep_data[i].state = SleepState::Sleeping;
250 }
251 }
252
253 pub fn wake_island(&mut self, body_index: usize) {
255 let root = self.find(body_index);
256 for i in 0..self.parent.len() {
257 if self.find(i) == root {
258 self.sleep_data[i].wake();
259 }
260 }
261 }
262
263 #[inline]
265 pub fn wake_body(&mut self, body_index: usize) {
266 if body_index < self.sleep_data.len() {
267 self.sleep_data[body_index].wake();
268 }
269 }
270
271 #[inline]
273 pub fn is_sleeping(&self, body_index: usize) -> bool {
274 self.sleep_data
275 .get(body_index)
276 .is_some_and(SleepData::is_sleeping)
277 }
278
279 #[must_use]
281 pub fn sleeping_count(&self) -> usize {
282 self.sleep_data.iter().filter(|d| d.is_sleeping()).count()
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289 use crate::math::Vec3Fix;
290
291 #[test]
292 fn test_union_find() {
293 let config = SleepConfig::default();
294 let mut mgr = IslandManager::new(5, config);
295
296 mgr.union(0, 1);
297 mgr.union(2, 3);
298
299 assert_eq!(mgr.find(0), mgr.find(1));
300 assert_ne!(mgr.find(0), mgr.find(2));
301 assert_eq!(mgr.find(2), mgr.find(3));
302 }
303
304 #[test]
305 fn test_build_islands() {
306 let config = SleepConfig::default();
307 let mut mgr = IslandManager::new(5, config);
308
309 mgr.union(0, 1);
310 mgr.union(2, 3);
311 let islands = mgr.build_islands();
314 assert_eq!(islands.len(), 3, "Should have 3 islands");
315
316 let total_bodies: usize = islands.iter().map(|i| i.bodies.len()).sum();
317 assert_eq!(total_bodies, 5);
318 }
319
320 #[test]
321 fn test_sleep_after_threshold() {
322 let config = SleepConfig {
323 frames_to_sleep: 3,
324 ..Default::default()
325 };
326 let mut mgr = IslandManager::new(1, config);
327
328 let still_body = RigidBody::new_static(Vec3Fix::ZERO);
329 let bodies = [still_body];
330
331 for _ in 0..3 {
333 mgr.update_sleep(&bodies);
334 }
335
336 assert!(mgr.is_sleeping(0));
337 }
338
339 #[test]
340 fn test_wake_on_motion() {
341 let config = SleepConfig {
342 linear_threshold: Fix128::from_ratio(1, 100),
343 frames_to_sleep: 2,
344 ..Default::default()
345 };
346 let mut mgr = IslandManager::new(1, config);
347
348 let still_body = RigidBody::new(Vec3Fix::ZERO, Fix128::ONE);
350 mgr.update_sleep(&[still_body]);
351 mgr.update_sleep(&[still_body]);
352 assert!(mgr.is_sleeping(0));
353
354 let mut moving_body = RigidBody::new(Vec3Fix::ZERO, Fix128::ONE);
356 moving_body.velocity = Vec3Fix::from_int(10, 0, 0);
357 mgr.update_sleep(&[moving_body]);
358 assert!(!mgr.is_sleeping(0));
359 }
360
361 #[test]
362 fn test_wake_island() {
363 let config = SleepConfig::default();
364 let mut mgr = IslandManager::new(3, config);
365
366 for d in &mut mgr.sleep_data {
368 d.state = SleepState::Sleeping;
369 }
370
371 mgr.union(0, 1);
372
373 mgr.wake_island(0);
375
376 assert!(!mgr.is_sleeping(0));
377 assert!(!mgr.is_sleeping(1));
378 assert!(mgr.is_sleeping(2)); }
380
381 #[test]
382 fn test_resize() {
383 let config = SleepConfig::default();
384 let mut mgr = IslandManager::new(2, config);
385 mgr.resize(5);
386
387 assert_eq!(mgr.parent.len(), 5);
388 assert_eq!(mgr.sleep_data.len(), 5);
389 }
390
391 #[test]
392 fn test_sleeping_count() {
393 let config = SleepConfig::default();
394 let mut mgr = IslandManager::new(5, config);
395
396 mgr.sleep_data[0].state = SleepState::Sleeping;
397 mgr.sleep_data[2].state = SleepState::Sleeping;
398 mgr.sleep_data[4].state = SleepState::Sleeping;
399
400 assert_eq!(mgr.sleeping_count(), 3);
401 }
402}