Skip to content

Commit 4d2b2f5

Browse files
authored
Improve tunneling prevention by solving static contacts last (#824)
# Objective Currently, static contacts are mixed with dynamic contacts starting from the second graph color. To improve tunneling prevention, it'd be better to reserve some colors just for static contacts, and to solve them last. ## Solution - Increase the `GRAPH_COLOR_COUNT` from 12 to 24 - Reserve some colors just for static contacts, and build static colors from the end to give them higher priority In the future, we could consider using dedicated one-body contact constraints for the static colors to further optimize things.
1 parent d026c05 commit 4d2b2f5

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

src/dynamics/solver/constraint_graph.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,20 @@ use crate::{
3333

3434
use super::contact::ContactConstraint;
3535

36-
/// The maximum number of colors in the constraint graph.
36+
/// The maximum number of [`GraphColor`]s in the [`ConstraintGraph`].
3737
/// Constraints that cannot find a color are added to the overflow set,
3838
/// which is solved on a single thread.
39-
pub const GRAPH_COLOR_COUNT: usize = 12;
39+
pub const GRAPH_COLOR_COUNT: usize = 24;
4040

4141
/// The index of the overflow color in the graph, used for constraints that don't fit
4242
/// the graph color limit. This can happen when a single body is interacting with many other bodies.
4343
pub const COLOR_OVERFLOW_INDEX: usize = GRAPH_COLOR_COUNT - 1;
4444

45+
/// The number of colors with constraints involving two non-static bodies.
46+
/// Leaving constraints involving static bodies to later colors gives higher priority
47+
/// to those constraints, reducing tunneling through static geometry.
48+
pub const DYNAMIC_COLOR_COUNT: usize = GRAPH_COLOR_COUNT - 4;
49+
4550
/// A color in the [`ConstraintGraph`]. Each color is a set of bodies and constraints
4651
/// that can be solved in parallel without race conditions.
4752
///
@@ -171,7 +176,10 @@ impl ConstraintGraph {
171176

172177
// TODO: We could allow forcing overflow by making this optional.
173178
if !is_static1 && !is_static2 {
174-
for i in 0..COLOR_OVERFLOW_INDEX {
179+
// Constraints involving only non-static bodies cannot be in colors reserved
180+
// for constraints involving static bodies. This helps reduce tunneling through
181+
// static geometry by solving static contacts last.
182+
for i in 0..DYNAMIC_COLOR_COUNT {
175183
let color = &mut self.colors[i];
176184
if color.body_set.get(body1.index() as usize)
177185
|| color.body_set.get(body2.index() as usize)
@@ -185,8 +193,8 @@ impl ConstraintGraph {
185193
break;
186194
}
187195
} else if !is_static1 {
188-
// No static contacts in color 0
189-
for i in 1..COLOR_OVERFLOW_INDEX {
196+
// Build static colors from the end to give them higher priority.
197+
for i in (1..COLOR_OVERFLOW_INDEX).rev() {
190198
let color = &mut self.colors[i];
191199
if color.body_set.get(body1.index() as usize) {
192200
continue;
@@ -197,8 +205,8 @@ impl ConstraintGraph {
197205
break;
198206
}
199207
} else if !is_static2 {
200-
// No static contacts in color 0
201-
for i in 1..COLOR_OVERFLOW_INDEX {
208+
// Build static colors from the end to give them higher priority.
209+
for i in (1..COLOR_OVERFLOW_INDEX).rev() {
202210
let color = &mut self.colors[i];
203211
if color.body_set.get(body2.index() as usize) {
204212
continue;

src/tests/determinism_2d.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fn cross_platform_determinism_2d() {
6060
let hash = compute_hash(app.world(), query);
6161

6262
// Update this value if simulation behavior changes.
63-
let expected = 0x543aed6d;
63+
let expected = 0x4fbe94b5;
6464

6565
assert!(
6666
hash == expected,

0 commit comments

Comments
 (0)