1use crate::body::{body_flags, remove_body_sim, BodySim, BodyState, IDENTITY_BODY_STATE};
7use crate::constants::GRAPH_COLOR_COUNT;
8use crate::constraint_graph::{
9 add_contact_to_graph, add_joint_to_graph, remove_joint_from_graph, OVERFLOW_INDEX,
10};
11use crate::contact::{contact_flags, ContactSim};
12use crate::core::NULL_INDEX;
13use crate::island::IslandSim;
14use crate::joint::JointSim;
15use crate::world::World;
16
17pub const STATIC_SET: i32 = 0;
21pub const DISABLED_SET: i32 = 1;
23pub const AWAKE_SET: i32 = 2;
26pub const FIRST_SLEEPING_SET: i32 = 3;
30
31#[derive(Debug, Clone, Default)]
40pub struct SolverSet {
41 pub body_sims: Vec<BodySim>,
43
44 pub body_states: Vec<BodyState>,
46
47 pub joint_sims: Vec<JointSim>,
49
50 pub contact_sims: Vec<ContactSim>,
53
54 pub island_sims: Vec<IslandSim>,
59
60 pub set_index: i32,
63}
64
65pub fn destroy_solver_set(world: &mut World, set_index: i32) {
67 let set = &mut world.solver_sets[set_index as usize];
68 *set = SolverSet::default();
69 set.set_index = NULL_INDEX;
70 world.solver_set_id_pool.free_id(set_index);
71}
72
73pub fn wake_solver_set(world: &mut World, set_index: i32) {
82 debug_assert!(set_index >= FIRST_SLEEPING_SET);
83
84 let body_count = world.solver_sets[set_index as usize].body_sims.len();
85 for i in 0..body_count {
86 let sim_src = world.solver_sets[set_index as usize].body_sims[i];
87 let body_id = sim_src.body_id;
88
89 debug_assert!(world.bodies[body_id as usize].set_index == set_index);
90 let awake_body_count = world.solver_sets[AWAKE_SET as usize].body_sims.len() as i32;
91 let flags = {
92 let body = &mut world.bodies[body_id as usize];
93 body.set_index = AWAKE_SET;
94 body.local_index = awake_body_count;
95
96 body.sleep_time = 0.0;
98 body.flags
99 };
100
101 world.solver_sets[AWAKE_SET as usize]
102 .body_sims
103 .push(sim_src);
104
105 let mut state = IDENTITY_BODY_STATE;
106 state.flags = flags;
107 world.solver_sets[AWAKE_SET as usize]
108 .body_states
109 .push(state);
110
111 let mut contact_key = world.bodies[body_id as usize].head_contact_key;
113 while contact_key != NULL_INDEX {
114 let edge_index = contact_key & 1;
115 let contact_id = contact_key >> 1;
116
117 contact_key = world.contacts[contact_id as usize].edges[edge_index as usize].next_key;
118
119 if world.contacts[contact_id as usize].set_index != DISABLED_SET {
120 debug_assert!(
121 world.contacts[contact_id as usize].set_index == AWAKE_SET
122 || world.contacts[contact_id as usize].set_index == set_index
123 );
124 continue;
125 }
126
127 let local_index = world.contacts[contact_id as usize].local_index;
128 let contact_sim =
129 world.solver_sets[DISABLED_SET as usize].contact_sims[local_index as usize];
130
131 debug_assert!(
132 (world.contacts[contact_id as usize].flags & contact_flags::TOUCHING) == 0
133 && contact_sim.manifold.point_count == 0
134 );
135
136 let awake_contact_count =
137 world.solver_sets[AWAKE_SET as usize].contact_sims.len() as i32;
138 {
139 let contact = &mut world.contacts[contact_id as usize];
140 contact.set_index = AWAKE_SET;
141 contact.local_index = awake_contact_count;
142 }
143 world.solver_sets[AWAKE_SET as usize]
144 .contact_sims
145 .push(contact_sim);
146
147 let moved_index =
148 world.solver_sets[DISABLED_SET as usize].contact_sims.len() as i32 - 1;
149 world.solver_sets[DISABLED_SET as usize]
150 .contact_sims
151 .swap_remove(local_index as usize);
152 if moved_index != local_index {
153 let moved_id = world.solver_sets[DISABLED_SET as usize].contact_sims
155 [local_index as usize]
156 .contact_id;
157 let moved_contact = &mut world.contacts[moved_id as usize];
158 debug_assert!(moved_contact.local_index == moved_index);
159 moved_contact.local_index = local_index;
160 }
161 }
162 }
163
164 {
166 let contact_count = world.solver_sets[set_index as usize].contact_sims.len();
167 for i in 0..contact_count {
168 let contact_sim = world.solver_sets[set_index as usize].contact_sims[i];
169 let contact_id = contact_sim.contact_id;
170 debug_assert!(world.contacts[contact_id as usize].flags & contact_flags::TOUCHING != 0);
171 debug_assert!(contact_sim.sim_flags & contact_flags::SIM_TOUCHING != 0);
172 debug_assert!(contact_sim.manifold.point_count > 0);
173 debug_assert!(world.contacts[contact_id as usize].set_index == set_index);
174 world.contacts[contact_id as usize].set_index = AWAKE_SET;
175 add_contact_to_graph(world, contact_sim, contact_id);
176 }
177 }
178
179 {
181 let joint_count = world.solver_sets[set_index as usize].joint_sims.len();
182 for i in 0..joint_count {
183 let joint_sim = world.solver_sets[set_index as usize].joint_sims[i];
184 let joint_id = joint_sim.joint_id;
185 debug_assert!(world.joints[joint_id as usize].set_index == set_index);
186 add_joint_to_graph(world, joint_sim, joint_id);
187 world.joints[joint_id as usize].set_index = AWAKE_SET;
188 }
189 }
190
191 {
196 let island_count = world.solver_sets[set_index as usize].island_sims.len();
197 for i in 0..island_count {
198 let island_src = world.solver_sets[set_index as usize].island_sims[i];
199 let awake_island_count = world.solver_sets[AWAKE_SET as usize].island_sims.len() as i32;
200 {
201 let island = &mut world.islands[island_src.island_id as usize];
202 island.set_index = AWAKE_SET;
203 island.local_index = awake_island_count;
204 }
205 world.solver_sets[AWAKE_SET as usize]
206 .island_sims
207 .push(island_src);
208 }
209 }
210
211 destroy_solver_set(world, set_index);
213}
214
215#[allow(dead_code)]
219pub fn try_sleep_island(world: &mut World, island_id: i32) {
220 debug_assert!(world.islands[island_id as usize].set_index == AWAKE_SET);
221
222 if world.islands[island_id as usize].constraint_remove_count > 0
225 && world.islands[island_id as usize].bodies.len() > 1
226 {
227 return;
228 }
229
230 let sleep_set_id = world.solver_set_id_pool.alloc_id();
238 if sleep_set_id == world.solver_sets.len() as i32 {
239 let set = SolverSet {
240 set_index: NULL_INDEX,
241 ..SolverSet::default()
242 };
243 world.solver_sets.push(set);
244 }
245
246 {
247 let (body_cap, contact_cap, joint_cap) = {
248 let island = &world.islands[island_id as usize];
249 (
250 island.bodies.len(),
251 island.contacts.len(),
252 island.joints.len(),
253 )
254 };
255 let sleep_set = &mut world.solver_sets[sleep_set_id as usize];
256 *sleep_set = SolverSet::default();
257 sleep_set.set_index = sleep_set_id;
258 sleep_set.body_sims.reserve(body_cap);
259 sleep_set.contact_sims.reserve(contact_cap);
260 sleep_set.joint_sims.reserve(joint_cap);
261 }
262
263 debug_assert!({
264 let local = world.islands[island_id as usize].local_index;
265 0 <= local && local < world.solver_sets[AWAKE_SET as usize].island_sims.len() as i32
266 });
267
268 {
271 let island_body_count = world.islands[island_id as usize].bodies.len();
272 for i in 0..island_body_count {
273 let body_id = world.islands[island_id as usize].bodies[i];
274 debug_assert!(world.bodies[body_id as usize].set_index == AWAKE_SET);
275 debug_assert!(world.bodies[body_id as usize].island_id == island_id);
276 debug_assert!(world.bodies[body_id as usize].island_index == i as i32);
277
278 let body_move_index = world.bodies[body_id as usize].body_move_index;
281 if body_move_index != NULL_INDEX {
282 let move_event = &mut world.body_move_events[body_move_index as usize];
283 debug_assert!(move_event.body_id.index1 - 1 == body_id);
284 debug_assert!(
285 move_event.body_id.generation == world.bodies[body_id as usize].generation
286 );
287 move_event.fell_asleep = true;
288 world.bodies[body_id as usize].body_move_index = NULL_INDEX;
289 }
290
291 let awake_body_index = world.bodies[body_id as usize].local_index;
292 let awake_sim =
293 world.solver_sets[AWAKE_SET as usize].body_sims[awake_body_index as usize];
294
295 let sleep_body_index = world.solver_sets[sleep_set_id as usize].body_sims.len() as i32;
297 world.solver_sets[sleep_set_id as usize]
298 .body_sims
299 .push(awake_sim);
300
301 remove_body_sim(
302 &mut world.solver_sets[AWAKE_SET as usize].body_sims,
303 &mut world.bodies,
304 awake_body_index,
305 );
306
307 world.solver_sets[AWAKE_SET as usize]
309 .body_states
310 .swap_remove(awake_body_index as usize);
311
312 {
313 let body = &mut world.bodies[body_id as usize];
314 body.set_index = sleep_set_id;
315 body.local_index = sleep_body_index;
316 }
317
318 let mut contact_key = world.bodies[body_id as usize].head_contact_key;
322 while contact_key != NULL_INDEX {
323 let contact_id = contact_key >> 1;
324 let edge_index = contact_key & 1;
325
326 debug_assert!(
327 world.contacts[contact_id as usize].set_index == AWAKE_SET
328 || world.contacts[contact_id as usize].set_index == DISABLED_SET
329 );
330 contact_key =
331 world.contacts[contact_id as usize].edges[edge_index as usize].next_key;
332
333 if world.contacts[contact_id as usize].set_index == DISABLED_SET {
334 continue;
336 }
337
338 if world.contacts[contact_id as usize].color_index != NULL_INDEX {
339 debug_assert!(
341 world.contacts[contact_id as usize].flags & contact_flags::TOUCHING != 0
342 );
343 continue;
344 }
345
346 let other_edge_index = edge_index ^ 1;
350 let other_body_id =
351 world.contacts[contact_id as usize].edges[other_edge_index as usize].body_id;
352 if world.bodies[other_body_id as usize].set_index == AWAKE_SET {
353 continue;
354 }
355
356 let local_index = world.contacts[contact_id as usize].local_index;
357 let contact_sim =
358 world.solver_sets[AWAKE_SET as usize].contact_sims[local_index as usize];
359
360 debug_assert!(contact_sim.manifold.point_count == 0);
361 debug_assert!(
362 world.contacts[contact_id as usize].flags & contact_flags::TOUCHING == 0
363 );
364
365 let disabled_count =
367 world.solver_sets[DISABLED_SET as usize].contact_sims.len() as i32;
368 {
369 let contact = &mut world.contacts[contact_id as usize];
370 contact.set_index = DISABLED_SET;
371 contact.local_index = disabled_count;
372 }
373 world.solver_sets[DISABLED_SET as usize]
374 .contact_sims
375 .push(contact_sim);
376
377 let moved_index =
378 world.solver_sets[AWAKE_SET as usize].contact_sims.len() as i32 - 1;
379 world.solver_sets[AWAKE_SET as usize]
380 .contact_sims
381 .swap_remove(local_index as usize);
382 if moved_index != local_index {
383 let moved_id = world.solver_sets[AWAKE_SET as usize].contact_sims
385 [local_index as usize]
386 .contact_id;
387 let moved_contact = &mut world.contacts[moved_id as usize];
388 debug_assert!(moved_contact.local_index == moved_index);
389 moved_contact.local_index = local_index;
390 }
391 }
392 }
393 }
394
395 {
398 let island_contact_count = world.islands[island_id as usize].contacts.len();
399 for i in 0..island_contact_count {
400 let contact_id = world.islands[island_id as usize].contacts[i].contact_id;
401 let (color_index, local_index, body_id_a, body_id_b) = {
402 let contact = &world.contacts[contact_id as usize];
403 debug_assert!(contact.set_index == AWAKE_SET);
404 debug_assert!(contact.island_id == island_id);
405 (
406 contact.color_index,
407 contact.local_index,
408 contact.edges[0].body_id,
409 contact.edges[1].body_id,
410 )
411 };
412 debug_assert!((0..GRAPH_COLOR_COUNT).contains(&color_index));
413
414 if color_index != OVERFLOW_INDEX {
416 let color = &mut world.constraint_graph.colors[color_index as usize];
418 color.body_set.clear_bit(body_id_a as u32);
419 color.body_set.clear_bit(body_id_b as u32);
420 }
421
422 let awake_contact_sim = world.constraint_graph.colors[color_index as usize]
423 .contact_sims[local_index as usize];
424
425 let sleep_contact_index =
426 world.solver_sets[sleep_set_id as usize].contact_sims.len() as i32;
427 world.solver_sets[sleep_set_id as usize]
428 .contact_sims
429 .push(awake_contact_sim);
430
431 let moved_index = world.constraint_graph.colors[color_index as usize]
432 .contact_sims
433 .len() as i32
434 - 1;
435 world.constraint_graph.colors[color_index as usize]
436 .contact_sims
437 .swap_remove(local_index as usize);
438 if moved_index != local_index {
439 let moved_id = world.constraint_graph.colors[color_index as usize].contact_sims
441 [local_index as usize]
442 .contact_id;
443 let moved_contact = &mut world.contacts[moved_id as usize];
444 debug_assert!(moved_contact.local_index == moved_index);
445 moved_contact.local_index = local_index;
446 }
447
448 let contact = &mut world.contacts[contact_id as usize];
449 contact.set_index = sleep_set_id;
450 contact.color_index = NULL_INDEX;
451 contact.local_index = sleep_contact_index;
452 }
453 }
454
455 {
458 let island_joint_count = world.islands[island_id as usize].joints.len();
459 for i in 0..island_joint_count {
460 let joint_id = world.islands[island_id as usize].joints[i].joint_id;
461 let (color_index, local_index, body_id_a, body_id_b) = {
462 let joint = &world.joints[joint_id as usize];
463 debug_assert!(joint.set_index == AWAKE_SET);
464 debug_assert!(joint.island_id == island_id);
465 (
466 joint.color_index,
467 joint.local_index,
468 joint.edges[0].body_id,
469 joint.edges[1].body_id,
470 )
471 };
472 debug_assert!((0..GRAPH_COLOR_COUNT).contains(&color_index));
473
474 if color_index != OVERFLOW_INDEX {
475 let color = &mut world.constraint_graph.colors[color_index as usize];
477 color.body_set.clear_bit(body_id_a as u32);
478 color.body_set.clear_bit(body_id_b as u32);
479 }
480
481 let awake_joint_sim = world.constraint_graph.colors[color_index as usize].joint_sims
482 [local_index as usize];
483
484 let sleep_joint_index =
485 world.solver_sets[sleep_set_id as usize].joint_sims.len() as i32;
486 world.solver_sets[sleep_set_id as usize]
487 .joint_sims
488 .push(awake_joint_sim);
489
490 let moved_index = world.constraint_graph.colors[color_index as usize]
491 .joint_sims
492 .len() as i32
493 - 1;
494 world.constraint_graph.colors[color_index as usize]
495 .joint_sims
496 .swap_remove(local_index as usize);
497 if moved_index != local_index {
498 let moved_id = world.constraint_graph.colors[color_index as usize].joint_sims
500 [local_index as usize]
501 .joint_id;
502 let moved_joint = &mut world.joints[moved_id as usize];
503 debug_assert!(moved_joint.local_index == moved_index);
504 moved_joint.local_index = local_index;
505 }
506
507 let joint = &mut world.joints[joint_id as usize];
508 joint.set_index = sleep_set_id;
509 joint.color_index = NULL_INDEX;
510 joint.local_index = sleep_joint_index;
511 }
512 }
513
514 {
516 debug_assert!(world.islands[island_id as usize].set_index == AWAKE_SET);
517
518 let island_index = world.islands[island_id as usize].local_index;
519 world.solver_sets[sleep_set_id as usize]
520 .island_sims
521 .push(IslandSim { island_id });
522
523 let moved_island_index = world.solver_sets[AWAKE_SET as usize].island_sims.len() as i32 - 1;
524 world.solver_sets[AWAKE_SET as usize]
525 .island_sims
526 .swap_remove(island_index as usize);
527 if moved_island_index != island_index {
528 let moved_island_id =
530 world.solver_sets[AWAKE_SET as usize].island_sims[island_index as usize].island_id;
531 let moved_island = &mut world.islands[moved_island_id as usize];
532 debug_assert!(moved_island.local_index == moved_island_index);
533 moved_island.local_index = island_index;
534 }
535
536 let island = &mut world.islands[island_id as usize];
537 island.set_index = sleep_set_id;
538 island.local_index = 0;
539 }
540
541 if world.split_island_id == island_id {
542 world.split_island_id = NULL_INDEX;
543 }
544
545 world.validate_solver_sets();
546}
547
548#[allow(dead_code)]
553pub fn merge_solver_sets(world: &mut World, set_id1: i32, set_id2: i32) {
554 debug_assert!(set_id1 >= FIRST_SLEEPING_SET);
555 debug_assert!(set_id2 >= FIRST_SLEEPING_SET);
556
557 let (set_id1, set_id2) = {
559 let count1 = world.solver_sets[set_id1 as usize].body_sims.len();
560 let count2 = world.solver_sets[set_id2 as usize].body_sims.len();
561 if count1 < count2 {
562 (set_id2, set_id1)
563 } else {
564 (set_id1, set_id2)
565 }
566 };
567
568 {
570 let body_count = world.solver_sets[set_id2 as usize].body_sims.len();
571 for i in 0..body_count {
572 let sim_src = world.solver_sets[set_id2 as usize].body_sims[i];
573 let target_count = world.solver_sets[set_id1 as usize].body_sims.len() as i32;
574 {
575 let body = &mut world.bodies[sim_src.body_id as usize];
576 debug_assert!(body.set_index == set_id2);
577 body.set_index = set_id1;
578 body.local_index = target_count;
579 }
580 world.solver_sets[set_id1 as usize].body_sims.push(sim_src);
581 }
582 }
583
584 {
586 let contact_count = world.solver_sets[set_id2 as usize].contact_sims.len();
587 for i in 0..contact_count {
588 let contact_src = world.solver_sets[set_id2 as usize].contact_sims[i];
589 let target_count = world.solver_sets[set_id1 as usize].contact_sims.len() as i32;
590 {
591 let contact = &mut world.contacts[contact_src.contact_id as usize];
592 debug_assert!(contact.set_index == set_id2);
593 contact.set_index = set_id1;
594 contact.local_index = target_count;
595 }
596 world.solver_sets[set_id1 as usize]
597 .contact_sims
598 .push(contact_src);
599 }
600 }
601
602 {
604 let joint_count = world.solver_sets[set_id2 as usize].joint_sims.len();
605 for i in 0..joint_count {
606 let joint_src = world.solver_sets[set_id2 as usize].joint_sims[i];
607 let target_count = world.solver_sets[set_id1 as usize].joint_sims.len() as i32;
608 {
609 let joint = &mut world.joints[joint_src.joint_id as usize];
610 debug_assert!(joint.set_index == set_id2);
611 joint.set_index = set_id1;
612 joint.local_index = target_count;
613 }
614 world.solver_sets[set_id1 as usize]
615 .joint_sims
616 .push(joint_src);
617 }
618 }
619
620 {
622 let island_count = world.solver_sets[set_id2 as usize].island_sims.len();
623 for i in 0..island_count {
624 let island_src = world.solver_sets[set_id2 as usize].island_sims[i];
625 let target_count = world.solver_sets[set_id1 as usize].island_sims.len() as i32;
626 {
627 let island = &mut world.islands[island_src.island_id as usize];
628 island.set_index = set_id1;
629 island.local_index = target_count;
630 }
631 world.solver_sets[set_id1 as usize]
632 .island_sims
633 .push(island_src);
634 }
635 }
636
637 destroy_solver_set(world, set_id2);
639
640 world.validate_solver_sets();
641}
642
643#[allow(dead_code)]
647pub fn transfer_body(
648 world: &mut World,
649 target_set_index: i32,
650 source_set_index: i32,
651 body_id: i32,
652) {
653 if target_set_index == source_set_index {
654 return;
655 }
656
657 let source_index = world.bodies[body_id as usize].local_index;
658 let mut sim = world.solver_sets[source_set_index as usize].body_sims[source_index as usize];
659
660 let target_index = world.solver_sets[target_set_index as usize].body_sims.len() as i32;
661
662 sim.flags &=
664 !(body_flags::IS_FAST | body_flags::IS_SPEED_CAPPED | body_flags::HAD_TIME_OF_IMPACT);
665 world.solver_sets[target_set_index as usize]
666 .body_sims
667 .push(sim);
668
669 remove_body_sim(
671 &mut world.solver_sets[source_set_index as usize].body_sims,
672 &mut world.bodies,
673 source_index,
674 );
675
676 if source_set_index == AWAKE_SET {
677 world.solver_sets[AWAKE_SET as usize]
678 .body_states
679 .swap_remove(source_index as usize);
680 } else if target_set_index == AWAKE_SET {
681 let mut state = IDENTITY_BODY_STATE;
682 state.flags = world.bodies[body_id as usize].flags;
683 world.solver_sets[AWAKE_SET as usize]
684 .body_states
685 .push(state);
686 }
687
688 let body = &mut world.bodies[body_id as usize];
689 body.set_index = target_set_index;
690 body.local_index = target_index;
691}
692
693#[allow(dead_code)]
697pub fn transfer_joint(
698 world: &mut World,
699 target_set_index: i32,
700 source_set_index: i32,
701 joint_id: i32,
702) {
703 if target_set_index == source_set_index {
704 return;
705 }
706
707 let (local_index, color_index) = {
708 let joint = &world.joints[joint_id as usize];
709 (joint.local_index, joint.color_index)
710 };
711
712 let source_sim = if source_set_index == AWAKE_SET {
714 debug_assert!((0..GRAPH_COLOR_COUNT).contains(&color_index));
715 world.constraint_graph.colors[color_index as usize].joint_sims[local_index as usize]
716 } else {
717 debug_assert!(color_index == NULL_INDEX);
718 world.solver_sets[source_set_index as usize].joint_sims[local_index as usize]
719 };
720
721 if target_set_index == AWAKE_SET {
723 add_joint_to_graph(world, source_sim, joint_id);
724 world.joints[joint_id as usize].set_index = AWAKE_SET;
725 } else {
726 let target_local = world.solver_sets[target_set_index as usize]
727 .joint_sims
728 .len() as i32;
729 {
730 let joint = &mut world.joints[joint_id as usize];
731 joint.set_index = target_set_index;
732 joint.local_index = target_local;
733 joint.color_index = NULL_INDEX;
734 }
735 world.solver_sets[target_set_index as usize]
736 .joint_sims
737 .push(source_sim);
738 }
739
740 if source_set_index == AWAKE_SET {
742 let (body_id_a, body_id_b) = {
743 let joint = &world.joints[joint_id as usize];
744 (joint.edges[0].body_id, joint.edges[1].body_id)
745 };
746 remove_joint_from_graph(world, body_id_a, body_id_b, color_index, local_index);
747 } else {
748 let moved_index = world.solver_sets[source_set_index as usize]
749 .joint_sims
750 .len() as i32
751 - 1;
752 world.solver_sets[source_set_index as usize]
753 .joint_sims
754 .swap_remove(local_index as usize);
755 if moved_index != local_index {
756 let moved_id = world.solver_sets[source_set_index as usize].joint_sims
758 [local_index as usize]
759 .joint_id;
760 world.joints[moved_id as usize].local_index = local_index;
761 }
762 }
763}