1use crate::core::NULL_INDEX;
8use crate::solver_set::{AWAKE_SET, DISABLED_SET, FIRST_SLEEPING_SET, STATIC_SET};
9use crate::world::World;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub struct ContactLink {
16 pub contact_id: i32,
17 pub body_id_a: i32,
18 pub body_id_b: i32,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub struct JointLink {
25 pub joint_id: i32,
26 pub body_id_a: i32,
27 pub body_id_b: i32,
28}
29
30#[derive(Debug, Clone)]
37pub struct Island {
38 pub set_index: i32,
40
41 pub local_index: i32,
43
44 pub island_id: i32,
45
46 pub constraint_remove_count: i32,
49
50 pub bodies: Vec<i32>,
51
52 pub contacts: Vec<ContactLink>,
56 pub joints: Vec<JointLink>,
57}
58
59impl Default for Island {
60 fn default() -> Self {
61 Island {
62 set_index: NULL_INDEX,
63 local_index: NULL_INDEX,
64 island_id: NULL_INDEX,
65 constraint_remove_count: 0,
66 bodies: Vec::new(),
67 contacts: Vec::new(),
68 joints: Vec::new(),
69 }
70 }
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub struct IslandSim {
76 pub island_id: i32,
77}
78
79impl Default for IslandSim {
80 fn default() -> Self {
81 IslandSim {
82 island_id: NULL_INDEX,
83 }
84 }
85}
86
87pub fn create_island(world: &mut World, set_index: i32) -> i32 {
90 debug_assert!(set_index == AWAKE_SET || set_index >= FIRST_SLEEPING_SET);
91
92 let island_id = world.island_id_pool.alloc_id();
93
94 if island_id == world.islands.len() as i32 {
95 world.islands.push(Island::default());
96 } else {
97 debug_assert!(world.islands[island_id as usize].set_index == NULL_INDEX);
98 }
99
100 let set = &mut world.solver_sets[set_index as usize];
101 let local_index = set.island_sims.len() as i32;
102 set.island_sims.push(IslandSim { island_id });
103
104 let island = &mut world.islands[island_id as usize];
105 island.set_index = set_index;
106 island.local_index = local_index;
107 island.island_id = island_id;
108 island.bodies = Vec::new();
109 island.contacts = Vec::new();
110 island.joints = Vec::new();
111 island.constraint_remove_count = 0;
112
113 island_id
114}
115
116pub fn destroy_island(world: &mut World, island_id: i32) {
118 if world.split_island_id == island_id {
119 world.split_island_id = NULL_INDEX;
120 }
121
122 let (set_index, local_index) = {
123 let island = &world.islands[island_id as usize];
124 (island.set_index, island.local_index)
125 };
126 let set = &mut world.solver_sets[set_index as usize];
127 {
128 let last_index = set.island_sims.len() - 1;
129 debug_assert!(0 <= local_index && (local_index as usize) <= last_index);
130 let move_island_id = set.island_sims[last_index].island_id;
131 set.island_sims.swap_remove(local_index as usize);
132 world.islands[move_island_id as usize].local_index = local_index;
133 }
134
135 let island = &mut world.islands[island_id as usize];
136 island.bodies = Vec::new();
137 island.contacts = Vec::new();
138 island.joints = Vec::new();
139 island.constraint_remove_count = 0;
140 island.local_index = NULL_INDEX;
141 island.island_id = NULL_INDEX;
142 island.set_index = NULL_INDEX;
143
144 world.island_id_pool.free_id(island_id);
145}
146
147fn merge_islands(world: &mut World, island_id_a: i32, island_id_b: i32) -> i32 {
150 if island_id_a == island_id_b {
151 return island_id_a;
152 }
153 if island_id_a == NULL_INDEX {
154 debug_assert!(island_id_b != NULL_INDEX);
155 return island_id_b;
156 }
157 if island_id_b == NULL_INDEX {
158 debug_assert!(island_id_a != NULL_INDEX);
159 return island_id_a;
160 }
161
162 let (big_id, small_id) = {
163 let count_a = world.islands[island_id_a as usize].bodies.len();
164 let count_b = world.islands[island_id_b as usize].bodies.len();
165 if count_a >= count_b {
166 (island_id_a, island_id_b)
167 } else {
168 (island_id_b, island_id_a)
169 }
170 };
171
172 let small_bodies = std::mem::take(&mut world.islands[small_id as usize].bodies);
173 for body_id in small_bodies {
174 debug_assert!(world.bodies[body_id as usize].island_id == small_id);
175 let island_index = world.islands[big_id as usize].bodies.len() as i32;
176 world.bodies[body_id as usize].island_id = big_id;
177 world.bodies[body_id as usize].island_index = island_index;
178 world.islands[big_id as usize].bodies.push(body_id);
179 }
180
181 let small_contacts = std::mem::take(&mut world.islands[small_id as usize].contacts);
182 for link in small_contacts {
183 let contact = &mut world.contacts[link.contact_id as usize];
184 contact.island_id = big_id;
185 contact.island_index = world.islands[big_id as usize].contacts.len() as i32;
186 world.islands[big_id as usize].contacts.push(link);
187 }
188
189 let small_joints = std::mem::take(&mut world.islands[small_id as usize].joints);
190 for link in small_joints {
191 let joint = &mut world.joints[link.joint_id as usize];
192 joint.island_id = big_id;
193 joint.island_index = world.islands[big_id as usize].joints.len() as i32;
194 world.islands[big_id as usize].joints.push(link);
195 }
196
197 world.islands[big_id as usize].constraint_remove_count +=
198 world.islands[small_id as usize].constraint_remove_count;
199
200 destroy_island(world, small_id);
201 validate_island(world, big_id);
202 big_id
203}
204
205fn add_contact_to_island(world: &mut World, island_id: i32, contact_id: i32) {
207 debug_assert!(world.contacts[contact_id as usize].island_id == NULL_INDEX);
208 debug_assert!(world.contacts[contact_id as usize].island_index == NULL_INDEX);
209
210 let island_index = world.islands[island_id as usize].contacts.len() as i32;
211 let link = ContactLink {
212 contact_id,
213 body_id_a: world.contacts[contact_id as usize].edges[0].body_id,
214 body_id_b: world.contacts[contact_id as usize].edges[1].body_id,
215 };
216
217 world.contacts[contact_id as usize].island_id = island_id;
218 world.contacts[contact_id as usize].island_index = island_index;
219 world.islands[island_id as usize].contacts.push(link);
220
221 validate_island(world, island_id);
222}
223
224pub fn link_contact(world: &mut World, contact_id: i32) {
227 use crate::contact::contact_flags;
228 use crate::solver_set::wake_solver_set;
229
230 debug_assert!((world.contacts[contact_id as usize].flags & contact_flags::TOUCHING) != 0);
231
232 let body_id_a = world.contacts[contact_id as usize].edges[0].body_id;
233 let body_id_b = world.contacts[contact_id as usize].edges[1].body_id;
234
235 let set_a = world.bodies[body_id_a as usize].set_index;
236 let set_b = world.bodies[body_id_b as usize].set_index;
237 debug_assert!(set_a != DISABLED_SET && set_b != DISABLED_SET);
238 debug_assert!(set_a != STATIC_SET || set_b != STATIC_SET);
239
240 if set_a == AWAKE_SET && set_b >= FIRST_SLEEPING_SET {
242 wake_solver_set(world, set_b);
243 }
244
245 let set_a = world.bodies[body_id_a as usize].set_index;
247 let set_b = world.bodies[body_id_b as usize].set_index;
248 if set_b == AWAKE_SET && set_a >= FIRST_SLEEPING_SET {
249 wake_solver_set(world, set_a);
250 }
251
252 let island_id_a = world.bodies[body_id_a as usize].island_id;
253 let island_id_b = world.bodies[body_id_b as usize].island_id;
254
255 debug_assert!(
256 world.bodies[body_id_a as usize].set_index != STATIC_SET || island_id_a == NULL_INDEX
257 );
258 debug_assert!(
259 world.bodies[body_id_b as usize].set_index != STATIC_SET || island_id_b == NULL_INDEX
260 );
261 debug_assert!(island_id_a != NULL_INDEX || island_id_b != NULL_INDEX);
262
263 let final_island_id = merge_islands(world, island_id_a, island_id_b);
264 add_contact_to_island(world, final_island_id, contact_id);
265}
266
267pub fn unlink_contact(world: &mut World, contact_id: i32) {
269 let island_id = world.contacts[contact_id as usize].island_id;
270 debug_assert!(island_id != NULL_INDEX);
271
272 let remove_index = world.contacts[contact_id as usize].island_index;
273 let island = &mut world.islands[island_id as usize];
274 debug_assert!(0 <= remove_index && (remove_index as usize) < island.contacts.len());
275 debug_assert!(island.contacts[remove_index as usize].contact_id == contact_id);
276
277 let moved_index = island.contacts.len() as i32 - 1;
278 island.contacts.swap_remove(remove_index as usize);
279 if moved_index != remove_index {
280 let moved_contact_id = island.contacts[remove_index as usize].contact_id;
281 debug_assert!(world.contacts[moved_contact_id as usize].island_index == moved_index);
282 world.contacts[moved_contact_id as usize].island_index = remove_index;
283 }
284
285 world.contacts[contact_id as usize].island_id = NULL_INDEX;
286 world.contacts[contact_id as usize].island_index = NULL_INDEX;
287 world.islands[island_id as usize].constraint_remove_count += 1;
288
289 validate_island(world, island_id);
290}
291
292fn add_joint_to_island(world: &mut World, island_id: i32, joint_id: i32) {
294 debug_assert!(world.joints[joint_id as usize].island_id == NULL_INDEX);
295 debug_assert!(world.joints[joint_id as usize].island_index == NULL_INDEX);
296
297 let island_index = world.islands[island_id as usize].joints.len() as i32;
298 let link = JointLink {
299 joint_id,
300 body_id_a: world.joints[joint_id as usize].edges[0].body_id,
301 body_id_b: world.joints[joint_id as usize].edges[1].body_id,
302 };
303
304 world.joints[joint_id as usize].island_id = island_id;
305 world.joints[joint_id as usize].island_index = island_index;
306 world.islands[island_id as usize].joints.push(link);
307
308 validate_island(world, island_id);
309}
310
311pub fn link_joint(world: &mut World, joint_id: i32) {
313 use crate::solver_set::wake_solver_set;
314 use crate::types::BodyType;
315
316 let body_id_a = world.joints[joint_id as usize].edges[0].body_id;
317 let body_id_b = world.joints[joint_id as usize].edges[1].body_id;
318
319 debug_assert!(
320 world.bodies[body_id_a as usize].type_ == BodyType::Dynamic
321 || world.bodies[body_id_b as usize].type_ == BodyType::Dynamic
322 );
323
324 let set_a = world.bodies[body_id_a as usize].set_index;
325 let set_b = world.bodies[body_id_b as usize].set_index;
326
327 if set_a == AWAKE_SET && set_b >= FIRST_SLEEPING_SET {
328 wake_solver_set(world, set_b);
329 } else if set_b == AWAKE_SET && set_a >= FIRST_SLEEPING_SET {
330 wake_solver_set(world, set_a);
331 }
332
333 let island_id_a = world.bodies[body_id_a as usize].island_id;
334 let island_id_b = world.bodies[body_id_b as usize].island_id;
335
336 debug_assert!(island_id_a != NULL_INDEX || island_id_b != NULL_INDEX);
337
338 let final_island_id = merge_islands(world, island_id_a, island_id_b);
340
341 add_joint_to_island(world, final_island_id, joint_id);
343}
344
345pub fn unlink_joint(world: &mut World, joint_id: i32) {
347 let island_id = world.joints[joint_id as usize].island_id;
348 if island_id == NULL_INDEX {
349 return;
350 }
351
352 let remove_index = world.joints[joint_id as usize].island_index;
353 let island = &mut world.islands[island_id as usize];
354 debug_assert!(0 <= remove_index && (remove_index as usize) < island.joints.len());
355 debug_assert!(island.joints[remove_index as usize].joint_id == joint_id);
356
357 let moved_index = island.joints.len() as i32 - 1;
358 island.joints.swap_remove(remove_index as usize);
359 if moved_index != remove_index {
360 let moved_joint_id = island.joints[remove_index as usize].joint_id;
362 debug_assert!(world.joints[moved_joint_id as usize].island_index == moved_index);
363 world.joints[moved_joint_id as usize].island_index = remove_index;
364 }
365
366 world.joints[joint_id as usize].island_id = NULL_INDEX;
367 world.joints[joint_id as usize].island_index = NULL_INDEX;
368 world.islands[island_id as usize].constraint_remove_count += 1;
369
370 validate_island(world, island_id);
371}
372
373fn island_find_parent(parents: &mut [i32], mut node: i32) -> i32 {
376 while parents[node as usize] != node {
378 let grand_parent = parents[parents[node as usize] as usize];
379 parents[node as usize] = grand_parent;
380 node = grand_parent;
381 }
382
383 node
384}
385
386fn island_union(
390 parents: &mut [i32],
391 ranks: &mut [i32],
392 node1: i32,
393 node2: i32,
394 contact_counts: &mut [i32],
395 joint_counts: &mut [i32],
396) {
397 let root1 = island_find_parent(parents, node1) as usize;
398 let root2 = island_find_parent(parents, node2) as usize;
399 if root1 != root2 {
400 if ranks[root1] < ranks[root2] {
401 parents[root1] = root2 as i32;
402 contact_counts[root2] += contact_counts[root1];
403 joint_counts[root2] += joint_counts[root1];
404 } else if ranks[root1] > ranks[root2] {
405 parents[root2] = root1 as i32;
406 contact_counts[root1] += contact_counts[root2];
407 joint_counts[root1] += joint_counts[root2];
408 } else {
409 parents[root2] = root1 as i32;
410 ranks[root1] += 1;
411 contact_counts[root1] += contact_counts[root2];
412 joint_counts[root1] += joint_counts[root2];
413 }
414 }
415}
416
417pub fn split_island(world: &mut World, base_id: i32) {
427 debug_assert!(world.islands[base_id as usize].constraint_remove_count > 0);
428 debug_assert!(world.islands[base_id as usize].set_index == AWAKE_SET);
429
430 validate_island(world, base_id);
431
432 let base_body_ids = std::mem::take(&mut world.islands[base_id as usize].bodies);
435 let base_contacts = std::mem::take(&mut world.islands[base_id as usize].contacts);
436 let base_joints = std::mem::take(&mut world.islands[base_id as usize].joints);
437
438 let base_body_count = base_body_ids.len();
439
440 let mut parents: Vec<i32> = (0..base_body_count as i32).collect();
443 let mut contact_counts: Vec<i32> = vec![0; base_body_count];
444 let mut joint_counts: Vec<i32> = vec![0; base_body_count];
445 let mut ranks: Vec<i32> = vec![0; base_body_count];
446
447 for link in &base_contacts {
449 debug_assert!(0 <= link.body_id_a && (link.body_id_a as usize) < world.bodies.len());
450 debug_assert!(0 <= link.body_id_b && (link.body_id_b as usize) < world.bodies.len());
451 let island_index_a = world.bodies[link.body_id_a as usize].island_index;
452 let island_index_b = world.bodies[link.body_id_b as usize].island_index;
453
454 if island_index_a != NULL_INDEX && island_index_b != NULL_INDEX {
456 debug_assert!(0 <= island_index_a && (island_index_a as usize) < base_body_count);
457 debug_assert!(0 <= island_index_b && (island_index_b as usize) < base_body_count);
458 island_union(
459 &mut parents,
460 &mut ranks,
461 island_index_a,
462 island_index_b,
463 &mut contact_counts,
464 &mut joint_counts,
465 );
466 let root = island_find_parent(&mut parents, island_index_a);
467 contact_counts[root as usize] += 1;
468 } else {
469 let island_index = if island_index_a != NULL_INDEX {
470 island_index_a
471 } else {
472 island_index_b
473 };
474 let root = island_find_parent(&mut parents, island_index);
475 contact_counts[root as usize] += 1;
476 }
477 }
478
479 for link in &base_joints {
481 debug_assert!(0 <= link.body_id_a && (link.body_id_a as usize) < world.bodies.len());
482 debug_assert!(0 <= link.body_id_b && (link.body_id_b as usize) < world.bodies.len());
483 let island_index_a = world.bodies[link.body_id_a as usize].island_index;
484 let island_index_b = world.bodies[link.body_id_b as usize].island_index;
485
486 if island_index_a != NULL_INDEX && island_index_b != NULL_INDEX {
488 debug_assert!(0 <= island_index_a && (island_index_a as usize) < base_body_count);
489 debug_assert!(0 <= island_index_b && (island_index_b as usize) < base_body_count);
490 island_union(
491 &mut parents,
492 &mut ranks,
493 island_index_a,
494 island_index_b,
495 &mut contact_counts,
496 &mut joint_counts,
497 );
498 let root = island_find_parent(&mut parents, island_index_a);
499 joint_counts[root as usize] += 1;
500 } else {
501 let island_index = if island_index_a != NULL_INDEX {
502 island_index_a
503 } else {
504 island_index_b
505 };
506 let root = island_find_parent(&mut parents, island_index);
507 joint_counts[root as usize] += 1;
508 }
509 }
510
511 drop(ranks);
513
514 let mut component_count = 0;
516 for i in 0..base_body_count {
517 parents[i] = island_find_parent(&mut parents, i as i32);
518 if parents[i] == i as i32 {
519 component_count += 1;
520 }
521 }
522
523 if component_count == 1 {
525 let base_island = &mut world.islands[base_id as usize];
526 base_island.constraint_remove_count = 0;
527 base_island.bodies = base_body_ids;
528 base_island.contacts = base_contacts;
529 base_island.joints = base_joints;
530 return;
531 }
532
533 let mut root_map: Vec<i32> = vec![NULL_INDEX; base_body_count];
535
536 let mut component_body_counts: Vec<i32> = vec![0; component_count];
537 let mut component_contact_counts: Vec<i32> = vec![0; component_count];
538 let mut component_joint_counts: Vec<i32> = vec![0; component_count];
539 let mut island_count = 0usize;
540
541 for &parent in parents.iter().take(base_body_count) {
544 let root_index = parent as usize;
545 if root_map[root_index] == NULL_INDEX {
546 root_map[root_index] = island_count as i32;
547 component_body_counts[island_count] = 0;
548 component_contact_counts[island_count] = contact_counts[root_index];
549 component_joint_counts[island_count] = joint_counts[root_index];
550 island_count += 1;
551 }
552
553 component_body_counts[root_map[root_index] as usize] += 1;
554 }
555
556 debug_assert!(island_count == component_count);
557
558 let mut island_ids: Vec<i32> = Vec::with_capacity(island_count);
560
561 for i in 0..island_count {
563 let new_island_id = create_island(world, AWAKE_SET);
564 island_ids.push(new_island_id);
565
566 let new_island = &mut world.islands[new_island_id as usize];
568 new_island.bodies.reserve(component_body_counts[i] as usize);
569 new_island
570 .contacts
571 .reserve(component_contact_counts[i] as usize);
572 new_island
573 .joints
574 .reserve(component_joint_counts[i] as usize);
575 }
576
577 for (i, &body_id) in base_body_ids.iter().enumerate() {
579 let root = island_find_parent(&mut parents, i as i32);
580 let new_island_id = island_ids[root_map[root as usize] as usize];
581
582 let island_index = world.islands[new_island_id as usize].bodies.len() as i32;
583 debug_assert!(
584 (island_index as usize) < world.islands[new_island_id as usize].bodies.capacity()
585 );
586 world.islands[new_island_id as usize].bodies.push(body_id);
587
588 let body = &mut world.bodies[body_id as usize];
589 body.island_id = new_island_id;
590 body.island_index = island_index;
591 }
592
593 for link in &base_contacts {
595 let island_id_a = world.bodies[link.body_id_a as usize].island_id;
597 let target_island_id = if island_id_a != NULL_INDEX {
598 island_id_a
599 } else {
600 world.bodies[link.body_id_b as usize].island_id
601 };
602
603 let target_island = &mut world.islands[target_island_id as usize];
604 let island_index = target_island.contacts.len() as i32;
605 debug_assert!((island_index as usize) < target_island.contacts.capacity());
606 target_island.contacts.push(*link);
607
608 let contact = &mut world.contacts[link.contact_id as usize];
609 contact.island_id = target_island_id;
610 contact.island_index = island_index;
611 }
612
613 for link in &base_joints {
615 let island_id_a = world.bodies[link.body_id_a as usize].island_id;
617 let target_island_id = if island_id_a != NULL_INDEX {
618 island_id_a
619 } else {
620 world.bodies[link.body_id_b as usize].island_id
621 };
622
623 let target_island = &mut world.islands[target_island_id as usize];
624 let island_index = target_island.joints.len() as i32;
625 debug_assert!((island_index as usize) < target_island.joints.capacity());
626 target_island.joints.push(*link);
627
628 let joint = &mut world.joints[link.joint_id as usize];
629 joint.island_id = target_island_id;
630 joint.island_index = island_index;
631 }
632
633 destroy_island(world, base_id);
635}
636
637pub fn validate_island(world: &World, island_id: i32) {
642 if island_id == NULL_INDEX {
643 return;
644 }
645
646 let island = &world.islands[island_id as usize];
647 debug_assert!(island.island_id == island_id);
648 debug_assert!(island.set_index != NULL_INDEX);
649
650 {
651 debug_assert!(!island.bodies.is_empty());
652 debug_assert!(island.bodies.len() as i32 <= world.body_id_pool.id_count());
653
654 for (i, &body_id) in island.bodies.iter().enumerate() {
655 let body = &world.bodies[body_id as usize];
656 debug_assert!(body.island_id == island_id);
657 debug_assert!(body.island_index == i as i32);
658 debug_assert!(body.set_index == island.set_index);
659 let _ = (body, i);
660 }
661 }
662
663 if !island.contacts.is_empty() {
664 debug_assert!(island.contacts.len() as i32 <= world.contact_id_pool.id_count());
665
666 for (i, link) in island.contacts.iter().enumerate() {
667 let contact = &world.contacts[link.contact_id as usize];
668 debug_assert!(contact.set_index == island.set_index);
669 debug_assert!(contact.island_id == island_id);
670 debug_assert!(contact.island_index == i as i32);
671 let _ = (contact, i);
672 }
673 }
674
675 if !island.joints.is_empty() {
676 debug_assert!(island.joints.len() as i32 <= world.joint_id_pool.id_count());
677
678 for (i, link) in island.joints.iter().enumerate() {
679 let joint = &world.joints[link.joint_id as usize];
680 debug_assert!(joint.set_index == island.set_index);
681 debug_assert!(joint.island_id == island_id);
682 debug_assert!(joint.island_index == i as i32);
683 let _ = (joint, i);
684 }
685 }
686}