-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Heightmap collision shape support in Godot Physics #47347
Conversation
5cfcbd8
to
822aeb7
Compare
CC @Zylann |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not setup for Godot 4 at all yet so I probably wont test this right now, but I can give it a read.
Note, if you want to check the validity and performance of raycasts, you can try [upgrading to Godot 4 and] using this plugin I made which scans the whole screen with raycasts and overlays the resulting normals: https://github.com/Zylann/godot_collision_scanner
About the acceleration grid structure, I hardcoded the Bullet implementation to use a grid of 16 cells. If the Godot version doesn't do that, it will be slower, but from what I remember it is still somewhat acceptable. However if you do very long raycasts that can traverse the whole terrain, that's where performance will be an issue. And this happens very quickly if the shape is pickable by default, which is why I turn that off in my plugin.
Most of my comments are about optimization. I assume it's good otherwise, the algorithm looks the same. I noticed that another C++ physics engine implemented that approach too with different code, if you want to check it out: DanielChappuis/reactphysics3d@d0fa4c2
// Simple case for rays that don't traverse the grid horizontally. | ||
// Just perform a test on the given cell. | ||
int x = CLAMP(begin_x, 0, width - 2); | ||
int z = CLAMP(begin_z, 0, depth - 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimization comment:
Probably worth a different PR/issue, but careful about using the CLAMP
macro. It expands the arguments multiple times, which can sometimes be expensive if the compiler cannot reduce the expression. In this present case I assume any decent compiler will figure it out.
I wonder why this is even a macro tbh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't realize that, it can be dangerous in some cases indeed. For this case it seems like it wouldn't make a huge difference anyway so I can probably leave it this way for readability.
return false; | ||
} | ||
|
||
Vector3 local_begin = p_begin + local_origin; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the ray begins outside of the heightmap? If it starts outside but intersects the AABB it should ideally start on the box hit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what this code does, just before the loop:
// Start inside the grid.
int x_start = CLAMP(x, 0, width - 2);
int z_start = CLAMP(z, 0, depth - 2);
// Adjust initial cross values.
cross_x += delta_x * x_step * (x_start - x);
cross_z += delta_z * z_step * (z_start - z);
x = x_start;
z = z_start;
But I agree it might be better to just reduce the ray itself according to the AABB, to replace this and the check to stop when outside the grid within the loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that it's already skipping the beginning and end of the ray and the current version seems to work fine, I actually haven't added the extra AABB check to change the ray.
} | ||
|
||
// Stop when outside the grid. | ||
if ((x < 0) || (z < 0) || (x >= width - 1) || (z >= depth - 1)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optimization comment:
If we clamp the maximum distance before entering the big loop it could allow to remove this check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually for this one, the check is needed in any case because it could fall outside the grid boundaries and crash otherwise (it's also checked for each quad in Bullet).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea was to clamp the max distance to the exit border so that case would never actually happen. However float imprecision might make this not doable anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it would seem a little bit risky not to have a test at all given that it's based on float calculation and might cause crashes in rare cases.
I tested your PR with my heightmap plugin. Upon opening my project (which has no default scene so it opens on a blank scene), I get this error:
Followed later by this error:
I don't know what these are or if they are even related to your PR, but they happen before opening any scene. I then tested a few things:
|
822aeb7
to
c8dd3c7
Compare
@Zylann I've just pushed changes based on your comments:
Thanks for running the performance tests! Given the x5 performance difference in release_debug, it's definitely worth adding the raycast acceleration based on chunks. I'll add it in a different PR later. |
Btw its working well. Can u bring it into master. Because i need a heightmap collider for my terrain tool ;-) |
@sboron Thanks for testing! This PR still needs a review and approval from a maintainer to be merged. In the meantime you can cherry-pick the commit to your custom branch. |
Thanks! |
I just remembered, we may consider supporting holes using nans/infs at some point, which would make it way easier to have openings in the map Zylann/godot_heightmap_plugin#125 |
@Zylann That sounds useful! Feel free to open a proposal if you want, otherwise I'll just add it to my todo list and write one when I find some time. |
Functional
HeightMapShape3DSW
in Godot Physics 3D, based onbtHeightfieldTerrainShape
from Bullet Physics with a simplified implementation.Test project:
heightmap-4.0.zip