1#![allow(dead_code)]
20#![allow(clippy::needless_range_loop)]
22
23use super::integrate::{finalize_bodies, integrate_positions, integrate_velocities};
24use super::StepContext;
25use crate::constants::GRAPH_COLOR_COUNT;
26use crate::constraint_graph::OVERFLOW_INDEX;
27use crate::contact::contact_flags;
28use crate::contact_solver::{
29 apply_restitution, prepare_contacts, solve_contacts, store_impulses, warm_start_contacts,
30 ContactConstraint,
31};
32use crate::core::NULL_INDEX;
33use crate::events::{BodyMoveEvent, ContactHitEvent, JointEvent};
34use crate::id::{BodyId, ContactId, JointId, ShapeId};
35use crate::joint::{get_joint_reaction, prepare_joint, solve_joint, warm_start_joint};
36use crate::math_functions::{make_world_transform, offset_pos, TRANSFORM_IDENTITY};
37use crate::solver_set::AWAKE_SET;
38use crate::types::BodyType;
39use crate::world::World;
40
41const ITERATIONS: i32 = 1;
43const RELAX_ITERATIONS: i32 = 1;
44
45fn prepare_color_joints(world: &mut World, color_index: i32, context: &StepContext) {
48 let count = world.constraint_graph.colors[color_index as usize]
49 .joint_sims
50 .len();
51 for i in 0..count {
52 let mut sim = world.constraint_graph.colors[color_index as usize].joint_sims[i];
53 prepare_joint(world, &mut sim, context);
54 world.constraint_graph.colors[color_index as usize].joint_sims[i] = sim;
55 }
56}
57
58pub fn solve(world: &mut World, context: &StepContext) {
60 world.step_index += 1;
62
63 let awake_body_count = world.solver_sets[AWAKE_SET as usize].body_sims.len();
66 if awake_body_count == 0 {
67 world.broad_phase.validate_no_enlarged();
68 return;
69 }
70
71 let mut bullet_bodies: Vec<i32> = Vec::with_capacity(awake_body_count);
73
74 world.body_move_events.resize(
76 awake_body_count,
77 BodyMoveEvent {
78 user_data: 0,
79 transform: make_world_transform(TRANSFORM_IDENTITY),
80 body_id: BodyId::default(),
81 fell_asleep: false,
82 },
83 );
84
85 let joint_id_capacity = world.joint_id_pool.id_capacity();
88 let contact_id_capacity = world.contact_id_pool.id_capacity();
89 {
90 let task_context = &mut world.task_contexts[0];
91 task_context
92 .joint_state_bit_set
93 .set_bit_count_and_clear(joint_id_capacity as u32);
94 task_context
95 .hit_event_bit_set
96 .set_bit_count_and_clear(contact_id_capacity as u32);
97 task_context.has_hit_events = false;
98 }
99
100 if world.split_island_id != NULL_INDEX {
104 let split_id = world.split_island_id;
105 crate::island::split_island(world, split_id);
106 world.split_island_id = NULL_INDEX;
107 }
108
109 for color_index in 0..OVERFLOW_INDEX {
112 prepare_color_joints(world, color_index, context);
113 }
114
115 let mut color_constraints: Vec<Vec<ContactConstraint>> =
117 (0..GRAPH_COLOR_COUNT).map(|_| Vec::new()).collect();
118 for color_index in 0..GRAPH_COLOR_COUNT as usize {
119 let count = world.constraint_graph.colors[color_index]
122 .contact_sims
123 .len();
124 color_constraints[color_index].resize(count, ContactConstraint::default());
125 }
126 for color_index in 0..OVERFLOW_INDEX as usize {
127 let contacts = &world.constraint_graph.colors[color_index].contact_sims;
128 let states = &world.solver_sets[AWAKE_SET as usize].body_states;
129 prepare_contacts(
130 &mut color_constraints[color_index],
131 contacts,
132 states,
133 context,
134 );
135 }
136
137 prepare_color_joints(world, OVERFLOW_INDEX, context);
140 {
141 let contacts = &world.constraint_graph.colors[OVERFLOW_INDEX as usize].contact_sims;
142 let states = &world.solver_sets[AWAKE_SET as usize].body_states;
143 prepare_contacts(
144 &mut color_constraints[OVERFLOW_INDEX as usize],
145 contacts,
146 states,
147 context,
148 );
149 }
150
151 let sub_step_count = context.sub_step_count;
153 for _sub_step_index in 0..sub_step_count {
154 integrate_velocities(world, context);
156
157 {
161 let world_parts = &mut *world;
162 let graph = &mut world_parts.constraint_graph;
163 let states = &mut world_parts.solver_sets[AWAKE_SET as usize].body_states;
164
165 for joint in graph.colors[OVERFLOW_INDEX as usize].joint_sims.iter_mut() {
166 warm_start_joint(joint, states);
167 }
168 warm_start_contacts(&mut color_constraints[OVERFLOW_INDEX as usize], states);
169
170 for color_index in 0..OVERFLOW_INDEX as usize {
171 for joint in graph.colors[color_index].joint_sims.iter_mut() {
172 warm_start_joint(joint, states);
173 }
174 warm_start_contacts(&mut color_constraints[color_index], states);
175 }
176 }
177
178 for _ in 0..ITERATIONS {
180 let use_bias = true;
181 let world_parts = &mut *world;
182 let graph = &mut world_parts.constraint_graph;
183 let states = &mut world_parts.solver_sets[AWAKE_SET as usize].body_states;
184 let joint_state_bit_set = &mut world_parts.task_contexts[0].joint_state_bit_set;
185
186 for joint in graph.colors[OVERFLOW_INDEX as usize].joint_sims.iter_mut() {
190 solve_joint(joint, context, states, use_bias);
191 }
192 solve_contacts(
193 &mut color_constraints[OVERFLOW_INDEX as usize],
194 states,
195 context,
196 use_bias,
197 );
198
199 for color_index in 0..OVERFLOW_INDEX as usize {
200 for joint in graph.colors[color_index].joint_sims.iter_mut() {
201 solve_joint(joint, context, states, use_bias);
202
203 if (joint.force_threshold < f32::MAX || joint.torque_threshold < f32::MAX)
204 && !joint_state_bit_set.get_bit(joint.joint_id as u32)
205 {
206 let (force, torque) = get_joint_reaction(joint, context.inv_h);
207
208 if force >= joint.force_threshold || torque >= joint.torque_threshold {
211 joint_state_bit_set.set_bit(joint.joint_id as u32);
213 }
214 }
215 }
216 solve_contacts(
217 &mut color_constraints[color_index],
218 states,
219 context,
220 use_bias,
221 );
222 }
223 }
224
225 integrate_positions(world, context);
227
228 for _ in 0..RELAX_ITERATIONS {
230 let use_bias = false;
231 let world_parts = &mut *world;
232 let graph = &mut world_parts.constraint_graph;
233 let states = &mut world_parts.solver_sets[AWAKE_SET as usize].body_states;
234
235 for joint in graph.colors[OVERFLOW_INDEX as usize].joint_sims.iter_mut() {
236 solve_joint(joint, context, states, use_bias);
237 }
238 solve_contacts(
239 &mut color_constraints[OVERFLOW_INDEX as usize],
240 states,
241 context,
242 use_bias,
243 );
244
245 for color_index in 0..OVERFLOW_INDEX as usize {
246 for joint in graph.colors[color_index].joint_sims.iter_mut() {
247 solve_joint(joint, context, states, use_bias);
248 }
249 solve_contacts(
250 &mut color_constraints[color_index],
251 states,
252 context,
253 use_bias,
254 );
255 }
256 }
257 }
258
259 {
261 let world_parts = &mut *world;
262 let states = &mut world_parts.solver_sets[AWAKE_SET as usize].body_states;
263
264 apply_restitution(
265 &mut color_constraints[OVERFLOW_INDEX as usize],
266 states,
267 context,
268 );
269 for color_index in 0..OVERFLOW_INDEX as usize {
270 apply_restitution(&mut color_constraints[color_index], states, context);
271 }
272 }
273
274 {
278 let world_parts = &mut *world;
279 let graph = &mut world_parts.constraint_graph;
280 let task_context = &mut world_parts.task_contexts[0];
281 let neg_hit_threshold = -world_parts.hit_event_threshold;
282
283 store_impulses(
284 &color_constraints[OVERFLOW_INDEX as usize],
285 &mut graph.colors[OVERFLOW_INDEX as usize].contact_sims,
286 );
287
288 for color_index in 0..OVERFLOW_INDEX as usize {
289 store_impulses(
290 &color_constraints[color_index],
291 &mut graph.colors[color_index].contact_sims,
292 );
293
294 for contact_sim in &graph.colors[color_index].contact_sims {
297 if contact_sim.sim_flags & contact_flags::SIM_ENABLE_HIT_EVENT != 0 {
298 for k in 0..contact_sim.manifold.point_count as usize {
299 let mp = &contact_sim.manifold.points[k];
300
301 if mp.normal_velocity < neg_hit_threshold && mp.total_normal_impulse > 0.0 {
304 task_context
305 .hit_event_bit_set
306 .set_bit(contact_sim.contact_id as u32);
307 task_context.has_hit_events = true;
308 break;
309 }
310 }
311 }
312 }
313 }
314 }
315
316 {
320 let awake_island_count = world.solver_sets[AWAKE_SET as usize].island_sims.len();
321 let task_context = &mut world.task_contexts[0];
322 task_context.sensor_hits.clear();
323 task_context
324 .enlarged_sim_bit_set
325 .set_bit_count_and_clear(awake_body_count as u32);
326 task_context
327 .awake_island_bit_set
328 .set_bit_count_and_clear(awake_island_count as u32);
329 task_context.split_island_id = NULL_INDEX;
330 task_context.split_sleep_time = 0.0;
331 }
332
333 finalize_bodies(world, context, &mut bullet_bodies);
336
337 {
339 let world_id = world.world_id;
340 let word_count = world.task_contexts[0].joint_state_bit_set.block_count();
341 for k in 0..word_count {
342 let mut word = world.task_contexts[0].joint_state_bit_set.block(k);
343 while word != 0 {
344 let ctz = word.trailing_zeros();
345 let joint_id = (64 * k + ctz) as i32;
346
347 let joint = &world.joints[joint_id as usize];
348 debug_assert!(joint.set_index == AWAKE_SET);
349
350 let event = JointEvent {
351 joint_id: JointId {
352 index1: joint_id + 1,
353 world0: world_id,
354 generation: joint.generation,
355 },
356 user_data: joint.user_data,
357 };
358
359 world.joint_events.push(event);
360
361 word &= word - 1;
363 }
364 }
365 }
366
367 {
369 debug_assert!(world.contact_hit_events.is_empty());
370
371 if world.task_contexts[0].has_hit_events {
372 let threshold = world.hit_event_threshold;
373 let world_id = world.world_id;
374
375 let word_count = world.task_contexts[0].hit_event_bit_set.block_count();
376 for k in 0..word_count {
377 let mut word = world.task_contexts[0].hit_event_bit_set.block(k);
378 while word != 0 {
379 let ctz = word.trailing_zeros();
380 let contact_id = (64 * k + ctz) as i32;
381
382 let contact = world.contacts[contact_id as usize];
383 debug_assert!(
384 contact.set_index == AWAKE_SET && contact.color_index != NULL_INDEX
385 );
386
387 let contact_sim = &world.constraint_graph.colors[contact.color_index as usize]
388 .contact_sims[contact.local_index as usize];
389
390 let mut approach_speed = threshold;
391 let mut best_point: Option<usize> = None;
392 for p in 0..contact_sim.manifold.point_count as usize {
393 let mp = &contact_sim.manifold.points[p];
394 let point_approach_speed = -mp.normal_velocity;
395
396 if point_approach_speed > approach_speed && mp.total_normal_impulse > 0.0 {
399 approach_speed = point_approach_speed;
400 best_point = Some(p);
401 }
402 }
403
404 if let Some(p) = best_point {
405 let best = contact_sim.manifold.points[p];
406 let normal = contact_sim.manifold.normal;
407
408 let shape_a = &world.shapes[contact_sim.shape_id_a as usize];
409 let shape_b = &world.shapes[contact_sim.shape_id_b as usize];
410
411 let body_a = &world.bodies[shape_a.body_id as usize];
418 let body_b = &world.bodies[shape_b.body_id as usize];
419 let point = if body_a.type_ != BodyType::Static
420 && body_b.type_ == BodyType::Static
421 {
422 let body_sim_b = &world.solver_sets[body_b.set_index as usize]
423 .body_sims[body_b.local_index as usize];
424 offset_pos(body_sim_b.center, best.anchor_b)
425 } else {
426 let body_sim_a = &world.solver_sets[body_a.set_index as usize]
427 .body_sims[body_a.local_index as usize];
428 offset_pos(body_sim_a.center, best.anchor_a)
429 };
430
431 let event = ContactHitEvent {
432 shape_id_a: ShapeId {
433 index1: shape_a.id + 1,
434 world0: world_id,
435 generation: shape_a.generation,
436 },
437 shape_id_b: ShapeId {
438 index1: shape_b.id + 1,
439 world0: world_id,
440 generation: shape_b.generation,
441 },
442 contact_id: ContactId {
443 index1: contact.contact_id + 1,
444 world0: world_id,
445 padding: 0,
446 generation: contact.generation,
447 },
448 point,
449 normal,
450 approach_speed,
451 };
452
453 world.contact_hit_events.push(event);
454 }
455
456 word &= word - 1;
458 }
459 }
460 }
461 }
462
463 {
465 world.broad_phase.validate_no_enlarged();
466
467 let word_count = world.task_contexts[0].enlarged_sim_bit_set.block_count();
473 for k in 0..word_count {
474 let mut word = world.task_contexts[0].enlarged_sim_bit_set.block(k);
475 while word != 0 {
476 let ctz = word.trailing_zeros();
477 let body_sim_index = (64 * k + ctz) as usize;
478
479 let (body_id, sim_flags) = {
480 let body_sim = &world.solver_sets[AWAKE_SET as usize].body_sims[body_sim_index];
481 (body_sim.body_id, body_sim.flags)
482 };
483
484 let mut shape_id = world.bodies[body_id as usize].head_shape_id;
485 if sim_flags
486 & (crate::body::body_flags::IS_BULLET | crate::body::body_flags::IS_FAST)
487 == (crate::body::body_flags::IS_BULLET | crate::body::body_flags::IS_FAST)
488 {
489 while shape_id != NULL_INDEX {
491 let proxy_key = world.shapes[shape_id as usize].proxy_key;
492
493 world.broad_phase.buffer_move(proxy_key);
498
499 shape_id = world.shapes[shape_id as usize].next_shape_id;
500 }
501 } else {
502 while shape_id != NULL_INDEX {
503 if world.shapes[shape_id as usize].enlarged_aabb {
509 let proxy_key = world.shapes[shape_id as usize].proxy_key;
510 let fat_aabb = world.shapes[shape_id as usize].fat_aabb;
511 world.broad_phase.enlarge_proxy(proxy_key, fat_aabb);
512 world.shapes[shape_id as usize].enlarged_aabb = false;
513 }
514
515 shape_id = world.shapes[shape_id as usize].next_shape_id;
516 }
517 }
518
519 word &= word - 1;
521 }
522 }
523
524 world.broad_phase.validate();
525 }
526
527 if !bullet_bodies.is_empty() {
529 for &sim_index in &bullet_bodies {
532 super::continuous::solve_continuous(world, sim_index);
533 }
534
535 for &sim_index in &bullet_bodies {
539 let (body_id, enlarge) = {
540 let bullet_body_sim =
541 &world.solver_sets[AWAKE_SET as usize].body_sims[sim_index as usize];
542 (
543 bullet_body_sim.body_id,
544 bullet_body_sim.flags & crate::body::body_flags::ENLARGE_BOUNDS != 0,
545 )
546 };
547 if !enlarge {
548 continue;
549 }
550
551 world.solver_sets[AWAKE_SET as usize].body_sims[sim_index as usize].flags &=
553 !crate::body::body_flags::ENLARGE_BOUNDS;
554
555 let mut shape_id = world.bodies[body_id as usize].head_shape_id;
556 while shape_id != NULL_INDEX {
557 if !world.shapes[shape_id as usize].enlarged_aabb {
558 shape_id = world.shapes[shape_id as usize].next_shape_id;
559 continue;
560 }
561
562 world.shapes[shape_id as usize].enlarged_aabb = false;
564
565 let proxy_key = world.shapes[shape_id as usize].proxy_key;
566 let proxy_id = crate::broad_phase::proxy_id(proxy_key);
567 debug_assert!(crate::broad_phase::proxy_type(proxy_key) == BodyType::Dynamic);
568
569 debug_assert!(world.broad_phase.moved_proxies[BodyType::Dynamic as usize]
571 .get_bit(proxy_id as u32));
572
573 let fat_aabb = world.shapes[shape_id as usize].fat_aabb;
574 world.broad_phase.trees[BodyType::Dynamic as usize]
575 .enlarge_proxy(proxy_id, fat_aabb);
576
577 shape_id = world.shapes[shape_id as usize].next_shape_id;
578 }
579 }
580 }
581
582 {
585 let hits = std::mem::take(&mut world.task_contexts[0].sensor_hits);
586 for hit in hits {
587 let sensor_index = world.shapes[hit.sensor_id as usize].sensor_index;
588 let generation = world.shapes[hit.visitor_id as usize].generation;
589
590 let shape_ref = crate::sensor::Visitor {
591 shape_id: hit.visitor_id,
592 generation,
593 };
594 world.sensors[sensor_index as usize].hits.push(shape_ref);
595 }
596 }
597
598 if world.enable_sleep {
602 debug_assert!(world.split_island_id == NULL_INDEX);
605 {
606 let task_context = &world.task_contexts[0];
607 if task_context.split_island_id != NULL_INDEX && task_context.split_sleep_time >= 0.0 {
608 debug_assert!(task_context.split_sleep_time > 0.0);
609 world.split_island_id = task_context.split_island_id;
610 }
611 }
612
613 let count = world.solver_sets[AWAKE_SET as usize].island_sims.len();
616 for island_index in (0..count).rev() {
617 if world.task_contexts[0]
618 .awake_island_bit_set
619 .get_bit(island_index as u32)
620 {
621 continue;
623 }
624
625 let island_id =
626 world.solver_sets[AWAKE_SET as usize].island_sims[island_index].island_id;
627
628 crate::solver_set::try_sleep_island(world, island_id);
629 }
630
631 world.validate_solver_sets();
632 }
633}