godot_heightmap_plugin icon indicating copy to clipboard operation
godot_heightmap_plugin copied to clipboard

Holes in collider

Open Zylann opened this issue 4 years ago • 10 comments

As far as I know, it is currently not possible (officially) to make "proper" holes work with the heightmap collider (which is handled by Bullet and not this plugin); Update: Godot Physics also supports heightmaps in 3.4 but not holes yet. I created this issue to keep track of it, because there are a few informations and workarounds to know about this.

For a bit of context, creating holes in a heightmap is usually achieved by painting one with the Hole tool, make a cave mesh in a program like Blender, and place the cave mesh on top of the hole, with a bit of margin to hide seams. Then collision needs to be adjusted.

  • First workaround: when getting close to the hole, the character will start walking on the "seams" of the cave mesh. When that happens, switch collision masks on the player body so that it no longer collides with the heightmap. This will allow to enter the cave.

  • Second workaround: apparently, if you set -INF or NaN values in the heightmap in places where you want a hole before sending the data to PhysicsServer, Bullet will "ignore" collisions with that part of the map. I'm not sure if it actively ignores it, or if it's a result of floating-point math. See comment here: https://www.youtube.com/watch?v=eZuvfIHDeT4&lc=Ugz-XKrZiiE3q8mWCUl4AaABAg.8k7bMi1kQ3g95GPDU-uqKK I haven't seen this documented anywhere yet so it's probably a hack. I also have implemented optimized raycasts in the recent version of Bullet, and I'm not sure if they will take that into account... that said, they use the same triangle processor as normal raycasts do, so maybe they do.

  • Third option, which was the way I thought to do it originally: modify the Bullet heightfield collider to accept a bitmap, so that vertices can be ignored explicitely. Using NaN values would actually be a cheap solution but again if that works already it needs to be documented somewhere.

  • Fourth, if none of the above is possible, another collider backend could be implemented using mesh colliders. These would exclude the dug vertices and be saved as binary files in the terrain data folder. It will probably decrease performance and raise memory usage a lot though.

Zylann avatar Feb 20 '20 18:02 Zylann

@erwincoumans is it expected that the heightfield collider ignores collisions when the processed triangles contain NaN or INF? It's actually quite handy to support holes, just wanted to check if it's a known feature?

Zylann avatar Mar 01 '20 18:03 Zylann

Bullet doesn't support NaN or INF anywhere, but there is one check in GJK to give up finding closest points. I would not rely on that undocumented / unintended behavior. We could implement a mechanism to support holes though. Either implement that and file a PR in Bullet, or file an new feature issue and be patient (may not happen)

erwincoumans avatar Mar 01 '20 18:03 erwincoumans

  • Third option, which was the way I thought to do it originally: modify the Bullet heightfield collider to accept a bitmap, so that vertices can be ignored explicitely. Using NaN values would actually be a cheap solution but again if that works already it needs to be documented somewhere.

Do you think this could be implemented in the new HeightMapShape in Godot Physics? https://github.com/godotengine/godot/pull/47349

jacobcoughenour avatar Apr 21 '21 03:04 jacobcoughenour

Probably yeah

Zylann avatar Apr 21 '21 09:04 Zylann

Would it be possible to set points in the HeightmapShape to a really low height (e.g. -10000, but not -INF or NAN)? It would probably work well enough and make it very difficult to actually collide with the terrain's bottom in areas where you define "holes".

Calinou avatar Dec 23 '21 01:12 Calinou

tested the idea of using NAN for generating holes in the HeightMapShape and it works holes in heightmap Here is another screenshot of in game test holes in heightmap 3

ozzr avatar Jan 17 '22 02:01 ozzr

@ozzr Is this already supported in core Godot, or is this something you implemented in the engine code?

Calinou avatar Jan 17 '22 14:01 Calinou

As highlighted in https://github.com/Zylann/godot_heightmap_plugin/issues/125#issuecomment-593131550, the use of NaN is a hack (at least in Bullet). It was never intented to work, but rather appears to work due to how the physics code is currently written. If not officially supported, it could break anytime the related code is changed.

And it might have unseen side effects. For example I wonder if the bounding box is properly calculated if there are NaNs in the heights.

Zylann avatar Jan 17 '22 14:01 Zylann

@ozzr Is this already supported in core Godot, or is this something you implemented in the engine code?

More than supported I would say that it is a combinent error? It works with both Godot and Bullet Physiscs. Maybe when the Godot Physics was updated with heighmap collision this behaviour ( bug? Error? ) was inherited since I think that Bullet Heightfield was used as reference

ozzr avatar Jan 17 '22 16:01 ozzr

I ran across this when looking for a solution myself.

I have implemented a PhysicsHole.cs script that should be attached to an Area3D.

https://gist.github.com/RepComm/2dbf64bbe7bcaf6ef83b2a9d4b0fd88f

It is short and sweet, and works great assuming you place the cutter shape appropriately. Here is a screenshot of what I'm using it on successfully:

Screenshot from 2024-01-29 21-36-41 Screenshot from 2024-01-29 21-38-49

I have my player's rigidbody set to collision layer 1, and mask to 1 and 2 Terrain collision layer and mask are both 2

PhysicsHole cut layer is set to 2 (to match terrain or other objects that should be cut)

PhysicsHole's Area3D collision mask includes 1 so that it detects the player and other objects that should walk thru holes

Happy hacking.

RepComm avatar Jan 30 '24 03:01 RepComm