godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.99k stars 21.16k forks source link

Errors when using NavigationMesh.create_from_mesh() #78245

Closed eldidou closed 1 year ago

eldidou commented 1 year ago

Godot version

4.0.2.stable

System information

Linux Godot_v4.0.2-stable_linux.x86_64 Vulkan (forward+)

Issue description

When using a custom mesh with create_from_mesh in some cases the following error is reported:

E 0:00:00:0287   sync: Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the current `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problems.
  <C++ Source>   modules/navigation/nav_map.cpp:692 @ sync()

This happen even for some simple meshes, like two touching, but not overlapping, triangles on the same plane.

Reading nav_map.cpp, it seems that it could be due to the _cellsize attribute of the NavigationMesh, but changing its value doesn't help.

Steps to reproduce

    var vertices = PackedVector3Array([Vector3(0.7, 0, 0.7),
                                       Vector3(0.7, 0, 1.0),
                                       Vector3(0.5, 0, 0.5),
                                       Vector3(0.7, 0, 1.0),
                                       Vector3(0.0, 0, 1.0),
                                       Vector3(0.5, 0, 0.5)]) 
    var indices = PackedInt32Array([0, 1, 2, 3, 4, 5])
    var arrays = []
    arrays.resize(Mesh.ARRAY_MAX)
    arrays[Mesh.ARRAY_VERTEX] = vertices
    arrays[Mesh.ARRAY_INDEX] = indices

    var arr_mesh = ArrayMesh.new()
    arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)

    var nav_mesh = NavigationMesh.new()
    # nav_mesh.cell_size = 0.1 # doesn't help
    nav_mesh.create_from_mesh(arr_mesh)

    var nav_region := NavigationRegion3D.new()
    nav_region.navigation_mesh = nav_mesh
    add_child(nav_region)

Minimal reproduction project

custom_mesh.zip

smix8 commented 1 year ago

NavigationMesh cell_size and cell_height must match with the NavigationServer navigation map cell_size to not fail the rasterization of the navigation mesh vertices on the navigation map.

You can change the cell size either in the ProjectSettings for the default navigation map or by using the NavigationServer.map_set_cell_size() function at runtime.

Sure also the data inside the NavigationMesh must also match the cell_size, does not help to only change the labeling when the content is a navigation mesh made for a completely wrong cell size, or made for a visual mesh but does not work for a navigation mesh.

Instead of creating a throw-away visual mesh you could directly create the navigation mesh vertices and polygon indices arrays and set them on the NavigationMesh as all the create_from_mesh() function does is copy the vertices and indices over.

The create_from_mesh() function has zero validation if the data makes any sense for a navigation mesh. See https://github.com/godotengine/godot/pull/77702 why it should not be used. If you are sure that your mesh data is good for a navigation mesh you can still copy your vertices and indices over with the available NavigationMesh function but for the majority of users a visual mesh copy to navigation mesh is just a source of errors.

eldidou commented 1 year ago

I was not aware of the cell_size parameter of the NavigationServer, and indeed changing it solves the issue. (I've also replaced the call to create_from_mesh() to calls to set_vertices() and add_polygon())

Should I close the issue?

Many thanks!

eldidou commented 1 year ago

Small note, for godot 4.1 (beta2), the error can appear if the nav mesh cell_size doesn't match exactly the project setting navigation/3d/default_cell_size. Changing nav mesh cell_size is not required in 4.0.

Here is the updated version that works in 4.1, with the calls to set_vertices() and add_polygon()) instead of create_from_mesh()

    var vertices = PackedVector3Array([Vector3(0.7, 0, 0.7),
                                       Vector3(0.7, 0, 1.0),
                                       Vector3(0.5, 0, 0.5),
                                       Vector3(0.7, 0, 1.0),
                                       Vector3(0.0, 0, 1.0),
                                       Vector3(0.5, 0, 0.5)])
    var indices = [PackedInt32Array([0, 1, 2]), PackedInt32Array([3, 4, 5])]

    var nav_mesh = NavigationMesh.new()
    nav_mesh.cell_size = 0.1 # needs to match exactly the project setting navigation/3d/default_cell_size, starting for godot 4.1
    nav_mesh.vertices = vertices
    for polygon in indices:
        nav_mesh.add_polygon(polygon)

    var nav_region := NavigationRegion3D.new()
    nav_region.navigation_mesh = nav_mesh
    add_child(nav_region)
smix8 commented 1 year ago

Should I close the issue?

If you don't have further questions, sure you can close it yourself.