diff --git a/doc/classes/Navigation.xml b/doc/classes/Navigation.xml index b92e9a4d6976..2fc3d3fd5251 100644 --- a/doc/classes/Navigation.xml +++ b/doc/classes/Navigation.xml @@ -57,6 +57,9 @@ + + The cell height to use for fields. + The XZ plane cell size to use for fields. diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml index 86f9c5280d50..66485d9f527c 100644 --- a/doc/classes/NavigationMesh.xml +++ b/doc/classes/NavigationMesh.xml @@ -98,7 +98,7 @@ The sampling distance to use when generating the detail mesh, in cell unit. - + The maximum distance the detail mesh surface should deviate from heightfield, in cell unit. diff --git a/doc/classes/NavigationServer.xml b/doc/classes/NavigationServer.xml index e90491d634a6..89e806869b8f 100644 --- a/doc/classes/NavigationServer.xml +++ b/doc/classes/NavigationServer.xml @@ -122,6 +122,13 @@ Create a new map. + + + + + Returns the map cell height. + + @@ -202,6 +209,14 @@ Sets the map active. + + + + + + Set the map cell height used to weld the navigation mesh polygons. + + diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 49013255a5e8..38ed94c60294 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -187,6 +187,20 @@ real_t GodotNavigationServer::map_get_cell_size(RID p_map) const { return map->get_cell_size(); } +COMMAND_2(map_set_cell_height, RID, p_map, real_t, p_cell_height) { + NavMap *map = map_owner.get(p_map); + ERR_FAIL_COND(map == nullptr); + + map->set_cell_height(p_cell_height); +} + +real_t GodotNavigationServer::map_get_cell_height(RID p_map) const { + const NavMap *map = map_owner.getornull(p_map); + ERR_FAIL_COND_V(map == nullptr, 0); + + return map->get_cell_height(); +} + COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin) { NavMap *map = map_owner.get(p_map); ERR_FAIL_COND(map == nullptr); diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index 66cc50239116..115676afdd5f 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -95,6 +95,9 @@ class GodotNavigationServer : public NavigationServer { COMMAND_2(map_set_cell_size, RID, p_map, real_t, p_cell_size); virtual real_t map_get_cell_size(RID p_map) const; + COMMAND_2(map_set_cell_height, RID, p_map, real_t, p_cell_height); + virtual real_t map_get_cell_height(RID p_map) const; + COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin); virtual real_t map_get_edge_connection_margin(RID p_map) const; diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 59bf1a74a45d..4b51db91bdea 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -44,6 +44,7 @@ NavMap::NavMap() : up(0, 1, 0), cell_size(0.3), + cell_height(0.2), edge_connection_margin(5.0), regenerate_polygons(true), regenerate_links(true), @@ -61,15 +62,20 @@ void NavMap::set_cell_size(float p_cell_size) { regenerate_polygons = true; } +void NavMap::set_cell_height(float p_cell_height) { + cell_height = p_cell_height; + regenerate_polygons = true; +} + void NavMap::set_edge_connection_margin(float p_edge_connection_margin) { edge_connection_margin = p_edge_connection_margin; regenerate_links = true; } gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const { - const int x = int(Math::floor(p_pos.x / cell_size)); - const int y = int(Math::floor(p_pos.y / cell_size)); - const int z = int(Math::floor(p_pos.z / cell_size)); + const int x = static_cast(Math::round(p_pos.x / cell_size)); + const int y = static_cast(Math::round(p_pos.y / cell_height)); + const int z = static_cast(Math::round(p_pos.z / cell_size)); gd::PointKey p; p.key = 0; @@ -640,7 +646,7 @@ void NavMap::sync() { connection->get().B->edges[connection->get().B_edge].other_edge = connection->get().A_edge; } else { // The edge is already connected with another edge, skip. - ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. This happens when the Navigation's `cell_size` is different from the one used to generate the navigation mesh. This will cause navigation problem."); + ERR_PRINT("Attempted to merge a navigation mesh triangle edge with another already-merged edge. Either the Navigation's `cell_size` is different from the one used to generate the navigation mesh or `detail/sample_max_error` is too small. This will cause navigation problem."); } } } diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index 6712bd4041c8..d8eb794dc88e 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -50,8 +50,9 @@ class NavMap : public NavRid { Vector3 up; /// To find the polygons edges the vertices are displaced in a grid where - /// each cell has the following cell_size. + /// each cell has the following cell_size and cell_height. real_t cell_size; + real_t cell_height; /// This value is used to detect the near edges to connect. real_t edge_connection_margin; @@ -95,6 +96,11 @@ class NavMap : public NavRid { return cell_size; } + void set_cell_height(float p_cell_height); + float get_cell_height() const { + return cell_height; + } + void set_edge_connection_margin(float p_edge_connection_margin); float get_edge_connection_margin() const { return edge_connection_margin; diff --git a/scene/3d/navigation.cpp b/scene/3d/navigation.cpp index 919c95e54e17..b7fcc369b004 100644 --- a/scene/3d/navigation.cpp +++ b/scene/3d/navigation.cpp @@ -66,6 +66,11 @@ void Navigation::set_cell_size(float p_cell_size) { NavigationServer::get_singleton()->map_set_cell_size(map, cell_size); } +void Navigation::set_cell_height(float p_cell_height) { + cell_height = p_cell_height; + NavigationServer::get_singleton()->map_set_cell_height(map, cell_height); +} + void Navigation::set_edge_connection_margin(float p_edge_connection_margin) { edge_connection_margin = p_edge_connection_margin; NavigationServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); @@ -86,11 +91,15 @@ void Navigation::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &Navigation::set_cell_size); ClassDB::bind_method(D_METHOD("get_cell_size"), &Navigation::get_cell_size); + ClassDB::bind_method(D_METHOD("set_cell_height", "cell_height"), &Navigation::set_cell_height); + ClassDB::bind_method(D_METHOD("get_cell_height"), &Navigation::get_cell_height); + ClassDB::bind_method(D_METHOD("set_edge_connection_margin", "margin"), &Navigation::set_edge_connection_margin); ClassDB::bind_method(D_METHOD("get_edge_connection_margin"), &Navigation::get_edge_connection_margin); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "up_vector"), "set_up_vector", "get_up_vector"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_size"), "set_cell_size", "get_cell_size"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "cell_height"), "set_cell_height", "get_cell_height"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "edge_connection_margin"), "set_edge_connection_margin", "get_edge_connection_margin"); } @@ -109,6 +118,7 @@ Navigation::Navigation() { map = NavigationServer::get_singleton()->map_create(); set_cell_size(0.3); + set_cell_height(0.2); set_edge_connection_margin(5.0); // Five meters, depends alot on the agents radius up = Vector3(0, 1, 0); diff --git a/scene/3d/navigation.h b/scene/3d/navigation.h index 65ac2f3a4a83..9779bd05b623 100644 --- a/scene/3d/navigation.h +++ b/scene/3d/navigation.h @@ -41,6 +41,7 @@ class Navigation : public Spatial { Vector3 up; real_t cell_size; + real_t cell_height; real_t edge_connection_margin; protected: @@ -60,6 +61,11 @@ class Navigation : public Spatial { return cell_size; } + void set_cell_height(float p_cell_height); + float get_cell_height() const { + return cell_height; + } + void set_edge_connection_margin(float p_edge_connection_margin); float get_edge_connection_margin() const { return edge_connection_margin; diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index 0624ce294fc7..eea4227d55fe 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -542,7 +542,7 @@ NavigationMesh::NavigationMesh() { edge_max_error = 1.3f; verts_per_poly = 6.0f; detail_sample_distance = 6.0f; - detail_sample_max_error = 1.0f; + detail_sample_max_error = 5.0f; partition_type = SAMPLE_PARTITION_WATERSHED; parsed_geometry_type = PARSED_GEOMETRY_MESH_INSTANCES; diff --git a/servers/navigation_server.cpp b/servers/navigation_server.cpp index 97976b2ad3b2..e30fedc81f5f 100644 --- a/servers/navigation_server.cpp +++ b/servers/navigation_server.cpp @@ -44,6 +44,8 @@ void NavigationServer::_bind_methods() { ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer::map_get_up); ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer::map_set_cell_size); ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer::map_get_cell_size); + ClassDB::bind_method(D_METHOD("map_set_cell_height", "map", "cell_height"), &NavigationServer::map_set_cell_height); + ClassDB::bind_method(D_METHOD("map_get_cell_height", "map"), &NavigationServer::map_get_cell_height); ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer::map_set_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer::map_get_edge_connection_margin); ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer::map_get_path); diff --git a/servers/navigation_server.h b/servers/navigation_server.h index deebd32f1c53..78de6c4a8da2 100644 --- a/servers/navigation_server.h +++ b/servers/navigation_server.h @@ -81,6 +81,12 @@ class NavigationServer : public Object { /// Returns the map cell size. virtual real_t map_get_cell_size(RID p_map) const = 0; + /// Set the map cell height used to weld the navigation mesh polygons. + virtual void map_set_cell_height(RID p_map, real_t p_cell_height) const = 0; + + /// Returns the map cell height. + virtual real_t map_get_cell_height(RID p_map) const = 0; + /// Set the map edge connection margin used to weld the compatible region edges. virtual void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) const = 0;