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