-
-
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
"Navigation map synchronization error" caused internally (by recast?) #85548
Comments
The errors comes from the navigation map edge rasterization that is done to merge the touching navigation mesh edges together. This project geometry error should be fixed and not ignored because it will cause between subtle-barely-noticeable to severe-and-everything-is-broken pathfinding bugs when the wrong navigation mesh edges are merged together and the excess edges are unmerged and rejected. The long-thin edges are not the problem but the mesh has a few faces with very small edges that all fall into the same rasterization cell of the navigation map triggering this error. This is also confirmed by slightly increasing the scale of the mesh to e.g. x1.1 fixing the error immediately because that makes the small edges large enough to not occupy the same cells. Note that while having a matching While both navigation map and ReCast use a cell size for rasterization ReCast uses is to rasterize the triangles of the mesh while the navigation map uses it to rasterize the edge keys to merge polygons with touching edges. It is just that if the cell sizes mismatch from the start errors for users are so common that we added the warning, it does not check more than comparing the two properties. The more hard climb and strong slope the source geometry has the more small regions and polygons ReCast is forced to create. The more small edges the more chances that too many of them fall into the same rasterization cell under certain transforms or when combined with other meshes. We also allow user created or imported navigation meshes not created by ReCast so there are even more options for users to play with a pandora's box and trigger these kind of errors. The navigation mesh is not per se invalid, it is invalid on that specific navigation map in that specific context, like placement of the edge, transform, scale and what not. Depending on source geometry and bake settings ReCast will happily return a navigation mesh with small edges that could result in more of those errors in some context of a navigation map. I think what we could do to mitigate this is to use internally a smaller subdiv of the cell size just for the rasterization. For ReCast encouraging users to use a small cell size would be a voxel amount performance kill but for the navigation map, at least at the moment, we can get away with a smaller cell size for just the rasterization. We do not use the cell size for anything else, e.g. like an octree where a very small cell size would be a performance death again. |
Is there anything a user can do to avoid this issue?
Would that cause this pathfinding issue @TokisanGames noted on my PR, where agents take indirect routes to the target? navRecording.2023-12-01.173953.mp4 |
Yes absolutely. If the wrong navigation mesh polygon edges are merged together or not merged at all the path search will travel nonsensical looking polygon corridors. Technically the path search does everything correct because that is how the pathfinding graph connections are build, it just makes no visual sense for the user that sees the result. The post processing that funnels the path lines on the corridor corners will amplify this stupid path because it makes the path snap to the corners of the corridor polygons. This is how the path search has to travel and builds the polygon corridor in ordered numbers. Also when you zoom-in in the video you can already spot the duplicated edge line that is too close that likely causes the issue.
Making sure that the 2 vertex of an edge never fall into the same cell on the navigation map, and also making sure that never more than 2 edges of the same length occupy the same two grid cells on the navigation map with their 2 vertices (edge key). You can try and tinker with certain NavigationMesh bake properties like max edge length to get different results but that may or may not work for a specific geometry. As mentioned what we can do on the development side is that we by default use a far smaller cell size just for the edge rasterization. E.g. if a user sets 0.25 as cell size we internally multiply by 0.5 and turn it into 0.125 or even less as that can help avoid those smaller rasterization problems that are not immediate breaking bugs, just suboptimal meshlayouts. |
Sorry, I think I wasn't very clear in my question - I wasn't asking about the navigation map, as much as nav mesh baking. Is there anything that a user of |
You can increase the sample distance and also tinker with the sample max error and max edge length in the bake settings. The way to really tackle this in a project is with the source geometry. In general for baking you want to reduce the high frequency in the source geometry to really avoid those issues. When you throw mini voxel-based polygons at ReCast as source geometry you will get many of those mini edges along the rasterization edges. This is a top view of your original demo, at the bottom with the default, and at the top with a static collision plane. The collision plane acts as a "cut-off" plane that basically beheads all the individual voxels along the plane. Notice how ReCast immediately turns the entire jagged problematic side into optimized 1-2 edges. This is the same with those kind of plane blockers on both sides and a larger sample distance and error max. Notice how everything is instantly more optimized and simplified. Yes the navmesh will no longer hug very close to the source geometry but it is still "good enough" and far more performant and less error prone for the pathfinding. In case for Terrain3D I dont expect to add collision blockers like that, but what could be done is to merge adjacent voxels where feasible before adding the triangle faces to the source geometry to reduce the frequency to avoid a lot of the jaggedness and mini polygons. |
If the issue is that there are vertices in the navmesh closer than the navigation map's resolution allows (did I understand correctly?) then would another potential solution be to post-process the navmesh and merge vertices that are closer than cell_size/cell_height? Like by rounding every vertex to the nearest multiple of cell_size/cell_height? |
Sure, at its core it is a rasterization and resolution issue. The two cells on the navigation map are already occupied by two merged edges and the third edge that tries to go into the same edge key space is rejected because it would make no logical sense for the navigation mesh to have a third edge at that place. |
I tried it out. Merging nearby vertices and deleting any polygons that are left with 2 or fewer edges solves most instances. It fixes the long strips at the edge of the mesh. However I still encounter the error in other cases. It seems like baking really can, sometimes, produce edges that are shared by more than 2 polygons: I've modified the reproducer script to print out the coordinates of the edges that are shared by more than 2 polygons. It also generates colored meshes for those polygons so they can be viewed visually. Here are 5 polygons that share edges: red, yellow, green, cyan, blue. The print out makes it clear that the yellow polygon shares exact point coordinates with green and cyan, which it z-fights with:
This is with vertex-merging disabled, so it's definitely not an artifact of rounding vertex to the nearest cell_size/height. The edges of these polygons are longer than cell_size/height, and they're not near the edges of the mesh. The updated reproducer project: |
Contributing a little anecdotal experience: I'm providing a terrain mesh here that I've been experimenting with. The distribution of vertices is a perfectly regular grid with plateaus. The goal with this mesh is to have a 3-unit-height plateau slope be walk-able, while a 6-unit-height plateau wall acts as a cliff as seen here: The mesh pictured has a grid size of 3 units. The closest each flat square represents a 3x3. No vertices are ever closer than 3 units. I have tested with both Mesh and Static Collider building options, but for the sake of this example I'm using a static mesh collider for the nav mesh building. Here are the mesh parameters that build without the synchronization error: With this mesh I have discovered that the only way to build without a synchronization error is to increase the sample max error to the total height between the lowest and highest plateaus. In the example photos above, an AABB is used to only map from height 0 up, which makes the height difference 12 units, and requires a Sample Max Error of 12 to build without synchronization errors. If the AABB is not used, and the full height of the mesh is mapped, a Sample Max Error of 18 is required (highest plateau 12 units, lowest at -6 units). If this is a hard and fast rule, we could probably improve the API to explain why. But is this operating correctly? A sample max error of the ENTIRE height of the map seems a bit odd, and doesn't seem correct compared to the default of 1 unit of sample max error. Mesh File GLTF EDIT FURTHER FINDINGS: TIPS TO WEARY TRAVELERS: Maybe something to this affect could be useful in the documentation. If a nav mesh build experiences this kind of synchronization error, is a possible solution arbitrarily shifting the offset and attempting again? This kind of error is most daunting in some scenario where your levels are procedurally generated, but maybe setting up your baking script so that it attempts different offsets if it experiences a synchronization error, and then holding onto the offset value that DID work for nav mesh rebuilds afterwards (initially attempting the rebake with that value, and then again doing arbitrary offsets if it no longer works) |
I am also encountering this issue using rigidbodies to update the navigation mesh. sometimes the boxes just happen to pile up or land in such a way that preventing edges from being too close is just impossible without snapping the landing location of the rigidbody to a grid, which sort of ruins the physics. it would be really nice if there was some kind of internal fallback like slumberface mentioned for when these sync errors occur. |
I've drafted a fix for this issue, but I'd like to test with any of the demos mentioned in this issue. Unfortunately none of those works in Godot 4.3. @tcoxon @slumberface or @InfernalWAVE could any of you upload an updated version of the demo project that reproduces the issue? |
Btw. This issue was discussed in the past: #56786 |
Just in case someone pops into this issue again. If you're certain that:
then change |
I'm getting a similar error for a mesh baked from code. I dumped my mesh data to test into a minimal project, and I get the same error both from code and from manual setup (only the first time though, whichever is opened first?), and for some reason only the editor one shows preview polygons. |
Godot version
4.1.3.stable.official
System information
Godot v4.1.3.stable - Arch Linux #1 SMP PREEMPT_DYNAMIC Tue, 10 Oct 2023 21:10:21 +0000 - X11 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 970 (nvidia; 535.113.01) - AMD Ryzen 5 2600 Six-Core Processor (12 Threads)
Issue description
For context, I'm working on navmesh support for the Terrain3D plugin. To support navmeshes, the plugin generates 'source geometry data' for navigable portions of the terrain, and uses that as input to the engine's
bake_from_source_geometry_data
function.I very frequently run into this error:
It's strange because I have verified that:
cell_size
andcell_height
on the navmesh match the navigation map values.I've created a minimal reproducer that reproduces this error. The reproducer creates a parabolic U-shaped mesh and bakes a navmesh from it:
I suspect that the issue is all these long-thin polygons from the edge of the mesh to the middle:
However, if I turn on wireframe, you can see that those long-thin polygons are not part of the source mesh, which is very regular:
Since these long polygons originate in the engine (or the recast library?) I think that this is a bug. If these long/dense edges are an error, then the engine shouldn't be creating them.
Steps to reproduce
nav_bake_issue.tscn
scene. A tool script will run on _ready to generate the mesh and bake it.Minimal reproduction project
nav_bake_issue.zip
The text was updated successfully, but these errors were encountered: