dimforge / dimforge/rapier

Odd cylinder collisions

Open
#305 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
5.7k
Forks
387
Avg merge
4d 23h
Merged PRs (30d)
6

Description

Putting 4 cylinders into a compound collider has some very odd collision behavior:

https://user-images.githubusercontent.com/2748981/160272665-44df6ac1-6935-4393-b9c2-6520e2230d87.mp4

It also happens in other orientations:

https://user-images.githubusercontent.com/2748981/160272672-b79e51eb-29b1-4690-832d-af3222e2112d.mp4

But not for other shapes:

https://user-images.githubusercontent.com/2748981/160272675-494237e3-81dd-472b-93cb-6d51ae7cbf1b.mp4

I've made an easily reproducible example:

```rust
use rapier3d::prelude::*;
use rapier_testbed3d::Testbed;

// This shows a bug when a cylinder is in contact with a very large
// but very thin cuboid. In this case the EPA returns an incorrect
// contact normal, resulting in the cylinder falling through the floor.
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let impulse_joints = ImpulseJointSet::new();
let multibody_joints = MultibodyJointSet::new();

/*
* Ground
*/
let ground_size = 100.1;
let ground_height = 0.1;

let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size).translation(vector![0.0, -ground_height, 0.0]).rotation(vector![0.2, 0.0, 0.0]).friction(0.0);
colliders.insert(collider);

// Build the rigid body.
let rigid_body = RigidBodyBuilder::dynamic().translation(vector![0.0, 3.0, 0.0]);
let handle = bodies.insert(rigid_body);

// Case 1: Bad collisions with cylinders in this orientation
let collider1 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![-1.5, 0.0, 2.0]);
let collider2 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![1.5, 0.0, 2.0]);
let collider3 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![-1.5, 0.0, -2.0]);
let collider4 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![1.5, 0.0, -2.0]);

// Case 2: Also with this orientation
// let collider1 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![-1.5, 0.0, 2.0]).rotation(vector![0.0, 0.0, 90.0_f32.to_radians()]);
// let collider2 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![1.5, 0.0, 2.0]).rotation(vector![0.0, 0.0, 90.0_f32.to_radians()]);
// let collider3 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![-1.5, 0.0, -2.0]).rotation(vector![0.0, 0.0, 90.0_f32.to_radians()]);
// let collider4 = ColliderBuilder::cylinder(0.19, 0.45).translation(vector![1.5, 0.0, -2.0]).rotation(vector![0.0, 0.0, 90.0_f32.to_radians()]);

// Case 3: Same thing doesn't happen with cuboids
// let collider1 = ColliderBuilder::cuboid(0.38, 0.9, 0.9).translation(vector![-1.5, 0.0, 2.0]);
// let collider2 = ColliderBuilder::cuboid(0.38, 0.9, 0.9).translation(vector![1.5, 0.0, 2.0]);
// let collider3 = ColliderBuilder::cuboid(0.38, 0.9, 0.9).translation(vector![-1.5, 0.0, -2.0]);
// let collider4 = ColliderBuilder::cuboid(0.38, 0.9, 0.9).translation(vector![1.5, 0.0, -2.0]);

// Case 4: Or with capsules
// let collider1 = ColliderBuilder::capsule_y(0.19, 0.45).translation(vector![-1.5, 0.0, 2.0]);
// let collider2 = ColliderBuilder::capsule_y(0.19, 0.45).translation(vector![1.5, 0.0, 2.0]);
// let collider3 = ColliderBuilder::capsule_y(0.19, 0.45).translation(vector![-1.5, 0.0, -2.0]);
// let collider4 = ColliderBuilder::capsule_y(0.19, 0.45).translation(vector![1.5, 0.0, -2.0]);

// Case 5: In either orientation
// let collider1 = ColliderBuilder::capsule_x(0.19, 0.45).translation(vector![-1.5, 0.0, 2.0]);
// let collider2 = ColliderBuilder::capsule_x(0.19, 0.45).translation(vector![1.5, 0.0, 2.0]);
// let collider3 = ColliderBuilder::capsule_x(0.19, 0.45).translation(vector![-1.5, 0.0, -2.0]);
// let collider4 = ColliderBuilder::capsule_x(0.19, 0.45).translation(vector![1.5, 0.0, -2.0]);

let shapes = vec![
(collider1.position, collider1.shape),
(collider2.position, collider2.shape),
(collider3.position, collider3.shape),
(collider4.position, collider4.shape),
];
let collider = ColliderBuilder::compound(shapes).restitution(0.2).friction(0.0).build();
colliders.insert_with_parent(collider, handle, &mut bodies);

/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, impulse_joints, multibody_joints);
testbed.look_at(point![100.0, 100.0, 100.0], Point::origin());
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.