Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bullet] Collision queries with a mesh collider detect things they don't touch even when changing margin #48905

Open
Tracked by #45022
Zylann opened this issue May 20, 2021 · 4 comments

Comments

@Zylann
Copy link
Contributor

Zylann commented May 20, 2021

Godot 3.3
Windows 10 64 bits
Bullet

Issue description:
I'm making a block-based building game prototype, which requires to verify relatively accurately wether or not a shape collides with others.
Some shapes use mesh colliders, but when they do, they keep detecting collisions with other shapes, even if they don't touch. They are right next to each other, so I thought adding a bit of margin, but that didnt have any effect.

I understand the existence of a margin for rigidbody physics, which I am okay with. However in this case I need to do simple collision queries such as "is it colliding, or not, just now" from code. I need precision for these, but I can't seem to make it work. The only workaround I found so far is to scale down the shape until it stops having false positives, however in my prototype I found I have to scale by about 0.81 sometimes until it stops happening (it varies with orientation for some reason, from 0.8 to 0.9). This is not suitable because not only it is too much, but also won't work with more complex shapes.

Minimal reproduction project:
Example project using a PrismMesh as collision shape. You can play with sliders to see when it detects an overlap and when it doesn't. In this example, margin does not have any effect, only scale does, below 0.84.
PrismCollisionQuery.zip

@pouleyKetchoupp pouleyKetchoupp changed the title Collision queries with a mesh collider detect things they don't touch even when changing margin [Bullet] Collision queries with a mesh collider detect things they don't touch even when changing margin May 20, 2021
@pouleyKetchoupp
Copy link
Contributor

Looking at your setup, this result is expected as Bullet uses margins for the shape you test overlap against. It's not just for rigid body physics, but more related to the internal algorithm Bullet uses for performance. Margins are needed for both performance and stability reasons in the collision detection system, including overlap tests.

You can decrease the margin on the collision shape itself to get better accuracy. It can't be 0, but the minimum of 0.001 gives you pretty good results (it detects no overlap with a scale of 0.99). The tradeoff is potential lower performance in some cases, especially if rigid bodies collide with the same shape. But it's possible that you won't see any difference.

Let me know if that helps!

Also for info:
The margin parameter on the query itself is only used for certain shapes in Bullet, not for convex or concave polygon for some reason (in godot physics it does make a difference in all cases). I'm not sure it would help in your case though, because it would detect an overlap even more easily with a value > 0.

@Zylann
Copy link
Contributor Author

Zylann commented May 20, 2021

I see that by default the margin of CollisionPolygon is 0.04, so how come I had to scale by 0.81 in some cases Oo
I thought margin in the query was an override to Shape.margin? If it's not then it should be better documented, the doc just says "the margin for the shape".

So changing it to 0.01 seems better, and likely I'll have to duplicate them so that shapes with a higher margin get used for world physics while duplicates are used temporarily for placement checks.

However I still have to scale down the model... ideally I should not even need to scale it, because that's not usable with some different shapes: what reduces overlap with one shape could create overlaps with others (concave ones for example). But if margin can't be zero does that mean what I need is impossible?

@pouleyKetchoupp
Copy link
Contributor

pouleyKetchoupp commented May 20, 2021

I see that by default the margin of CollisionPolygon is 0.04, so how come I had to scale by 0.81 in some cases Oo

It seems to add up for me. The shape is 1.0 wide, and has margins of 0.04 on both sides, applied whatever the scale. So you would need to make a size decrease of 0.08 in order to avoid overlaps. On top of that, this collision margin seems to be applied on both the query shape and the static body shape, so that's a total of 0.16, which corresponds to a 84% scale. That's what I experience in your scene. It probably gets worse with rotations.

I thought margin in the query was an override to Shape.margin? If it's not then it should be better documented, the doc just says "the margin for the shape".

No, actually it's different (I'm discovering these different parameters with same names and I agree it's not great).
Query margin: This one comes from Godot Physics, it's an optional extra margin for collision checks (in move_and_collide it's used for recovery when stuck, but I'm not sure if it has a different use case in queries).
Shape margin: This one is specific to Bullet and is applied to any collision or overlap, and is only needed because of how the internal collision algorithm works.

That will get much better when godot physics can become the default again and we get rid of shape margins.

However I still have to scale down the model... ideally I should not even need to scale it, because that's not usable with some different shapes: what reduces overlap with one shape could create overlaps with others (concave ones for example). But if margin can't be zero does that mean what I need is impossible?

It's a Bullet limitation unfortunately.

I see different possibilities to get better results though:

  • Use very low shape margins (like 0.001), and scale just a little bit. The precision doesn't seem that bad with these settings. Maybe it will be good enough even with concave shapes.
  • Switch to godot physics so you get the maximum precision for these queries. I know it has other problems right now, but it will get better over time. This issue with margins is exactly one of the reasons why the goal at the moment is to make it more stable and replace Bullet.

Edit: I've added a documentation tag to keep this issue as a reminder to make the query margin documentation clearer.

@Zylann
Copy link
Contributor Author

Zylann commented May 20, 2021

Switching to Godot Physics is quite an bet for a problem like this, because that affects the entire game, both feature-wise and performance-wise (in the longer run, think Space Engineers kind of game).
At the very least I'll surely get to test Godot Physics at the time I migrate my projects to Godot 4, especially my voxel engine because this one tends to hit the limits on every front, so it would be a big stress test^^

I thought of other workarounds, which are painful but I don't see another way without switching/customizing the physics engine:

  • have a second version of the shape which is shrunk by a tiny amount along its normals, and use that for placement checks.
  • not using physics for block placement collision, and instead use litterally an algorithm whose job is to actually compute this accurately, as a super-narrow phase to supplement the engine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants