1mod sleeping;
46
47#[expect(deprecated)]
48pub use sleeping::{
49 IslandSleepingPlugin, SleepBody, SleepIslands, WakeBody, WakeIslands, WakeUpBody,
50};
51
52use bevy::{
53 ecs::{entity_disabling::Disabled, lifecycle::HookContext, world::DeferredWorld},
54 prelude::*,
55};
56use slab::Slab;
57
58use crate::{
59 collision::contact_types::{ContactGraphInternal, ContactId},
60 dynamics::solver::{
61 joint_graph::{JointGraph, JointId},
62 solver_body::SolverBody,
63 },
64 prelude::{
65 ContactGraph, PhysicsSchedule, RigidBody, RigidBodyColliders, RigidBodyDisabled,
66 SolverSystems,
67 },
68};
69
70pub struct IslandPlugin;
74
75impl Plugin for IslandPlugin {
76 fn build(&self, app: &mut App) {
77 app.init_resource::<PhysicsIslands>();
78
79 app.register_required_components::<SolverBody, BodyIslandNode>();
81
82 app.add_observer(
85 |trigger: On<Replace, RigidBodyDisabled>,
86 rb_query: Query<&RigidBody>,
87 mut commands: Commands| {
88 let Ok(rb) = rb_query.get(trigger.entity) else {
89 return;
90 };
91 if rb.is_dynamic() || rb.is_kinematic() {
92 commands
93 .entity(trigger.entity)
94 .try_insert(BodyIslandNode::default());
95 }
96 },
97 );
98 app.add_observer(
99 |trigger: On<Replace, Disabled>,
100 rb_query: Query<
101 &RigidBody,
102 (
103 With<Disabled>,
106 Without<RigidBodyDisabled>,
107 ),
108 >,
109 mut commands: Commands| {
110 let Ok(rb) = rb_query.get(trigger.entity) else {
111 return;
112 };
113 if rb.is_dynamic() || rb.is_kinematic() {
114 commands
115 .entity(trigger.entity)
116 .try_insert(BodyIslandNode::default());
117 }
118 },
119 );
120
121 app.add_observer(|trigger: On<Remove, RigidBody>, mut commands: Commands| {
127 commands
128 .entity(trigger.entity)
129 .try_remove::<BodyIslandNode>();
130 });
131 app.add_observer(
132 |trigger: On<Insert, (Disabled, RigidBodyDisabled)>,
133 query: Query<&RigidBody, Or<(With<Disabled>, Without<Disabled>)>>,
134 mut commands: Commands| {
135 if query.contains(trigger.entity) {
136 commands
137 .entity(trigger.entity)
138 .try_remove::<BodyIslandNode>();
139 }
140 },
141 );
142 app.add_observer(
143 |trigger: On<Insert, RigidBody>, query: Query<&RigidBody>, mut commands: Commands| {
144 if let Ok(rb) = query.get(trigger.entity)
145 && rb.is_static()
146 {
147 commands
148 .entity(trigger.entity)
149 .try_remove::<BodyIslandNode>();
150 }
151 },
152 );
153
154 app.add_systems(
155 PhysicsSchedule,
156 split_island.in_set(SolverSystems::Finalize),
157 );
158 }
159}
160
161fn split_island(
162 mut islands: ResMut<PhysicsIslands>,
163 mut body_islands: Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
164 body_colliders: Query<&RigidBodyColliders>,
165 mut contact_graph: ResMut<ContactGraph>,
166 mut joint_graph: ResMut<JointGraph>,
167) {
168 if let Some(island_id) = islands.split_candidate {
170 islands.split_island(
171 island_id,
172 &mut body_islands,
173 &body_colliders,
174 &mut contact_graph,
175 &mut joint_graph,
176 );
177 }
178}
179
180#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Reflect)]
182#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
183#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
184#[reflect(Debug, PartialEq)]
185pub struct IslandId(pub u32);
186
187impl IslandId {
188 pub const PLACEHOLDER: Self = Self(u32::MAX);
190}
191
192impl core::fmt::Display for IslandId {
193 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
194 write!(f, "IslandId({})", self.0)
195 }
196}
197
198#[derive(Clone, Debug, PartialEq)]
213pub struct PhysicsIsland {
214 pub(crate) id: IslandId,
215
216 pub(crate) head_body: Option<Entity>,
217 pub(crate) tail_body: Option<Entity>,
218 pub(crate) body_count: u32,
219
220 pub(crate) head_contact: Option<ContactId>,
221 pub(crate) tail_contact: Option<ContactId>,
222 pub(crate) contact_count: u32,
223
224 pub(crate) head_joint: Option<JointId>,
225 pub(crate) tail_joint: Option<JointId>,
226 pub(crate) joint_count: u32,
227
228 pub(crate) sleep_timer: f32,
229 pub(crate) is_sleeping: bool,
230
231 pub(crate) constraints_removed: u32,
232}
233
234impl PhysicsIsland {
235 #[inline]
237 pub const fn new(id: IslandId) -> Self {
238 Self {
239 id,
240 head_body: None,
241 tail_body: None,
242 body_count: 0,
243 head_contact: None,
244 tail_contact: None,
245 contact_count: 0,
246 head_joint: None,
247 tail_joint: None,
248 joint_count: 0,
249 sleep_timer: 0.0,
250 is_sleeping: false,
251 constraints_removed: 0,
252 }
253 }
254
255 #[inline]
257 pub const fn id(&self) -> IslandId {
258 self.id
259 }
260
261 #[inline]
263 pub const fn body_count(&self) -> u32 {
264 self.body_count
265 }
266
267 #[inline]
269 pub const fn contact_count(&self) -> u32 {
270 self.contact_count
271 }
272
273 #[inline]
275 pub const fn joint_count(&self) -> u32 {
276 self.joint_count
277 }
278
279 #[inline]
281 pub const fn is_sleeping(&self) -> bool {
282 self.is_sleeping
283 }
284
285 #[inline]
287 pub const fn constraints_removed(&self) -> u32 {
288 self.constraints_removed
289 }
290
291 #[inline]
294 pub fn validate(
295 &self,
296 body_islands: &Query<&BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
297 contact_graph: &ContactGraphInternal,
298 joint_graph: &JointGraph,
299 ) {
300 self.validate_bodies(body_islands);
301 self.validate_contacts(contact_graph);
302 self.validate_joints(joint_graph);
303 }
304
305 pub fn validate_bodies(
307 &self,
308 body_islands: &Query<&BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
309 ) {
310 if self.head_body.is_none() {
311 assert!(self.tail_body.is_none());
312 assert_eq!(self.body_count, 0);
313 return;
314 }
315
316 assert!(self.tail_body.is_some());
317 assert!(self.body_count > 0);
318
319 if self.body_count > 1 {
320 assert_ne!(self.head_body, self.tail_body);
321 }
322
323 let mut count = 0;
324 let mut body_id = self.head_body;
325
326 while let Some(entity) = body_id {
327 let body = body_islands.get(entity).unwrap();
328 assert_eq!(body.island_id, self.id);
329
330 count += 1;
331
332 if count == self.body_count {
333 assert_eq!(body_id, self.tail_body);
334 }
335
336 body_id = body.next;
337 }
338
339 assert_eq!(count, self.body_count);
340 }
341
342 pub fn validate_contacts(&self, contact_graph: &ContactGraphInternal) {
344 if self.head_contact.is_none() {
345 assert!(self.tail_contact.is_none());
346 assert_eq!(self.contact_count, 0);
347 return;
348 }
349
350 assert!(self.tail_contact.is_some());
351 assert!(self.contact_count > 0);
352
353 if self.contact_count > 1 {
354 assert_ne!(self.head_contact, self.tail_contact);
355 }
356
357 let mut count = 0;
358 let mut contact_id = self.head_contact;
359
360 while let Some(id) = contact_id {
361 let contact = contact_graph.edge_weight(id.into()).unwrap();
362 let contact_island = contact
363 .island
364 .as_ref()
365 .unwrap_or_else(|| panic!("Contact {id:?} has no island"));
366 assert_eq!(contact_island.island_id, self.id);
367
368 count += 1;
369
370 if count == self.contact_count {
371 assert_eq!(contact_id, self.tail_contact);
372 }
373
374 contact_id = contact_island.next;
375 }
376
377 assert_eq!(count, self.contact_count);
378 }
379
380 pub fn validate_joints(&self, joint_graph: &JointGraph) {
382 if self.head_joint.is_none() {
383 assert!(self.tail_joint.is_none());
384 assert_eq!(self.joint_count, 0);
385 return;
386 }
387
388 assert!(self.tail_joint.is_some());
389 assert!(self.joint_count > 0);
390
391 if self.joint_count > 1 {
392 assert_ne!(self.head_joint, self.tail_joint);
393 }
394
395 let mut count = 0;
396 let mut joint_id = self.head_joint;
397
398 while let Some(id) = joint_id {
399 let joint = joint_graph.get_by_id(id).unwrap();
400 let joint_island = &joint.island;
401 assert_eq!(joint_island.island_id, self.id);
402
403 count += 1;
404
405 if count == self.joint_count {
406 assert_eq!(joint_id, self.tail_joint);
407 }
408
409 joint_id = joint_island.next;
410 }
411
412 assert_eq!(count, self.joint_count);
413 }
414}
415
416#[derive(Resource, Debug, Default, Clone)]
418pub struct PhysicsIslands {
419 islands: Slab<PhysicsIsland>,
421 pub split_candidate: Option<IslandId>,
426 pub split_candidate_sleep_timer: f32,
430}
431
432impl PhysicsIslands {
433 #[inline]
435 pub fn create_island_with<F>(&mut self, init: F) -> IslandId
436 where
437 F: FnOnce(&mut PhysicsIsland),
438 {
439 let island_id = self.next_id();
441 let mut island = PhysicsIsland::new(island_id);
442
443 init(&mut island);
445
446 IslandId(self.islands.insert(island) as u32)
448 }
449
450 #[inline]
456 pub fn remove_island(&mut self, island_id: IslandId) -> PhysicsIsland {
457 if self.split_candidate == Some(island_id) {
458 self.split_candidate = None;
459 }
460
461 self.islands.remove(island_id.0 as usize)
463 }
464
465 #[inline]
467 pub fn next_id(&self) -> IslandId {
468 IslandId(self.islands.vacant_key() as u32)
469 }
470
471 #[inline]
473 pub fn get(&self, island_id: IslandId) -> Option<&PhysicsIsland> {
474 self.islands.get(island_id.0 as usize)
475 }
476
477 #[inline]
479 pub fn get_mut(&mut self, island_id: IslandId) -> Option<&mut PhysicsIsland> {
480 self.islands.get_mut(island_id.0 as usize)
481 }
482
483 #[inline]
485 pub fn iter(&self) -> impl Iterator<Item = &PhysicsIsland> {
486 self.islands.iter().map(|(_, island)| island)
487 }
488
489 #[inline]
491 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut PhysicsIsland> {
492 self.islands.iter_mut().map(|(_, island)| island)
493 }
494
495 #[inline]
497 pub fn len(&self) -> usize {
498 self.islands.len()
499 }
500
501 #[inline]
503 pub fn is_empty(&self) -> bool {
504 self.islands.is_empty()
505 }
506
507 pub fn add_contact(
514 &mut self,
515 contact_id: ContactId,
516 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
517 contact_graph: &mut ContactGraph,
518 joint_graph: &mut JointGraph,
519 ) -> Option<&PhysicsIsland> {
520 let contact = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
521
522 debug_assert!(contact.island.is_none());
523 debug_assert!(contact.is_touching());
524
525 let (Some(body1), Some(body2)) = (contact.body1, contact.body2) else {
526 return None;
527 };
528
529 let island_id = self.merge_islands(body1, body2, body_islands, contact_graph, joint_graph);
531
532 let island = self
534 .islands
535 .get_mut(island_id.0 as usize)
536 .unwrap_or_else(|| {
537 panic!("Island {island_id} does not exist");
538 });
539
540 let mut contact_island = IslandNode {
541 island_id: island.id,
542 prev: None,
543 next: None,
544 is_visited: false,
545 };
546
547 if let Some(head_contact_id) = island.head_contact {
548 contact_island.next = Some(head_contact_id);
550
551 let head_contact = contact_graph.get_edge_mut_by_id(head_contact_id).unwrap();
552 let head_contact_island = head_contact
553 .island
554 .as_mut()
555 .unwrap_or_else(|| panic!("Head contact {head_contact_id:?} has no island"));
556 head_contact_island.prev = Some(contact_id);
557 }
558
559 island.head_contact = Some(contact_id);
560
561 if island.tail_contact.is_none() {
562 island.tail_contact = island.head_contact;
563 }
564
565 let contact = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
567 contact.island = Some(contact_island);
568
569 island.contact_count += 1;
570
571 #[cfg(feature = "validate")]
572 {
573 island.validate(
575 &body_islands.as_readonly(),
576 &contact_graph.edges,
577 joint_graph,
578 );
579 }
580
581 Some(island)
582 }
583
584 #[expect(
591 unused_variables,
592 reason = "additional parameters are needed with the `validate` feature"
593 )]
594 pub fn remove_contact(
595 &mut self,
596 contact_id: ContactId,
597 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
598 contact_graph: &mut ContactGraphInternal,
599 joint_graph: &JointGraph,
600 ) -> &PhysicsIsland {
601 let contact = contact_graph.edge_weight_mut(contact_id.into()).unwrap();
602
603 debug_assert!(contact.island.is_some());
604
605 let contact_island = contact.island.take().unwrap();
607
608 if let Some(prev_contact_id) = contact_island.prev {
610 let prev_contact = contact_graph
611 .edge_weight_mut(prev_contact_id.into())
612 .unwrap();
613 let prev_contact_island = prev_contact
614 .island
615 .as_mut()
616 .expect("Previous contact has no island");
617 debug_assert!(prev_contact_island.next == Some(contact_id));
618 prev_contact_island.next = contact_island.next;
619 }
620
621 if let Some(next_contact_id) = contact_island.next {
622 let next_contact = contact_graph
623 .edge_weight_mut(next_contact_id.into())
624 .unwrap();
625 let next_contact_island = next_contact
626 .island
627 .as_mut()
628 .expect("Next contact has no island");
629 debug_assert!(next_contact_island.prev == Some(contact_id));
630 next_contact_island.prev = contact_island.prev;
631 }
632
633 let island = self
634 .islands
635 .get_mut(contact_island.island_id.0 as usize)
636 .unwrap_or_else(|| {
637 panic!("Island {} does not exist", contact_island.island_id);
638 });
639
640 if island.head_contact == Some(contact_id) {
641 island.head_contact = contact_island.next;
643 }
644
645 if island.tail_contact == Some(contact_id) {
646 island.tail_contact = contact_island.prev;
648 }
649
650 debug_assert!(island.contact_count > 0);
651 island.contact_count -= 1;
652 island.constraints_removed += 1;
653
654 #[cfg(feature = "validate")]
655 {
656 island.validate(&body_islands.as_readonly(), contact_graph, joint_graph);
658 }
659
660 island
661 }
662
663 pub fn add_joint(
670 &mut self,
671 joint_id: JointId,
672 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
673 contact_graph: &mut ContactGraph,
674 joint_graph: &mut JointGraph,
675 ) -> Option<&PhysicsIsland> {
676 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
677
678 let island_id = self.merge_islands(
680 joint.body1,
681 joint.body2,
682 body_islands,
683 contact_graph,
684 joint_graph,
685 );
686
687 let island = self
689 .islands
690 .get_mut(island_id.0 as usize)
691 .unwrap_or_else(|| {
692 panic!("Island {island_id} does not exist");
693 });
694
695 let mut joint_island = IslandNode {
696 island_id: island.id,
697 prev: None,
698 next: None,
699 is_visited: false,
700 };
701
702 if let Some(head_joint_id) = island.head_joint {
703 joint_island.next = Some(head_joint_id);
705
706 let head_joint = joint_graph.get_mut_by_id(head_joint_id).unwrap();
707 let head_island = &mut head_joint.island;
708 head_island.prev = Some(joint_id);
709 }
710
711 island.head_joint = Some(joint_id);
712
713 if island.tail_joint.is_none() {
714 island.tail_joint = island.head_joint;
715 }
716
717 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
719 joint.island = joint_island;
720
721 island.joint_count += 1;
722
723 #[cfg(feature = "validate")]
724 {
725 island.validate(
727 &body_islands.as_readonly(),
728 &contact_graph.edges,
729 joint_graph,
730 );
731 }
732
733 Some(island)
734 }
735
736 #[expect(
745 unused_variables,
746 reason = "additional parameters are needed with the `validate` feature"
747 )]
748 pub fn remove_joint(
749 &mut self,
750 joint_id: JointId,
751 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
752 contact_graph: &ContactGraph,
753 joint_graph: &mut JointGraph,
754 ) -> &PhysicsIsland {
755 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
756
757 debug_assert!(joint.island.island_id != IslandId::PLACEHOLDER);
758
759 let joint_island = joint.island;
761
762 if let Some(prev_joint_id) = joint_island.prev {
764 let prev_joint = joint_graph.get_mut_by_id(prev_joint_id).unwrap();
765 let prev_island = &mut prev_joint.island;
766 debug_assert!(prev_island.next == Some(joint_id));
767 prev_island.next = joint_island.next;
768 }
769
770 if let Some(next_joint_id) = joint_island.next {
771 let next_joint = joint_graph.get_mut_by_id(next_joint_id).unwrap();
772 let next_island = &mut next_joint.island;
773 debug_assert!(next_island.prev == Some(joint_id));
774 next_island.prev = joint_island.prev;
775 }
776
777 let island = self
778 .islands
779 .get_mut(joint_island.island_id.0 as usize)
780 .unwrap_or_else(|| {
781 panic!("Island {} does not exist", joint_island.island_id);
782 });
783
784 if island.head_joint == Some(joint_id) {
785 island.head_joint = joint_island.next;
787 }
788
789 if island.tail_joint == Some(joint_id) {
790 island.tail_joint = joint_island.prev;
792 }
793
794 debug_assert!(island.joint_count > 0);
795 island.joint_count -= 1;
796 island.constraints_removed += 1;
797
798 #[cfg(feature = "validate")]
799 {
800 island.validate(
802 &body_islands.as_readonly(),
803 &contact_graph.edges,
804 joint_graph,
805 );
806 }
807
808 island
809 }
810
811 pub fn merge_islands(
819 &mut self,
820 body1: Entity,
821 body2: Entity,
822 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
823 contact_graph: &mut ContactGraph,
824 joint_graph: &mut JointGraph,
825 ) -> IslandId {
826 let Ok(island_id1) = body_islands.get(body1).map(|island| island.island_id) else {
827 let island2 = body_islands.get(body2).unwrap_or_else(|_| {
828 panic!("Neither body {body1:?} nor {body2:?} is in an island");
829 });
830 return island2.island_id;
831 };
832
833 let Ok(island_id2) = body_islands.get(body2).map(|island| island.island_id) else {
834 let island1 = body_islands.get(body1).unwrap_or_else(|_| {
835 panic!("Neither body {body1:?} nor {body2:?} is in an island");
836 });
837 return island1.island_id;
838 };
839
840 if island_id1 == island_id2 {
841 return island_id1;
843 }
844
845 let [mut big, mut small] = self
848 .islands
849 .get_disjoint_mut([island_id1.0 as usize, island_id2.0 as usize])
850 .unwrap();
851 if big.body_count < small.body_count {
852 core::mem::swap(&mut big, &mut small);
853 }
854
855 let mut body_entity = small.head_body;
859 while let Some(entity) = body_entity {
860 let mut body_island = body_islands.get_mut(entity).unwrap();
861 body_island.island_id = big.id;
862 body_entity = body_island.next;
863 }
864
865 let mut contact_id = small.head_contact;
867 while let Some(id) = contact_id {
868 let contact = contact_graph.get_edge_mut_by_id(id).unwrap();
869 let contact_island = contact.island.as_mut().expect("Contact has no island");
870 contact_island.island_id = big.id;
871 contact_id = contact_island.next;
872 }
873
874 let mut joint_id = small.head_joint;
876 while let Some(id) = joint_id {
877 let joint = joint_graph.get_mut_by_id(id).unwrap();
878 joint.island.island_id = big.id;
879 joint_id = joint.island.next;
880 }
881
882 let tail_body_id = big.tail_body.expect("Island {island_id1} has no tail body");
886 let head_body_id = small
887 .head_body
888 .expect("Island {island_id2} has no head body");
889 let [mut tail_body, mut head_body] = body_islands
890 .get_many_mut([tail_body_id, head_body_id])
891 .unwrap();
892 tail_body.next = small.head_body;
893 head_body.prev = big.tail_body;
894
895 big.tail_body = small.tail_body;
896 big.body_count += small.body_count;
897
898 if big.head_contact.is_none() {
900 debug_assert!(big.tail_contact.is_none() && big.contact_count == 0);
902
903 big.head_contact = small.head_contact;
904 big.tail_contact = small.tail_contact;
905 big.contact_count = small.contact_count;
906 } else if small.head_contact.is_some() {
907 debug_assert!(big.contact_count > 0);
909 debug_assert!(small.contact_count > 0);
910
911 let tail_contact_id = big.tail_contact.expect("Root island has no tail contact");
912 let head_contact_id = small.head_contact.expect("Island has no head contact");
913
914 let tail_contact = contact_graph.get_edge_mut_by_id(tail_contact_id).unwrap();
916 let tail_contact_island = tail_contact
917 .island
918 .as_mut()
919 .expect("Tail contact has no island");
920 debug_assert!(tail_contact_island.next.is_none());
921 tail_contact_island.next = small.head_contact;
922
923 let head_contact = contact_graph.get_edge_mut_by_id(head_contact_id).unwrap();
925 let head_contact_island = head_contact
926 .island
927 .as_mut()
928 .expect("Head contact has no island");
929 debug_assert!(head_contact_island.prev.is_none());
930 head_contact_island.prev = big.tail_contact;
931
932 big.tail_contact = small.tail_contact;
933 big.contact_count += small.contact_count;
934 }
935
936 if big.head_joint.is_none() {
938 debug_assert!(big.tail_joint.is_none() && big.joint_count == 0);
940
941 big.head_joint = small.head_joint;
942 big.tail_joint = small.tail_joint;
943 big.joint_count = small.joint_count;
944 } else if small.head_joint.is_some() {
945 debug_assert!(big.joint_count > 0);
947 debug_assert!(small.joint_count > 0);
948
949 let tail_joint_id = big.tail_joint.expect("Root island has no tail joint");
950 let head_joint_id = small.head_joint.expect("Island has no head joint");
951
952 let tail_joint = joint_graph.get_mut_by_id(tail_joint_id).unwrap();
954 let tail_island = &mut tail_joint.island;
955 debug_assert!(tail_island.next.is_none());
956 tail_island.next = small.head_joint;
957
958 let head_joint = joint_graph.get_mut_by_id(head_joint_id).unwrap();
960 let head_island = &mut head_joint.island;
961 debug_assert!(head_island.prev.is_none());
962 head_island.prev = big.tail_joint;
963
964 big.tail_joint = small.tail_joint;
965 big.joint_count += small.joint_count;
966 }
967
968 big.constraints_removed += small.constraints_removed;
970
971 if small.is_sleeping {
973 big.is_sleeping = true;
975 big.sleep_timer = small.sleep_timer.max(big.sleep_timer);
976 }
977
978 #[cfg(feature = "validate")]
979 {
980 big.validate(
982 &body_islands.as_readonly(),
983 &contact_graph.edges,
984 joint_graph,
985 );
986 }
987
988 let big_id = big.id;
990 let small_id = small.id;
991 self.remove_island(small_id);
992
993 big_id
994 }
995
996 pub fn split_island(
1000 &mut self,
1001 island_id: IslandId,
1002 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
1003 body_colliders: &Query<&RigidBodyColliders>,
1004 contact_graph: &mut ContactGraph,
1005 joint_graph: &mut JointGraph,
1006 ) {
1007 let island = self.islands.get_mut(island_id.0 as usize).unwrap();
1008
1009 if island.is_sleeping {
1010 return;
1012 }
1013
1014 if island.constraints_removed == 0 {
1015 return;
1017 }
1018
1019 #[cfg(feature = "validate")]
1020 {
1021 island.validate(
1023 &body_islands.as_readonly(),
1024 &contact_graph.edges,
1025 joint_graph,
1026 );
1027 }
1028
1029 let body_count = island.body_count;
1030
1031 let mut body_ids = Vec::with_capacity(body_count as usize);
1036 let mut next_body = island.head_body;
1037
1038 while let Some(body_id) = next_body {
1039 body_ids.push(body_id);
1040
1041 let mut body_island = body_islands.get_mut(body_id).unwrap();
1042
1043 body_island.is_visited = false;
1045
1046 next_body = body_island.next;
1047 }
1048
1049 debug_assert_eq!(body_ids.len(), body_count as usize);
1050
1051 let mut next_contact = island.head_contact;
1053 while let Some(contact_id) = next_contact {
1054 let contact = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
1055 let contact_island = contact
1056 .island
1057 .as_mut()
1058 .unwrap_or_else(|| panic!("Contact {contact_id:?} has no island"));
1059
1060 contact_island.is_visited = false;
1062
1063 next_contact = contact_island.next;
1064 }
1065
1066 let mut next_joint = island.head_joint;
1068 while let Some(joint_id) = next_joint {
1069 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
1070 let joint_island = &mut joint.island;
1071
1072 joint_island.is_visited = false;
1074
1075 next_joint = joint_island.next;
1076 }
1077
1078 self.remove_island(island_id);
1080
1081 let mut stack = Vec::with_capacity(body_ids.len());
1083 for seed_id in body_ids.into_iter() {
1084 let mut seed = body_islands.get_mut(seed_id).unwrap();
1085
1086 if seed.is_visited {
1087 continue;
1089 }
1090
1091 seed.is_visited = true;
1092
1093 let island_id = self.next_id();
1095 let mut island = PhysicsIsland::new(island_id);
1096
1097 stack.push(seed_id);
1099
1100 while let Some(body) = stack.pop() {
1102 let mut body_island = unsafe { body_islands.get_unchecked(body).unwrap() };
1103
1104 debug_assert!(body_island.is_visited);
1105
1106 body_island.island_id = island_id;
1108
1109 if let Some(tail_body_id) = island.tail_body {
1110 debug_assert_ne!(tail_body_id, body);
1111 unsafe {
1112 body_islands.get_unchecked(tail_body_id).unwrap().next = Some(body);
1113 }
1114 }
1115
1116 body_island.prev = island.tail_body;
1117 body_island.next = None;
1118 island.tail_body = Some(body);
1119
1120 if island.head_body.is_none() {
1121 island.head_body = Some(body);
1122 }
1123
1124 island.body_count += 1;
1125
1126 let contact_edges: Vec<(ContactId, Entity)> = body_colliders
1129 .get(body)
1130 .iter()
1131 .flat_map(|colliders| {
1132 colliders.into_iter().flat_map(|collider| {
1133 contact_graph
1134 .contact_edges_with(collider)
1135 .filter_map(|contact_edge| {
1136 if contact_edge.island.is_some_and(|island| island.is_visited) {
1137 return None;
1139 }
1140
1141 if contact_edge.constraint_handles.is_empty() {
1142 return None;
1144 }
1145
1146 let (Some(body1), Some(body2)) =
1148 (contact_edge.body1, contact_edge.body2)
1149 else {
1150 return None;
1152 };
1153
1154 Some((
1155 contact_edge.id,
1156 if body1 == body { body2 } else { body1 },
1157 ))
1158 })
1159 })
1160 })
1161 .collect();
1162
1163 for (contact_id, other_body) in contact_edges {
1164 if let Ok(mut other_body_island) = body_islands.get_mut(other_body)
1166 && !other_body_island.is_visited
1167 {
1168 stack.push(other_body);
1169 other_body_island.is_visited = true;
1170 }
1171
1172 if let Some(tail_contact_id) = island.tail_contact {
1174 let tail_contact =
1175 contact_graph.get_edge_mut_by_id(tail_contact_id).unwrap();
1176 let tail_contact_island =
1177 tail_contact.island.as_mut().unwrap_or_else(|| {
1178 panic!("Tail contact {tail_contact_id:?} has no island")
1179 });
1180 tail_contact_island.next = Some(contact_id);
1181 }
1182
1183 let contact_edge = contact_graph.get_edge_mut_by_id(contact_id).unwrap();
1184 let contact_island = contact_edge
1185 .island
1186 .as_mut()
1187 .unwrap_or_else(|| panic!("Contact {contact_id:?} has no island"));
1188
1189 contact_island.is_visited = true;
1190 contact_island.island_id = island_id;
1191 contact_island.prev = island.tail_contact;
1192 contact_island.next = None;
1193
1194 island.tail_contact = Some(contact_id);
1195
1196 if island.head_contact.is_none() {
1197 island.head_contact = Some(contact_id);
1198 }
1199
1200 island.contact_count += 1;
1201 }
1202
1203 let joint_edges: Vec<(JointId, Entity)> = joint_graph
1205 .joints_of(body)
1206 .filter_map(|joint_edge| {
1207 if joint_edge.island.is_visited {
1208 return None;
1210 }
1211
1212 Some((
1213 joint_edge.id,
1214 if joint_edge.body1 == body {
1215 joint_edge.body2
1216 } else {
1217 joint_edge.body1
1218 },
1219 ))
1220 })
1221 .collect();
1222
1223 for (joint_id, other_body) in joint_edges {
1224 if let Ok(mut other_body_island) = body_islands.get_mut(other_body)
1226 && !other_body_island.is_visited
1227 {
1228 stack.push(other_body);
1229 other_body_island.is_visited = true;
1230 }
1231
1232 if let Some(tail_joint_id) = island.tail_joint {
1234 let tail_joint = joint_graph.get_mut_by_id(tail_joint_id).unwrap();
1235 let tail_island = &mut tail_joint.island;
1236 tail_island.next = Some(joint_id);
1237 }
1238
1239 let joint = joint_graph.get_mut_by_id(joint_id).unwrap();
1240 let joint_island = &mut joint.island;
1241
1242 joint_island.is_visited = true;
1243 joint_island.island_id = island_id;
1244 joint_island.prev = island.tail_joint;
1245 joint_island.next = None;
1246
1247 island.tail_joint = Some(joint_id);
1248
1249 if island.head_joint.is_none() {
1250 island.head_joint = Some(joint_id);
1251 }
1252
1253 island.joint_count += 1;
1254 }
1255 }
1256
1257 #[cfg(feature = "validate")]
1258 {
1259 island.validate(
1261 &body_islands.as_readonly(),
1262 &contact_graph.edges,
1263 joint_graph,
1264 );
1265 }
1266
1267 self.islands.insert(island);
1269 }
1270 }
1271}
1272
1273#[derive(Clone, Debug, PartialEq, Eq, Reflect)]
1275#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1276pub struct IslandNode<Id> {
1277 pub(crate) island_id: IslandId,
1279 pub(crate) prev: Option<Id>,
1281 pub(crate) next: Option<Id>,
1283 pub(crate) is_visited: bool,
1285}
1286
1287impl<Id> IslandNode<Id> {
1288 pub const PLACEHOLDER: Self = Self::new(IslandId::PLACEHOLDER);
1290
1291 #[inline]
1293 pub const fn new(island_id: IslandId) -> Self {
1294 Self {
1295 island_id,
1296 prev: None,
1297 next: None,
1298 is_visited: false,
1299 }
1300 }
1301
1302 #[inline]
1304 pub const fn island_id(&self) -> IslandId {
1305 self.island_id
1306 }
1307}
1308
1309impl<Id> Default for IslandNode<Id> {
1310 fn default() -> Self {
1311 Self::PLACEHOLDER
1312 }
1313}
1314
1315impl<Id: Copy> Copy for IslandNode<Id> {}
1316
1317#[derive(Component, Clone, Debug, Default, Deref, DerefMut, PartialEq, Eq, Reflect)]
1319#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1320#[component(on_add = BodyIslandNode::on_add, on_remove = BodyIslandNode::on_remove)]
1321pub struct BodyIslandNode(IslandNode<Entity>);
1322
1323impl BodyIslandNode {
1324 #[inline]
1326 pub const fn new(island_id: IslandId) -> Self {
1327 Self(IslandNode::new(island_id))
1328 }
1329
1330 fn on_add(mut world: DeferredWorld, ctx: HookContext) {
1332 let mut islands = world.resource_mut::<PhysicsIslands>();
1334 let island_id = islands.create_island_with(|island| {
1335 island.head_body = Some(ctx.entity);
1336 island.tail_body = Some(ctx.entity);
1337 island.body_count = 1;
1338 });
1339
1340 let mut body_island = world.get_mut::<BodyIslandNode>(ctx.entity).unwrap();
1342 body_island.island_id = island_id;
1343 }
1344
1345 fn on_remove(mut world: DeferredWorld, ctx: HookContext) {
1347 let body_island = world.get::<BodyIslandNode>(ctx.entity).unwrap();
1348 let island_id = body_island.island_id;
1349 let prev_body_entity = body_island.prev;
1350 let next_body_entity = body_island.next;
1351
1352 if let Some(entity) = prev_body_entity {
1354 let mut prev_body_island = world.get_mut::<BodyIslandNode>(entity).unwrap();
1355 prev_body_island.next = next_body_entity;
1356 }
1357 if let Some(entity) = next_body_entity {
1358 let mut next_body_island = world.get_mut::<BodyIslandNode>(entity).unwrap();
1359 next_body_island.prev = prev_body_entity;
1360 }
1361
1362 let mut islands = world.resource_mut::<PhysicsIslands>();
1363 let island = islands
1364 .get_mut(island_id)
1365 .unwrap_or_else(|| panic!("Island {island_id} does not exist"));
1366
1367 debug_assert!(island.body_count > 0);
1368 island.body_count -= 1;
1369
1370 #[cfg(feature = "validate")]
1371 let mut island_removed = false;
1372
1373 if island.head_body == Some(ctx.entity) {
1374 island.head_body = next_body_entity;
1375
1376 if island.head_body.is_none() {
1377 debug_assert!(island.tail_body == Some(ctx.entity));
1379 debug_assert!(island.body_count == 0);
1380 debug_assert!(island.contact_count == 0);
1381
1382 world
1383 .resource_mut::<PhysicsIslands>()
1384 .remove_island(island_id);
1385
1386 #[cfg(feature = "validate")]
1387 {
1388 island_removed = true;
1389 }
1390 }
1391 } else if island.tail_body == Some(ctx.entity) {
1392 island.tail_body = prev_body_entity;
1393 }
1394
1395 #[cfg(feature = "validate")]
1396 if !island_removed {
1397 world.commands().queue(move |world: &mut World| {
1399 use bevy::ecs::system::RunSystemOnce;
1400 let _ = world.run_system_once(
1402 move |bodies: Query<
1403 &BodyIslandNode,
1404 Or<(With<Disabled>, Without<Disabled>)>,
1405 >,
1406 islands: Res<PhysicsIslands>,
1407 contact_graph: Res<ContactGraph>,
1408 joint_graph: Res<JointGraph>| {
1409 let island = islands
1410 .get(island_id)
1411 .unwrap_or_else(|| panic!("Island {island_id} does not exist"));
1412 island.validate(&bodies, &contact_graph.edges, &joint_graph);
1413 },
1414 );
1415 });
1416 }
1417 }
1418}