1use crate::core::NULL_INDEX;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct ContactLink {
14 pub contact_id: i32,
15 pub body_id_a: i32,
16 pub body_id_b: i32,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct JointLink {
23 pub joint_id: i32,
24 pub body_id_a: i32,
25 pub body_id_b: i32,
26}
27
28#[derive(Debug, Clone)]
35pub struct Island {
36 pub set_index: i32,
38
39 pub local_index: i32,
41
42 pub island_id: i32,
43
44 pub constraint_remove_count: i32,
47
48 pub bodies: Vec<i32>,
49
50 pub contacts: Vec<ContactLink>,
54 pub joints: Vec<JointLink>,
55}
56
57impl Default for Island {
58 fn default() -> Self {
59 Island {
60 set_index: NULL_INDEX,
61 local_index: NULL_INDEX,
62 island_id: NULL_INDEX,
63 constraint_remove_count: 0,
64 bodies: Vec::new(),
65 contacts: Vec::new(),
66 joints: Vec::new(),
67 }
68 }
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub struct IslandSim {
74 pub island_id: i32,
75}
76
77impl Default for IslandSim {
78 fn default() -> Self {
79 IslandSim {
80 island_id: NULL_INDEX,
81 }
82 }
83}
84
85use crate::solver_set::{AWAKE_SET, FIRST_SLEEPING_SET};
91use crate::world::World;
92
93pub fn create_island(world: &mut World, set_index: i32) -> i32 {
96 debug_assert!(set_index == AWAKE_SET || set_index >= FIRST_SLEEPING_SET);
97
98 let island_id = world.island_id_pool.alloc_id();
99
100 if island_id == world.islands.len() as i32 {
101 world.islands.push(Island::default());
102 } else {
103 debug_assert!(world.islands[island_id as usize].set_index == NULL_INDEX);
104 }
105
106 let set = &mut world.solver_sets[set_index as usize];
107
108 let local_index = set.island_sims.len() as i32;
109 set.island_sims.push(IslandSim { island_id });
110
111 let island = &mut world.islands[island_id as usize];
112 island.set_index = set_index;
113 island.local_index = local_index;
114 island.island_id = island_id;
115 island.bodies = Vec::new();
116 island.contacts = Vec::new();
117 island.joints = Vec::new();
118 island.constraint_remove_count = 0;
119
120 island_id
121}
122
123pub fn destroy_island(world: &mut World, island_id: i32) {
125 if world.split_island_id == island_id {
126 world.split_island_id = NULL_INDEX;
127 }
128
129 let (set_index, local_index) = {
131 let island = &world.islands[island_id as usize];
132 (island.set_index, island.local_index)
133 };
134 let set = &mut world.solver_sets[set_index as usize];
135 {
136 let last_index = set.island_sims.len() - 1;
137 debug_assert!(0 <= local_index && local_index as usize <= last_index);
138 let move_island_id = set.island_sims[last_index].island_id;
139 set.island_sims.swap_remove(local_index as usize);
140 world.islands[move_island_id as usize].local_index = local_index;
141 }
142
143 let island = &mut world.islands[island_id as usize];
145 island.bodies = Vec::new();
146 island.contacts = Vec::new();
147 island.joints = Vec::new();
148 island.constraint_remove_count = 0;
149 island.local_index = NULL_INDEX;
150 island.island_id = NULL_INDEX;
151 island.set_index = NULL_INDEX;
152
153 world.island_id_pool.free_id(island_id);
154}
155
156pub(crate) fn merge_islands(world: &mut World, island_id_a: i32, island_id_b: i32) -> i32 {
159 if island_id_a == island_id_b {
160 return island_id_a;
161 }
162
163 if island_id_a == NULL_INDEX {
164 debug_assert!(island_id_b != NULL_INDEX);
165 return island_id_b;
166 }
167
168 if island_id_b == NULL_INDEX {
169 debug_assert!(island_id_a != NULL_INDEX);
170 return island_id_a;
171 }
172
173 let (big_island_id, small_island_id) = {
175 let count_a = world.islands[island_id_a as usize].bodies.len();
176 let count_b = world.islands[island_id_b as usize].bodies.len();
177 if count_a >= count_b {
178 (island_id_a, island_id_b)
179 } else {
180 (island_id_b, island_id_a)
181 }
182 };
183
184 let small_bodies = std::mem::take(&mut world.islands[small_island_id as usize].bodies);
186 for &body_id in &small_bodies {
187 let body = &mut world.bodies[body_id as usize];
188 debug_assert!(body.island_id == small_island_id);
189 body.island_id = big_island_id;
190 body.island_index = world.islands[big_island_id as usize].bodies.len() as i32;
191 world.islands[big_island_id as usize].bodies.push(body_id);
192 }
193
194 let small_contacts = std::mem::take(&mut world.islands[small_island_id as usize].contacts);
196 for link in &small_contacts {
197 let contact = &mut world.contacts[link.contact_id as usize];
198 contact.island_id = big_island_id;
199 contact.island_index = world.islands[big_island_id as usize].contacts.len() as i32;
200 world.islands[big_island_id as usize].contacts.push(*link);
201 }
202
203 let small_joints = std::mem::take(&mut world.islands[small_island_id as usize].joints);
205 for link in &small_joints {
206 let joint = &mut world.joints[link.joint_id as usize];
207 joint.island_id = big_island_id;
208 joint.island_index = world.islands[big_island_id as usize].joints.len() as i32;
209 world.islands[big_island_id as usize].joints.push(*link);
210 }
211
212 let small_removed = world.islands[small_island_id as usize].constraint_remove_count;
214 world.islands[big_island_id as usize].constraint_remove_count += small_removed;
215
216 destroy_island(world, small_island_id);
217
218 validate_island(world, big_island_id);
219
220 big_island_id
221}
222
223fn add_contact_to_island(world: &mut World, island_id: i32, contact_id: i32) {
225 let (edge_body_a, edge_body_b) = {
226 let contact = &world.contacts[contact_id as usize];
227 debug_assert!(contact.island_id == NULL_INDEX);
228 debug_assert!(contact.island_index == NULL_INDEX);
229 (contact.edges[0].body_id, contact.edges[1].body_id)
230 };
231
232 let island = &mut world.islands[island_id as usize];
233
234 let island_index = island.contacts.len() as i32;
235 island.contacts.push(ContactLink {
236 contact_id,
237 body_id_a: edge_body_a,
238 body_id_b: edge_body_b,
239 });
240
241 let contact = &mut world.contacts[contact_id as usize];
242 contact.island_id = island_id;
243 contact.island_index = island_index;
244
245 validate_island(world, island_id);
246}
247
248pub fn link_contact(world: &mut World, contact_id: i32) {
251 use crate::contact::contact_flags::TOUCHING;
252 use crate::solver_set::DISABLED_SET;
253
254 let (body_id_a, body_id_b) = {
255 let contact = &world.contacts[contact_id as usize];
256 debug_assert!(contact.flags & TOUCHING != 0);
257 (contact.edges[0].body_id, contact.edges[1].body_id)
258 };
259
260 let set_a = world.bodies[body_id_a as usize].set_index;
261 let set_b = world.bodies[body_id_b as usize].set_index;
262
263 debug_assert!(set_a != DISABLED_SET && set_b != DISABLED_SET);
264 debug_assert!(set_a != crate::solver_set::STATIC_SET || set_b != crate::solver_set::STATIC_SET);
265
266 if set_a == AWAKE_SET && set_b >= FIRST_SLEEPING_SET {
268 crate::solver_set::wake_solver_set(world, set_b);
269 }
270
271 let set_a2 = world.bodies[body_id_a as usize].set_index;
273 let set_b2 = world.bodies[body_id_b as usize].set_index;
274 if set_b2 == AWAKE_SET && set_a2 >= FIRST_SLEEPING_SET {
275 crate::solver_set::wake_solver_set(world, set_a2);
276 }
277
278 let island_id_a = world.bodies[body_id_a as usize].island_id;
279 let island_id_b = world.bodies[body_id_b as usize].island_id;
280
281 debug_assert!(
283 world.bodies[body_id_a as usize].set_index != crate::solver_set::STATIC_SET
284 || island_id_a == NULL_INDEX
285 );
286 debug_assert!(
287 world.bodies[body_id_b as usize].set_index != crate::solver_set::STATIC_SET
288 || island_id_b == NULL_INDEX
289 );
290 debug_assert!(island_id_a != NULL_INDEX || island_id_b != NULL_INDEX);
291
292 let final_island_id = merge_islands(world, island_id_a, island_id_b);
294
295 add_contact_to_island(world, final_island_id, contact_id);
297}
298
299pub fn unlink_contact(world: &mut World, contact_id: i32) {
302 let (island_id, remove_index) = {
303 let contact = &world.contacts[contact_id as usize];
304 debug_assert!(contact.island_id != NULL_INDEX);
305 (contact.island_id, contact.island_index)
306 };
307
308 {
310 let island = &mut world.islands[island_id as usize];
311 debug_assert!(0 <= remove_index && (remove_index as usize) < island.contacts.len());
312 debug_assert!(island.contacts[remove_index as usize].contact_id == contact_id);
313
314 let moved_index = island.contacts.len() as i32 - 1;
315 island.contacts.swap_remove(remove_index as usize);
316 if moved_index != remove_index {
317 let moved_contact_id = island.contacts[remove_index as usize].contact_id;
319 let moved_contact = &mut world.contacts[moved_contact_id as usize];
320 debug_assert!(moved_contact.island_index == moved_index);
321 moved_contact.island_index = remove_index;
322 }
323 }
324
325 let contact = &mut world.contacts[contact_id as usize];
326 contact.island_id = NULL_INDEX;
327 contact.island_index = NULL_INDEX;
328 world.islands[island_id as usize].constraint_remove_count += 1;
329
330 validate_island(world, island_id);
331}
332
333fn add_joint_to_island(world: &mut World, island_id: i32, joint_id: i32) {
335 let (edge_body_a, edge_body_b) = {
336 let joint = &world.joints[joint_id as usize];
337 debug_assert!(joint.island_id == NULL_INDEX);
338 debug_assert!(joint.island_index == NULL_INDEX);
339 (joint.edges[0].body_id, joint.edges[1].body_id)
340 };
341
342 let island = &mut world.islands[island_id as usize];
343
344 let island_index = island.joints.len() as i32;
345 island.joints.push(JointLink {
346 joint_id,
347 body_id_a: edge_body_a,
348 body_id_b: edge_body_b,
349 });
350
351 let joint = &mut world.joints[joint_id as usize];
352 joint.island_id = island_id;
353 joint.island_index = island_index;
354
355 validate_island(world, island_id);
356}
357
358pub fn link_joint(world: &mut World, joint_id: i32) {
360 use crate::types::BodyType;
361
362 let (body_id_a, body_id_b) = {
363 let joint = &world.joints[joint_id as usize];
364 (joint.edges[0].body_id, joint.edges[1].body_id)
365 };
366
367 debug_assert!(
368 world.bodies[body_id_a as usize].type_ == BodyType::Dynamic
369 || world.bodies[body_id_b as usize].type_ == BodyType::Dynamic
370 );
371
372 let set_a = world.bodies[body_id_a as usize].set_index;
373 let set_b = world.bodies[body_id_b as usize].set_index;
374
375 if set_a == AWAKE_SET && set_b >= FIRST_SLEEPING_SET {
376 crate::solver_set::wake_solver_set(world, set_b);
377 } else if set_b == AWAKE_SET && set_a >= FIRST_SLEEPING_SET {
378 crate::solver_set::wake_solver_set(world, set_a);
379 }
380
381 let island_id_a = world.bodies[body_id_a as usize].island_id;
382 let island_id_b = world.bodies[body_id_b as usize].island_id;
383
384 debug_assert!(island_id_a != NULL_INDEX || island_id_b != NULL_INDEX);
385
386 let final_island_id = merge_islands(world, island_id_a, island_id_b);
388
389 add_joint_to_island(world, final_island_id, joint_id);
391}
392
393pub fn unlink_joint(world: &mut World, joint_id: i32) {
395 let (island_id, remove_index) = {
396 let joint = &world.joints[joint_id as usize];
397 if joint.island_id == NULL_INDEX {
398 return;
399 }
400 (joint.island_id, joint.island_index)
401 };
402
403 {
405 let island = &mut world.islands[island_id as usize];
406 debug_assert!(0 <= remove_index && (remove_index as usize) < island.joints.len());
407 debug_assert!(island.joints[remove_index as usize].joint_id == joint_id);
408
409 let moved_index = island.joints.len() as i32 - 1;
410 island.joints.swap_remove(remove_index as usize);
411 if moved_index != remove_index {
412 let moved_joint_id = island.joints[remove_index as usize].joint_id;
414 let moved_joint = &mut world.joints[moved_joint_id as usize];
415 debug_assert!(moved_joint.island_index == moved_index);
416 moved_joint.island_index = remove_index;
417 }
418 }
419
420 let joint = &mut world.joints[joint_id as usize];
421 joint.island_id = NULL_INDEX;
422 joint.island_index = NULL_INDEX;
423 world.islands[island_id as usize].constraint_remove_count += 1;
424
425 validate_island(world, island_id);
426}
427
428pub fn validate_island(world: &World, island_id: i32) {
433 if !cfg!(debug_assertions) {
435 return;
436 }
437
438 if island_id == NULL_INDEX {
439 return;
440 }
441
442 let island = &world.islands[island_id as usize];
443 debug_assert!(island.island_id == island_id);
444 debug_assert!(island.set_index != NULL_INDEX);
445
446 {
447 debug_assert!(!island.bodies.is_empty());
448 debug_assert!(island.bodies.len() as i32 <= world.body_id_pool.id_count());
449
450 for (i, &body_id) in island.bodies.iter().enumerate() {
451 let body = &world.bodies[body_id as usize];
452 debug_assert!(body.island_id == island_id);
453 debug_assert!(body.island_index == i as i32);
454 debug_assert!(body.set_index == island.set_index);
455 let _ = (body, i);
456 }
457 }
458
459 if !island.contacts.is_empty() {
460 debug_assert!(island.contacts.len() as i32 <= world.contact_id_pool.id_count());
461
462 for (i, link) in island.contacts.iter().enumerate() {
463 let contact = &world.contacts[link.contact_id as usize];
464 debug_assert!(contact.set_index == island.set_index);
465 debug_assert!(contact.island_id == island_id);
466 debug_assert!(contact.island_index == i as i32);
467 let _ = (contact, i);
468 }
469 }
470
471 if !island.joints.is_empty() {
472 debug_assert!(island.joints.len() as i32 <= world.joint_id_pool.id_count());
473
474 for (i, link) in island.joints.iter().enumerate() {
475 let joint = &world.joints[link.joint_id as usize];
476 debug_assert!(joint.set_index == island.set_index);
477 debug_assert!(joint.island_id == island_id);
478 debug_assert!(joint.island_index == i as i32);
479 let _ = (joint, i);
480 }
481 }
482}
483
484fn island_find_parent(parents: &mut [i32], mut node: i32) -> i32 {
487 while parents[node as usize] != node {
490 let grand_parent = parents[parents[node as usize] as usize];
491 parents[node as usize] = grand_parent;
492 node = grand_parent;
493 }
494
495 node
496}
497
498fn island_union(
502 parents: &mut [i32],
503 ranks: &mut [i32],
504 node1: i32,
505 node2: i32,
506 contact_counts: &mut [i32],
507 joint_counts: &mut [i32],
508) {
509 let root1 = island_find_parent(parents, node1);
510 let root2 = island_find_parent(parents, node2);
511 if root1 != root2 {
512 if ranks[root1 as usize] < ranks[root2 as usize] {
513 parents[root1 as usize] = root2;
514 contact_counts[root2 as usize] += contact_counts[root1 as usize];
515 joint_counts[root2 as usize] += joint_counts[root1 as usize];
516 } else if ranks[root1 as usize] > ranks[root2 as usize] {
517 parents[root2 as usize] = root1;
518 contact_counts[root1 as usize] += contact_counts[root2 as usize];
519 joint_counts[root1 as usize] += joint_counts[root2 as usize];
520 } else {
521 parents[root2 as usize] = root1;
522 ranks[root1 as usize] += 1;
523 contact_counts[root1 as usize] += contact_counts[root2 as usize];
524 joint_counts[root1 as usize] += joint_counts[root2 as usize];
525 }
526 }
527}
528
529pub fn split_island(world: &mut World, base_id: i32) {
537 debug_assert!(world.islands[base_id as usize].constraint_remove_count > 0);
538 debug_assert!(world.islands[base_id as usize].set_index == AWAKE_SET);
539
540 validate_island(world, base_id);
541
542 let base_body_ids = std::mem::take(&mut world.islands[base_id as usize].bodies);
546 let base_contacts = std::mem::take(&mut world.islands[base_id as usize].contacts);
547 let base_joints = std::mem::take(&mut world.islands[base_id as usize].joints);
548
549 let base_body_count = base_body_ids.len();
550
551 let mut parents: Vec<i32> = (0..base_body_count as i32).collect();
553 let mut contact_counts: Vec<i32> = vec![0; base_body_count];
554 let mut joint_counts: Vec<i32> = vec![0; base_body_count];
555 let mut ranks: Vec<i32> = vec![0; base_body_count];
556
557 for link in &base_contacts {
559 let island_index_a = world.bodies[link.body_id_a as usize].island_index;
560 let island_index_b = world.bodies[link.body_id_b as usize].island_index;
561
562 if island_index_a != NULL_INDEX && island_index_b != NULL_INDEX {
564 island_union(
565 &mut parents,
566 &mut ranks,
567 island_index_a,
568 island_index_b,
569 &mut contact_counts,
570 &mut joint_counts,
571 );
572 let root = island_find_parent(&mut parents, island_index_a);
573 contact_counts[root as usize] += 1;
574 } else {
575 let island_index = if island_index_a != NULL_INDEX {
576 island_index_a
577 } else {
578 island_index_b
579 };
580 let root = island_find_parent(&mut parents, island_index);
581 contact_counts[root as usize] += 1;
582 }
583 }
584
585 for link in &base_joints {
587 let island_index_a = world.bodies[link.body_id_a as usize].island_index;
588 let island_index_b = world.bodies[link.body_id_b as usize].island_index;
589
590 if island_index_a != NULL_INDEX && island_index_b != NULL_INDEX {
592 island_union(
593 &mut parents,
594 &mut ranks,
595 island_index_a,
596 island_index_b,
597 &mut contact_counts,
598 &mut joint_counts,
599 );
600 let root = island_find_parent(&mut parents, island_index_a);
601 joint_counts[root as usize] += 1;
602 } else {
603 let island_index = if island_index_a != NULL_INDEX {
604 island_index_a
605 } else {
606 island_index_b
607 };
608 let root = island_find_parent(&mut parents, island_index);
609 joint_counts[root as usize] += 1;
610 }
611 }
612
613 let mut component_count = 0usize;
615 #[allow(clippy::needless_range_loop)]
616 for i in 0..base_body_count {
617 let root = island_find_parent(&mut parents, i as i32);
618 parents[i] = root;
619 if root == i as i32 {
620 component_count += 1;
621 }
622 }
623
624 if component_count == 1 {
626 let island = &mut world.islands[base_id as usize];
627 island.constraint_remove_count = 0;
628 island.bodies = base_body_ids;
629 island.contacts = base_contacts;
630 island.joints = base_joints;
631 return;
632 }
633
634 let mut root_map: Vec<i32> = vec![NULL_INDEX; base_body_count];
636
637 let mut component_body_counts: Vec<i32> = vec![0; component_count];
638 let mut component_contact_counts: Vec<i32> = vec![0; component_count];
639 let mut component_joint_counts: Vec<i32> = vec![0; component_count];
640 let mut island_count = 0usize;
641
642 #[allow(clippy::needless_range_loop)]
645 for i in 0..base_body_count {
646 let root_index = parents[i] as usize;
647 if root_map[root_index] == NULL_INDEX {
648 root_map[root_index] = island_count as i32;
649 component_body_counts[island_count] = 0;
650 component_contact_counts[island_count] = contact_counts[root_index];
651 component_joint_counts[island_count] = joint_counts[root_index];
652 island_count += 1;
653 }
654
655 component_body_counts[root_map[root_index] as usize] += 1;
656 }
657
658 debug_assert!(island_count == component_count);
659
660 let mut island_ids: Vec<i32> = Vec::with_capacity(island_count);
662
663 for i in 0..island_count {
665 let new_island_id = create_island(world, AWAKE_SET);
666 island_ids.push(new_island_id);
667
668 let new_island = &mut world.islands[new_island_id as usize];
670 new_island.bodies.reserve(component_body_counts[i] as usize);
671 new_island
672 .contacts
673 .reserve(component_contact_counts[i] as usize);
674 new_island
675 .joints
676 .reserve(component_joint_counts[i] as usize);
677 }
678
679 for (i, &body_id) in base_body_ids.iter().enumerate() {
681 let root = island_find_parent(&mut parents, i as i32);
682 let new_island_id = island_ids[root_map[root as usize] as usize];
683
684 let island_index = world.islands[new_island_id as usize].bodies.len() as i32;
685 let body = &mut world.bodies[body_id as usize];
686 body.island_id = new_island_id;
687 body.island_index = island_index;
688
689 world.islands[new_island_id as usize].bodies.push(body_id);
690 }
691
692 for link in &base_contacts {
694 let island_id_a = world.bodies[link.body_id_a as usize].island_id;
696 let target_island_id = if island_id_a != NULL_INDEX {
697 island_id_a
698 } else {
699 world.bodies[link.body_id_b as usize].island_id
700 };
701
702 let island_index = world.islands[target_island_id as usize].contacts.len() as i32;
703 let contact = &mut world.contacts[link.contact_id as usize];
704 contact.island_id = target_island_id;
705 contact.island_index = island_index;
706
707 world.islands[target_island_id as usize]
708 .contacts
709 .push(*link);
710 }
711
712 for link in &base_joints {
714 let island_id_a = world.bodies[link.body_id_a as usize].island_id;
716 let target_island_id = if island_id_a != NULL_INDEX {
717 island_id_a
718 } else {
719 world.bodies[link.body_id_b as usize].island_id
720 };
721
722 let island_index = world.islands[target_island_id as usize].joints.len() as i32;
723 let joint = &mut world.joints[link.joint_id as usize];
724 joint.island_id = target_island_id;
725 joint.island_index = island_index;
726
727 world.islands[target_island_id as usize].joints.push(*link);
728 }
729
730 destroy_island(world, base_id);
732}