godot_heightmap_plugin
godot_heightmap_plugin copied to clipboard
Holes in collider
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
orNaN
values in the heightmap in places where you want a hole before sending the data toPhysicsServer
, 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.
@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?
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)
- 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
Probably yeah
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".
tested the idea of using NAN for generating holes in the HeightMapShape and it works
Here is another screenshot of in game test
@ozzr Is this already supported in core Godot, or is this something you implemented in the engine code?
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.
@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
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:
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.