1mod sleeping;
46pub use sleeping::{IslandSleepingPlugin, SleepBody, SleepIslands, WakeBody, WakeIslands};
47
48use bevy::{
49 ecs::{
50 entity::{ComponentCloneCtx, SourceComponent},
51 entity_disabling::Disabled,
52 lifecycle::HookContext,
53 world::DeferredWorld,
54 },
55 prelude::*,
56};
57
58use crate::{
59 collision::contact_types::ContactId,
60 data_structures::stable_vec::StableVec,
61 dynamics::{
62 joints::joint_graph::{JointGraph, JointId},
63 solver::solver_body::SolverBodyIndex,
64 },
65 prelude::{
66 ContactGraph, PhysicsSchedule, RigidBody, RigidBodyColliders, RigidBodyDisabled,
67 SolverSystems,
68 },
69};
70
71pub struct IslandPlugin;
75
76impl Plugin for IslandPlugin {
77 fn build(&self, app: &mut App) {
78 app.init_resource::<PhysicsIslands>();
79
80 app.register_required_components::<SolverBodyIndex, BodyIslandNode>();
82
83 app.add_observer(
86 |trigger: On<Discard<RigidBodyDisabled>>,
87 rb_query: Query<&RigidBody>,
88 mut commands: Commands| {
89 let Ok(rb) = rb_query.get(trigger.entity) else {
90 return;
91 };
92 if rb.is_dynamic() || rb.is_kinematic() {
93 commands
94 .entity(trigger.entity)
95 .try_insert(BodyIslandNode::default());
96 }
97 },
98 );
99 app.add_observer(
100 |trigger: On<Discard<Disabled>>,
101 rb_query: Query<
102 &RigidBody,
103 (
104 With<Disabled>,
107 Without<RigidBodyDisabled>,
108 ),
109 >,
110 mut commands: Commands| {
111 let Ok(rb) = rb_query.get(trigger.entity) else {
112 return;
113 };
114 if rb.is_dynamic() || rb.is_kinematic() {
115 commands
116 .entity(trigger.entity)
117 .try_insert(BodyIslandNode::default());
118 }
119 },
120 );
121
122 app.add_observer(|trigger: On<Remove<RigidBody>>, mut commands: Commands| {
128 commands
129 .entity(trigger.entity)
130 .try_remove::<BodyIslandNode>();
131 });
132 app.add_observer(
133 |trigger: On<Insert<(Disabled, RigidBodyDisabled)>>,
134 query: Query<&RigidBody, Or<(With<Disabled>, Without<Disabled>)>>,
135 mut commands: Commands| {
136 if query.contains(trigger.entity) {
137 commands
138 .entity(trigger.entity)
139 .try_remove::<BodyIslandNode>();
140 }
141 },
142 );
143 app.add_observer(
144 |trigger: On<Insert<RigidBody>>, query: Query<&RigidBody>, mut commands: Commands| {
145 if let Ok(rb) = query.get(trigger.entity)
146 && rb.is_static()
147 {
148 commands
149 .entity(trigger.entity)
150 .try_remove::<BodyIslandNode>();
151 }
152 },
153 );
154
155 app.add_systems(
156 PhysicsSchedule,
157 split_island.in_set(SolverSystems::Finalize),
158 );
159 }
160}
161
162fn split_island(
163 mut islands: ResMut<PhysicsIslands>,
164 mut body_islands: Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
165 body_colliders: Query<&RigidBodyColliders>,
166 contact_graph: Res<ContactGraph>,
167 joint_graph: Res<JointGraph>,
168) {
169 if let Some(island_id) = islands.split_candidate {
171 islands.split_island(
172 island_id,
173 &mut body_islands,
174 &body_colliders,
175 &contact_graph,
176 &joint_graph,
177 );
178 }
179}
180
181#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Reflect)]
183#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
184#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
185#[reflect(Debug, PartialEq)]
186pub struct IslandId(pub u32);
187
188impl IslandId {
189 pub const PLACEHOLDER: Self = Self(u32::MAX);
191}
192
193impl core::fmt::Display for IslandId {
194 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
195 write!(f, "IslandId({})", self.0)
196 }
197}
198
199#[derive(Clone, Debug, PartialEq)]
212pub struct PhysicsIsland {
213 pub(crate) id: IslandId,
214
215 pub(crate) head_body: Option<Entity>,
216 pub(crate) tail_body: Option<Entity>,
217 pub(crate) body_count: u32,
218
219 pub(crate) head_contact: Option<ContactId>,
220 pub(crate) tail_contact: Option<ContactId>,
221 pub(crate) contact_count: u32,
222
223 pub(crate) head_joint: Option<JointId>,
224 pub(crate) tail_joint: Option<JointId>,
225 pub(crate) joint_count: u32,
226
227 pub(crate) sleep_timer: f32,
228 pub(crate) is_sleeping: bool,
229
230 pub(crate) constraints_removed: u32,
231}
232
233impl PhysicsIsland {
234 #[inline]
236 pub const fn new(id: IslandId) -> Self {
237 Self {
238 id,
239 head_body: None,
240 tail_body: None,
241 body_count: 0,
242 head_contact: None,
243 tail_contact: None,
244 contact_count: 0,
245 head_joint: None,
246 tail_joint: None,
247 joint_count: 0,
248 sleep_timer: 0.0,
249 is_sleeping: false,
250 constraints_removed: 0,
251 }
252 }
253
254 #[inline]
256 pub const fn id(&self) -> IslandId {
257 self.id
258 }
259
260 #[inline]
262 pub const fn body_count(&self) -> u32 {
263 self.body_count
264 }
265
266 #[inline]
268 pub const fn contact_count(&self) -> u32 {
269 self.contact_count
270 }
271
272 #[inline]
274 pub const fn joint_count(&self) -> u32 {
275 self.joint_count
276 }
277
278 #[inline]
280 pub const fn is_sleeping(&self) -> bool {
281 self.is_sleeping
282 }
283
284 #[inline]
286 pub const fn constraints_removed(&self) -> u32 {
287 self.constraints_removed
288 }
289
290 #[inline]
293 pub fn validate(
294 &self,
295 body_islands: &Query<&BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
296 contact_nodes: &[Option<IslandNode<ContactId>>],
297 joint_nodes: &[Option<IslandNode<JointId>>],
298 ) {
299 self.validate_bodies(body_islands);
300 self.validate_contacts(contact_nodes);
301 self.validate_joints(joint_nodes);
302 }
303
304 pub fn validate_bodies(
306 &self,
307 body_islands: &Query<&BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
308 ) {
309 if self.head_body.is_none() {
310 assert!(self.tail_body.is_none());
311 assert_eq!(self.body_count, 0);
312 return;
313 }
314
315 assert!(self.tail_body.is_some());
316 assert!(self.body_count > 0);
317
318 if self.body_count > 1 {
319 assert_ne!(self.head_body, self.tail_body);
320 }
321
322 let mut count = 0;
323 let mut body_id = self.head_body;
324
325 while let Some(entity) = body_id {
326 let body = body_islands.get(entity).unwrap();
327 assert_eq!(body.island_id, self.id);
328
329 count += 1;
330
331 if count == self.body_count {
332 assert_eq!(body_id, self.tail_body);
333 }
334
335 body_id = body.next;
336 }
337
338 assert_eq!(count, self.body_count);
339 }
340
341 pub fn validate_contacts(&self, contact_nodes: &[Option<IslandNode<ContactId>>]) {
343 if self.head_contact.is_none() {
344 assert!(self.tail_contact.is_none());
345 assert_eq!(self.contact_count, 0);
346 return;
347 }
348
349 assert!(self.tail_contact.is_some());
350 assert!(self.contact_count > 0);
351
352 if self.contact_count > 1 {
353 assert_ne!(self.head_contact, self.tail_contact);
354 }
355
356 let mut count = 0;
357 let mut contact_id = self.head_contact;
358
359 while let Some(id) = contact_id {
360 let contact_island = contact_nodes
361 .get(id.0 as usize)
362 .and_then(|node| node.as_ref())
363 .unwrap_or_else(|| panic!("Contact {id:?} has no island"));
364 assert_eq!(contact_island.island_id, self.id);
365
366 count += 1;
367
368 if count == self.contact_count {
369 assert_eq!(contact_id, self.tail_contact);
370 }
371
372 contact_id = contact_island.next;
373 }
374
375 assert_eq!(count, self.contact_count);
376 }
377
378 pub fn validate_joints(&self, joint_nodes: &[Option<IslandNode<JointId>>]) {
380 if self.head_joint.is_none() {
381 assert!(self.tail_joint.is_none());
382 assert_eq!(self.joint_count, 0);
383 return;
384 }
385
386 assert!(self.tail_joint.is_some());
387 assert!(self.joint_count > 0);
388
389 if self.joint_count > 1 {
390 assert_ne!(self.head_joint, self.tail_joint);
391 }
392
393 let mut count = 0;
394 let mut joint_id = self.head_joint;
395
396 while let Some(id) = joint_id {
397 let joint_island = joint_nodes
398 .get(id.0 as usize)
399 .and_then(|node| node.as_ref())
400 .unwrap_or_else(|| panic!("Joint {id:?} has no 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: StableVec<PhysicsIsland>,
421 contact_nodes: Vec<Option<IslandNode<ContactId>>>,
425 joint_nodes: Vec<Option<IslandNode<JointId>>>,
429 pub split_candidate: Option<IslandId>,
434 pub split_candidate_sleep_timer: f32,
438}
439
440impl PhysicsIslands {
441 #[inline]
443 pub fn create_island_with<F>(&mut self, init: F) -> IslandId
444 where
445 F: FnOnce(&mut PhysicsIsland),
446 {
447 let island_id = self.next_id();
449 let mut island = PhysicsIsland::new(island_id);
450
451 init(&mut island);
453
454 IslandId(self.islands.push(island) as u32)
456 }
457
458 #[inline]
464 pub fn remove_island(&mut self, island_id: IslandId) -> PhysicsIsland {
465 if self.split_candidate == Some(island_id) {
466 self.split_candidate = None;
467 }
468
469 self.islands.remove(island_id.0 as usize)
471 }
472
473 #[inline]
481 pub fn remove_island_if_empty(&mut self, island_id: IslandId) {
482 if let Some(island) = self.islands.get(island_id.0 as usize)
483 && island.body_count == 0
484 && island.contact_count == 0
485 && island.joint_count == 0
486 {
487 self.remove_island(island_id);
488 }
489 }
490
491 #[inline]
493 pub fn next_id(&self) -> IslandId {
494 IslandId(self.islands.next_push_index() as u32)
495 }
496
497 #[inline]
500 pub fn contact_node(&self, contact_id: ContactId) -> Option<&IslandNode<ContactId>> {
501 self.contact_nodes
502 .get(contact_id.0 as usize)
503 .and_then(|node| node.as_ref())
504 }
505
506 #[cfg(feature = "validate")]
508 #[inline]
509 pub(crate) fn contact_nodes(&self) -> &[Option<IslandNode<ContactId>>] {
510 &self.contact_nodes
511 }
512
513 #[inline]
516 pub fn joint_node(&self, joint_id: JointId) -> Option<&IslandNode<JointId>> {
517 self.joint_nodes
518 .get(joint_id.0 as usize)
519 .and_then(|node| node.as_ref())
520 }
521
522 #[cfg(feature = "validate")]
524 #[inline]
525 pub(crate) fn joint_nodes(&self) -> &[Option<IslandNode<JointId>>] {
526 &self.joint_nodes
527 }
528
529 #[inline]
531 pub fn get(&self, island_id: IslandId) -> Option<&PhysicsIsland> {
532 self.islands.get(island_id.0 as usize)
533 }
534
535 #[inline]
537 pub fn get_mut(&mut self, island_id: IslandId) -> Option<&mut PhysicsIsland> {
538 self.islands.get_mut(island_id.0 as usize)
539 }
540
541 #[inline]
543 pub fn iter(&self) -> impl Iterator<Item = &PhysicsIsland> {
544 self.islands.iter().map(|(_, island)| island)
545 }
546
547 #[inline]
549 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut PhysicsIsland> {
550 self.islands.iter_mut().map(|(_, island)| island)
551 }
552
553 #[inline]
555 pub fn len(&self) -> usize {
556 self.islands.len()
557 }
558
559 #[inline]
561 pub fn is_empty(&self) -> bool {
562 self.islands.is_empty()
563 }
564
565 pub fn add_contact(
572 &mut self,
573 contact_id: ContactId,
574 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
575 contact_graph: &ContactGraph,
576 ) -> Option<&PhysicsIsland> {
577 let contact = contact_graph.get_edge_by_id(contact_id).unwrap();
578
579 debug_assert!(self.contact_node(contact_id).is_none());
580 debug_assert!(contact.is_touching());
581
582 let (Some(body1), Some(body2)) = (contact.body1, contact.body2) else {
583 return None;
584 };
585
586 let island_id = self.merge_islands(body1, body2, body_islands);
588
589 let contact_index = contact_id.0 as usize;
591 if contact_index >= self.contact_nodes.len() {
592 self.contact_nodes.resize_with(contact_index + 1, || None);
593 }
594
595 let island = self
597 .islands
598 .get_mut(island_id.0 as usize)
599 .unwrap_or_else(|| {
600 panic!("Island {island_id} does not exist");
601 });
602
603 let mut contact_island = IslandNode {
604 island_id: island.id,
605 prev: None,
606 next: None,
607 is_visited: false,
608 };
609
610 if let Some(head_contact_id) = island.head_contact {
611 contact_island.next = Some(head_contact_id);
613
614 let head_contact_island = self.contact_nodes[head_contact_id.0 as usize]
615 .as_mut()
616 .unwrap_or_else(|| panic!("Head contact {head_contact_id:?} has no island"));
617 head_contact_island.prev = Some(contact_id);
618 }
619
620 island.head_contact = Some(contact_id);
621
622 if island.tail_contact.is_none() {
623 island.tail_contact = island.head_contact;
624 }
625
626 self.contact_nodes[contact_index] = Some(contact_island);
627
628 island.contact_count += 1;
629
630 #[cfg(feature = "validate")]
631 {
632 island.validate(
634 &body_islands.as_readonly(),
635 &self.contact_nodes,
636 &self.joint_nodes,
637 );
638 }
639
640 Some(island)
641 }
642
643 #[cfg_attr(
650 not(feature = "validate"),
651 expect(
652 unused_variables,
653 reason = "`body_islands` is only used with the `validate` feature"
654 )
655 )]
656 pub fn remove_contact(
657 &mut self,
658 contact_id: ContactId,
659 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
660 ) -> &PhysicsIsland {
661 debug_assert!(self.contact_node(contact_id).is_some());
662
663 let contact_island = self.contact_nodes[contact_id.0 as usize]
665 .take()
666 .expect("Contact has no island");
667
668 if let Some(prev_contact_id) = contact_island.prev {
670 let prev_contact_island = self.contact_nodes[prev_contact_id.0 as usize]
671 .as_mut()
672 .expect("Previous contact has no island");
673 debug_assert!(prev_contact_island.next == Some(contact_id));
674 prev_contact_island.next = contact_island.next;
675 }
676
677 if let Some(next_contact_id) = contact_island.next {
678 let next_contact_island = self.contact_nodes[next_contact_id.0 as usize]
679 .as_mut()
680 .expect("Next contact has no island");
681 debug_assert!(next_contact_island.prev == Some(contact_id));
682 next_contact_island.prev = contact_island.prev;
683 }
684
685 let island = self
686 .islands
687 .get_mut(contact_island.island_id.0 as usize)
688 .unwrap_or_else(|| {
689 panic!("Island {} does not exist", contact_island.island_id);
690 });
691
692 if island.head_contact == Some(contact_id) {
693 island.head_contact = contact_island.next;
695 }
696
697 if island.tail_contact == Some(contact_id) {
698 island.tail_contact = contact_island.prev;
700 }
701
702 debug_assert!(island.contact_count > 0);
703 island.contact_count -= 1;
704 island.constraints_removed += 1;
705
706 #[cfg(feature = "validate")]
707 {
708 island.validate(
710 &body_islands.as_readonly(),
711 &self.contact_nodes,
712 &self.joint_nodes,
713 );
714 }
715
716 island
717 }
718
719 pub fn add_joint(
726 &mut self,
727 joint_id: JointId,
728 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
729 joint_graph: &JointGraph,
730 ) -> Option<&PhysicsIsland> {
731 let joint = joint_graph.get_by_id(joint_id).unwrap();
732
733 debug_assert!(self.joint_node(joint_id).is_none());
734
735 let island_id = self.merge_islands(joint.body1, joint.body2, body_islands);
737
738 let joint_index = joint_id.0 as usize;
740 if joint_index >= self.joint_nodes.len() {
741 self.joint_nodes.resize_with(joint_index + 1, || None);
742 }
743
744 let island = self
746 .islands
747 .get_mut(island_id.0 as usize)
748 .unwrap_or_else(|| {
749 panic!("Island {island_id} does not exist");
750 });
751
752 let mut joint_island = IslandNode {
753 island_id: island.id,
754 prev: None,
755 next: None,
756 is_visited: false,
757 };
758
759 if let Some(head_joint_id) = island.head_joint {
760 joint_island.next = Some(head_joint_id);
762
763 let head_joint_island = self.joint_nodes[head_joint_id.0 as usize]
764 .as_mut()
765 .unwrap_or_else(|| panic!("Head joint {head_joint_id:?} has no island"));
766 head_joint_island.prev = Some(joint_id);
767 }
768
769 island.head_joint = Some(joint_id);
770
771 if island.tail_joint.is_none() {
772 island.tail_joint = island.head_joint;
773 }
774
775 self.joint_nodes[joint_index] = Some(joint_island);
776
777 island.joint_count += 1;
778
779 #[cfg(feature = "validate")]
780 {
781 island.validate(
783 &body_islands.as_readonly(),
784 &self.contact_nodes,
785 &self.joint_nodes,
786 );
787 }
788
789 Some(island)
790 }
791
792 #[cfg_attr(
802 not(feature = "validate"),
803 expect(
804 unused_variables,
805 reason = "`body_islands` is only used with the `validate` feature"
806 )
807 )]
808 pub fn remove_joint(
809 &mut self,
810 joint_id: JointId,
811 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
812 ) -> Option<&PhysicsIsland> {
813 debug_assert!(self.joint_node(joint_id).is_some());
814
815 let joint_island = self.joint_nodes[joint_id.0 as usize]
817 .take()
818 .expect("Joint has no island");
819
820 if let Some(prev_joint_id) = joint_island.prev {
822 let prev_joint_island = self.joint_nodes[prev_joint_id.0 as usize]
823 .as_mut()
824 .expect("Previous joint has no island");
825 debug_assert!(prev_joint_island.next == Some(joint_id));
826 prev_joint_island.next = joint_island.next;
827 }
828
829 if let Some(next_joint_id) = joint_island.next {
830 let next_joint_island = self.joint_nodes[next_joint_id.0 as usize]
831 .as_mut()
832 .expect("Next joint has no island");
833 debug_assert!(next_joint_island.prev == Some(joint_id));
834 next_joint_island.prev = joint_island.prev;
835 }
836
837 let island = self.islands.get_mut(joint_island.island_id.0 as usize)?;
838
839 if island.head_joint == Some(joint_id) {
840 island.head_joint = joint_island.next;
842 }
843
844 if island.tail_joint == Some(joint_id) {
845 island.tail_joint = joint_island.prev;
847 }
848
849 debug_assert!(island.joint_count > 0);
850 island.joint_count -= 1;
851 island.constraints_removed += 1;
852
853 #[cfg(feature = "validate")]
854 {
855 island.validate(
857 &body_islands.as_readonly(),
858 &self.contact_nodes,
859 &self.joint_nodes,
860 );
861 }
862
863 Some(island)
864 }
865
866 pub fn merge_islands(
874 &mut self,
875 body1: Entity,
876 body2: Entity,
877 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
878 ) -> IslandId {
879 let Ok(island_id1) = body_islands.get(body1).map(|island| island.island_id) else {
880 let island2 = body_islands.get(body2).unwrap_or_else(|_| {
881 panic!("Neither body {body1:?} nor {body2:?} is in an island");
882 });
883 return island2.island_id;
884 };
885
886 let Ok(island_id2) = body_islands.get(body2).map(|island| island.island_id) else {
887 let island1 = body_islands.get(body1).unwrap_or_else(|_| {
888 panic!("Neither body {body1:?} nor {body2:?} is in an island");
889 });
890 return island1.island_id;
891 };
892
893 if island_id1 == island_id2 {
894 return island_id1;
896 }
897
898 let [mut big, mut small] = self
901 .islands
902 .get_disjoint_mut2(island_id1.0 as usize, island_id2.0 as usize)
903 .unwrap();
904 if big.body_count < small.body_count {
905 core::mem::swap(&mut big, &mut small);
906 }
907
908 let mut body_entity = small.head_body;
912 while let Some(entity) = body_entity {
913 let mut body_island = body_islands.get_mut(entity).unwrap();
914 body_island.island_id = big.id;
915 body_entity = body_island.next;
916 }
917
918 let mut contact_id = small.head_contact;
920 while let Some(id) = contact_id {
921 let contact_island = self.contact_nodes[id.0 as usize]
922 .as_mut()
923 .expect("Contact has no island");
924 contact_island.island_id = big.id;
925 contact_id = contact_island.next;
926 }
927
928 let mut joint_id = small.head_joint;
930 while let Some(id) = joint_id {
931 let joint_island = self.joint_nodes[id.0 as usize]
932 .as_mut()
933 .expect("Joint has no island");
934 joint_island.island_id = big.id;
935 joint_id = joint_island.next;
936 }
937
938 let tail_body_id = big.tail_body.expect("Island {island_id1} has no tail body");
942 let head_body_id = small
943 .head_body
944 .expect("Island {island_id2} has no head body");
945 let [mut tail_body, mut head_body] = body_islands
946 .get_many_mut([tail_body_id, head_body_id])
947 .unwrap();
948 tail_body.next = small.head_body;
949 head_body.prev = big.tail_body;
950
951 big.tail_body = small.tail_body;
952 big.body_count += small.body_count;
953
954 if big.head_contact.is_none() {
956 debug_assert!(big.tail_contact.is_none() && big.contact_count == 0);
958
959 big.head_contact = small.head_contact;
960 big.tail_contact = small.tail_contact;
961 big.contact_count = small.contact_count;
962 } else if small.head_contact.is_some() {
963 debug_assert!(big.contact_count > 0);
965 debug_assert!(small.contact_count > 0);
966
967 let tail_contact_id = big.tail_contact.expect("Root island has no tail contact");
968 let head_contact_id = small.head_contact.expect("Island has no head contact");
969
970 let tail_contact_island = self.contact_nodes[tail_contact_id.0 as usize]
972 .as_mut()
973 .expect("Tail contact has no island");
974 debug_assert!(tail_contact_island.next.is_none());
975 tail_contact_island.next = small.head_contact;
976
977 let head_contact_island = self.contact_nodes[head_contact_id.0 as usize]
979 .as_mut()
980 .expect("Head contact has no island");
981 debug_assert!(head_contact_island.prev.is_none());
982 head_contact_island.prev = big.tail_contact;
983
984 big.tail_contact = small.tail_contact;
985 big.contact_count += small.contact_count;
986 }
987
988 if big.head_joint.is_none() {
990 debug_assert!(big.tail_joint.is_none() && big.joint_count == 0);
992
993 big.head_joint = small.head_joint;
994 big.tail_joint = small.tail_joint;
995 big.joint_count = small.joint_count;
996 } else if small.head_joint.is_some() {
997 debug_assert!(big.joint_count > 0);
999 debug_assert!(small.joint_count > 0);
1000
1001 let tail_joint_id = big.tail_joint.expect("Root island has no tail joint");
1002 let head_joint_id = small.head_joint.expect("Island has no head joint");
1003
1004 let tail_joint_island = self.joint_nodes[tail_joint_id.0 as usize]
1006 .as_mut()
1007 .expect("Tail joint has no island");
1008 debug_assert!(tail_joint_island.next.is_none());
1009 tail_joint_island.next = small.head_joint;
1010
1011 let head_joint_island = self.joint_nodes[head_joint_id.0 as usize]
1013 .as_mut()
1014 .expect("Head joint has no island");
1015 debug_assert!(head_joint_island.prev.is_none());
1016 head_joint_island.prev = big.tail_joint;
1017
1018 big.tail_joint = small.tail_joint;
1019 big.joint_count += small.joint_count;
1020 }
1021
1022 big.constraints_removed += small.constraints_removed;
1024
1025 if small.is_sleeping {
1027 big.is_sleeping = true;
1029 big.sleep_timer = small.sleep_timer.max(big.sleep_timer);
1030 }
1031
1032 #[cfg(feature = "validate")]
1033 {
1034 big.validate(
1036 &body_islands.as_readonly(),
1037 &self.contact_nodes,
1038 &self.joint_nodes,
1039 );
1040 }
1041
1042 let big_id = big.id;
1044 let small_id = small.id;
1045 self.remove_island(small_id);
1046
1047 big_id
1048 }
1049
1050 pub fn split_island(
1054 &mut self,
1055 island_id: IslandId,
1056 body_islands: &mut Query<&mut BodyIslandNode, Or<(With<Disabled>, Without<Disabled>)>>,
1057 body_colliders: &Query<&RigidBodyColliders>,
1058 contact_graph: &ContactGraph,
1059 joint_graph: &JointGraph,
1060 ) {
1061 let island = self.islands.get_mut(island_id.0 as usize).unwrap();
1062
1063 if island.is_sleeping {
1064 return;
1066 }
1067
1068 if island.constraints_removed == 0 {
1069 return;
1071 }
1072
1073 #[cfg(feature = "validate")]
1074 {
1075 island.validate(
1077 &body_islands.as_readonly(),
1078 &self.contact_nodes,
1079 &self.joint_nodes,
1080 );
1081 }
1082
1083 let body_count = island.body_count;
1084
1085 let mut body_ids = Vec::with_capacity(body_count as usize);
1090 let mut next_body = island.head_body;
1091
1092 while let Some(body_id) = next_body {
1093 body_ids.push(body_id);
1094
1095 let mut body_island = body_islands.get_mut(body_id).unwrap();
1096
1097 body_island.is_visited = false;
1099
1100 next_body = body_island.next;
1101 }
1102
1103 debug_assert_eq!(body_ids.len(), body_count as usize);
1104
1105 let mut next_contact = island.head_contact;
1107 while let Some(contact_id) = next_contact {
1108 let contact_island = self.contact_nodes[contact_id.0 as usize]
1109 .as_mut()
1110 .unwrap_or_else(|| panic!("Contact {contact_id:?} has no island"));
1111
1112 contact_island.is_visited = false;
1114
1115 next_contact = contact_island.next;
1116 }
1117
1118 let mut next_joint = island.head_joint;
1120 while let Some(joint_id) = next_joint {
1121 let joint_island = self.joint_nodes[joint_id.0 as usize]
1122 .as_mut()
1123 .unwrap_or_else(|| panic!("Joint {joint_id:?} has no island"));
1124
1125 joint_island.is_visited = false;
1127
1128 next_joint = joint_island.next;
1129 }
1130
1131 self.remove_island(island_id);
1133
1134 let mut stack = Vec::with_capacity(body_ids.len());
1136 for seed_id in body_ids.into_iter() {
1137 let mut seed = body_islands.get_mut(seed_id).unwrap();
1138
1139 if seed.is_visited {
1140 continue;
1142 }
1143
1144 seed.is_visited = true;
1145
1146 let island_id = self.next_id();
1148 let mut island = PhysicsIsland::new(island_id);
1149
1150 stack.push(seed_id);
1152
1153 while let Some(body) = stack.pop() {
1155 let mut body_island = unsafe { body_islands.get_unchecked(body).unwrap() };
1156
1157 debug_assert!(body_island.is_visited);
1158
1159 body_island.island_id = island_id;
1161
1162 if let Some(tail_body_id) = island.tail_body {
1163 debug_assert_ne!(tail_body_id, body);
1164 unsafe {
1165 body_islands.get_unchecked(tail_body_id).unwrap().next = Some(body);
1166 }
1167 }
1168
1169 body_island.prev = island.tail_body;
1170 body_island.next = None;
1171 island.tail_body = Some(body);
1172
1173 if island.head_body.is_none() {
1174 island.head_body = Some(body);
1175 }
1176
1177 island.body_count += 1;
1178
1179 let contact_edges: Vec<(ContactId, Entity)> = body_colliders
1182 .get(body)
1183 .iter()
1184 .flat_map(|colliders| {
1185 colliders.into_iter().flat_map(|collider| {
1186 contact_graph
1187 .contact_edges_with(collider)
1188 .filter_map(|contact_edge| {
1189 if self
1190 .contact_node(contact_edge.id)
1191 .is_none_or(|node| node.is_visited)
1192 {
1193 return None;
1196 }
1197
1198 let (Some(body1), Some(body2)) =
1200 (contact_edge.body1, contact_edge.body2)
1201 else {
1202 return None;
1204 };
1205
1206 Some((
1207 contact_edge.id,
1208 if body1 == body { body2 } else { body1 },
1209 ))
1210 })
1211 })
1212 })
1213 .collect();
1214
1215 for (contact_id, other_body) in contact_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_contact_id) = island.tail_contact {
1226 let tail_contact_island = self.contact_nodes[tail_contact_id.0 as usize]
1227 .as_mut()
1228 .unwrap_or_else(|| {
1229 panic!("Tail contact {tail_contact_id:?} has no island")
1230 });
1231 tail_contact_island.next = Some(contact_id);
1232 }
1233
1234 let contact_island = self.contact_nodes[contact_id.0 as usize]
1235 .as_mut()
1236 .unwrap_or_else(|| panic!("Contact {contact_id:?} has no island"));
1237
1238 contact_island.is_visited = true;
1239 contact_island.island_id = island_id;
1240 contact_island.prev = island.tail_contact;
1241 contact_island.next = None;
1242
1243 island.tail_contact = Some(contact_id);
1244
1245 if island.head_contact.is_none() {
1246 island.head_contact = Some(contact_id);
1247 }
1248
1249 island.contact_count += 1;
1250 }
1251
1252 let joint_edges: Vec<(JointId, Entity)> = joint_graph
1254 .joints_of(body)
1255 .filter_map(|joint_edge| {
1256 if self
1257 .joint_node(joint_edge.id)
1258 .is_none_or(|node| node.is_visited)
1259 {
1260 return None;
1262 }
1263
1264 Some((
1265 joint_edge.id,
1266 if joint_edge.body1 == body {
1267 joint_edge.body2
1268 } else {
1269 joint_edge.body1
1270 },
1271 ))
1272 })
1273 .collect();
1274
1275 for (joint_id, other_body) in joint_edges {
1276 if let Ok(mut other_body_island) = body_islands.get_mut(other_body)
1278 && !other_body_island.is_visited
1279 {
1280 stack.push(other_body);
1281 other_body_island.is_visited = true;
1282 }
1283
1284 if let Some(tail_joint_id) = island.tail_joint {
1286 let tail_joint_island = self.joint_nodes[tail_joint_id.0 as usize]
1287 .as_mut()
1288 .unwrap_or_else(|| {
1289 panic!("Tail joint {tail_joint_id:?} has no island")
1290 });
1291 tail_joint_island.next = Some(joint_id);
1292 }
1293
1294 let joint_island = self.joint_nodes[joint_id.0 as usize]
1295 .as_mut()
1296 .unwrap_or_else(|| panic!("Joint {joint_id:?} has no island"));
1297
1298 joint_island.is_visited = true;
1299 joint_island.island_id = island_id;
1300 joint_island.prev = island.tail_joint;
1301 joint_island.next = None;
1302
1303 island.tail_joint = Some(joint_id);
1304
1305 if island.head_joint.is_none() {
1306 island.head_joint = Some(joint_id);
1307 }
1308
1309 island.joint_count += 1;
1310 }
1311 }
1312
1313 #[cfg(feature = "validate")]
1314 {
1315 island.validate(
1317 &body_islands.as_readonly(),
1318 &self.contact_nodes,
1319 &self.joint_nodes,
1320 );
1321 }
1322
1323 self.islands.push(island);
1325 }
1326 }
1327}
1328
1329#[derive(Clone, Debug, PartialEq, Eq, Reflect)]
1331#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1332pub struct IslandNode<Id> {
1333 pub(crate) island_id: IslandId,
1335 pub(crate) prev: Option<Id>,
1337 pub(crate) next: Option<Id>,
1339 pub(crate) is_visited: bool,
1341}
1342
1343impl<Id> IslandNode<Id> {
1344 pub const PLACEHOLDER: Self = Self::new(IslandId::PLACEHOLDER);
1346
1347 #[inline]
1349 pub const fn new(island_id: IslandId) -> Self {
1350 Self {
1351 island_id,
1352 prev: None,
1353 next: None,
1354 is_visited: false,
1355 }
1356 }
1357
1358 #[inline]
1360 pub const fn island_id(&self) -> IslandId {
1361 self.island_id
1362 }
1363}
1364
1365impl<Id> Default for IslandNode<Id> {
1366 fn default() -> Self {
1367 Self::PLACEHOLDER
1368 }
1369}
1370
1371impl<Id: Copy> Copy for IslandNode<Id> {}
1372
1373#[derive(Component, Clone, Debug, Default, Deref, DerefMut, PartialEq, Eq, Reflect)]
1375#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
1376#[component(
1377 on_add = BodyIslandNode::on_add,
1378 on_remove = BodyIslandNode::on_remove,
1379 clone_behavior = Custom(clone_placeholder_body_island_node),
1380)]
1381pub struct BodyIslandNode(IslandNode<Entity>);
1382
1383fn clone_placeholder_body_island_node(_source: &SourceComponent, ctx: &mut ComponentCloneCtx) {
1385 ctx.write_target_component(BodyIslandNode::default());
1386}
1387
1388impl BodyIslandNode {
1389 #[inline]
1391 pub const fn new(island_id: IslandId) -> Self {
1392 Self(IslandNode::new(island_id))
1393 }
1394
1395 fn on_add(mut world: DeferredWorld, ctx: HookContext) {
1397 let mut islands = world.resource_mut::<PhysicsIslands>();
1399 let island_id = islands.create_island_with(|island| {
1400 island.head_body = Some(ctx.entity);
1401 island.tail_body = Some(ctx.entity);
1402 island.body_count = 1;
1403 });
1404
1405 let mut body_island = world.get_mut::<BodyIslandNode>(ctx.entity).unwrap();
1407 body_island.island_id = island_id;
1408 }
1409
1410 fn on_remove(mut world: DeferredWorld, ctx: HookContext) {
1412 let body_island = world.get::<BodyIslandNode>(ctx.entity).unwrap();
1413 let island_id = body_island.island_id;
1414 let prev_body_entity = body_island.prev;
1415 let next_body_entity = body_island.next;
1416
1417 if let Some(entity) = prev_body_entity {
1419 let mut prev_body_island = world.get_mut::<BodyIslandNode>(entity).unwrap();
1420 prev_body_island.next = next_body_entity;
1421 }
1422 if let Some(entity) = next_body_entity {
1423 let mut next_body_island = world.get_mut::<BodyIslandNode>(entity).unwrap();
1424 next_body_island.prev = prev_body_entity;
1425 }
1426
1427 let mut islands = world.resource_mut::<PhysicsIslands>();
1428 let island = islands
1429 .get_mut(island_id)
1430 .unwrap_or_else(|| panic!("Island {island_id} does not exist"));
1431
1432 debug_assert!(island.body_count > 0);
1433 island.body_count -= 1;
1434
1435 if island.head_body == Some(ctx.entity) {
1438 island.head_body = next_body_entity;
1439 }
1440 if island.tail_body == Some(ctx.entity) {
1441 island.tail_body = prev_body_entity;
1442 }
1443
1444 islands.remove_island_if_empty(island_id);
1449
1450 #[cfg(feature = "validate")]
1451 let island_removed = islands.get(island_id).is_none();
1452
1453 #[cfg(feature = "validate")]
1454 if !island_removed {
1455 world.commands().queue(move |world: &mut World| {
1457 use bevy::ecs::system::RunSystemOnce;
1458 let _ = world.run_system_once(
1460 move |bodies: Query<
1461 &BodyIslandNode,
1462 Or<(With<Disabled>, Without<Disabled>)>,
1463 >,
1464 islands: Res<PhysicsIslands>| {
1465 let island = islands
1466 .get(island_id)
1467 .unwrap_or_else(|| panic!("Island {island_id} does not exist"));
1468 island.validate(&bodies, islands.contact_nodes(), islands.joint_nodes());
1469 },
1470 );
1471 });
1472 }
1473 }
1474}