-
-
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
Fix BVH::ray_query()
numerical precision
#100475
base: master
Are you sure you want to change the base?
Conversation
Could you alternatively just add another function for the i.e. Am wondering if there would there be so many of the old cases (even after converting) that it is better to retain the old API as an alternative, to prevent boiler plate in client code. |
There are not that many places that call BVH raycast. You can actually see them in the diff :
The thing is these 3 functions take themselves ray starts and ray ends as parameters. So I'm not sure wrapping the old logic right in |
Also as usual with these things, do we have any issues where this is causing a problem in practice? If 99% of cases involve a start and end point anyway, whether this calculation is done within the function or externally, it still gets done. And APIs are primarily designed for common use. This is why I was wondering whether it would be better just making the existing function a wrapper, then adding a more accurate version with direction called from this wrapper if use cases / issues warrant it. The other question is whether there are precision issues at these large ranges anyway within the ray cast routine. Remember also that Godot can be compiled with |
Now I understand better your previous comment. For context I'm working on uncapping camera's zfar in the editor (PR to come), after having uncapped it in game already (#99986). This would untap the potential of reverse-z in both single and double precision builds. From the engine's perspective, it's a matter of rewriting in a more precision-friendly way a targeted collection of operations across the rendering and physic logic. This PR is one of them. To your points more specifically :
Anyway your questioning is very valid. I think I will make my zfar-uncapped editor PR out first so people can grasp what it brings, and continue the discussion. |
Ah and just to make this clear :
The precision friendly version requires a ray normal at first hand. This is to avoid So there is no real point to just call the new one from the old as we would have to do this normalization in the wrapper then. |
Yup I understand this - I'm trying to say that if the client code is based around a start and end point (rather than a direction), then this calculation is done somewhere regardless. Whether it is done in the client code or in a wrapper function is a matter of convenience for the user, and reduction of boiler plate. There's no precision gain in using this client side:
versus doing it in a wrapper, no? |
Got you. Correct. For now I've seen Will share here whenever I stumble upon such a case. |
Interestingly Unity raycasts with I found only
In both cases though, it's hard to figure out any usage at very large scales, so we can keep using the non-precision proof version there. Will keep updating this list ☝️ whenever I find any other case. |
The current BVH ray query implementation starts generating false positive / negative hits on small objects when the ray's starting point is farther than ~1000km away from the origin (with single precision build).
As an example, with
p_ray_from = Vector3(1e+7, 0.0, 1e+7)
andp_ray_to = Vector3(5.0, 0.0, 0.0)
,BHV::ray_query()
will hit any 1 meter large object at the origin although the ray doesn't pass there.This PR circumvents the numerical precision issue involved there by making
ray_query()
taking the ray direction and length instead of the ray's endpoint. This avoids the precision-killing operationp_ray_end - p_ray_start
in the function's body.Note that making Godot's raycasting actually precision-proof will require to move away from the ray_start / ray_end pattern (in favor of ray_start / ray_dir / ray_length) at various places in the codebase.
As these additional changes would affect several independant subparts of the engine (physic server, editor picking, scene culling) they will be splitted into specific PRs for easier review :
BVH::ray_query()
#100478BVH::ray_query()
#100480BVH::ray_query()
#100604GodotBroadPhase3D
The current PR lays the foundations, and for now just makes sure non precision-proof code interoperates smoothly with it. This way it can be independently review and merged.