From 180a5cded1d01e8c8965f009624652ee6ef1807c Mon Sep 17 00:00:00 2001
From: smix8 <52464204+smix8@users.noreply.github.com>
Date: Tue, 13 Jun 2023 13:36:05 +0200
Subject: [PATCH] Fix `cell_height` for navigation meshes
Fixes `cell_height` for navigation meshes.
---
doc/classes/NavigationMesh.xml | 4 ++--
doc/classes/NavigationServer2D.xml | 4 ++--
doc/classes/NavigationServer3D.xml | 19 +++++++++++++++++--
doc/classes/ProjectSettings.xml | 3 +++
.../navigation/godot_navigation_server.cpp | 14 ++++++++++++++
modules/navigation/godot_navigation_server.h | 3 +++
modules/navigation/nav_map.cpp | 14 +++++++++++---
modules/navigation/nav_map.h | 8 ++++++--
modules/navigation/nav_region.cpp | 4 ++++
scene/resources/navigation_mesh.h | 4 ++--
scene/resources/navigation_polygon.h | 2 +-
scene/resources/world_3d.cpp | 1 +
servers/navigation_server_3d.cpp | 3 +++
servers/navigation_server_3d.h | 3 +++
servers/navigation_server_3d_dummy.h | 2 ++
15 files changed, 74 insertions(+), 14 deletions(-)
diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml
index 5999dc62228..f481fd70990 100644
--- a/doc/classes/NavigationMesh.xml
+++ b/doc/classes/NavigationMesh.xml
@@ -91,10 +91,10 @@
[b]Note:[/b] While baking, this value will be rounded up to the nearest multiple of [member cell_size].
- The Y axis cell size to use for fields.
+ The cell height used to rasterize the navigation mesh vertices on the Y axis. Must match with the cell height on the navigation map.
- The XZ plane cell size to use for fields.
+ The cell size used to rasterize the navigation mesh vertices on the XZ plane. Must match with the cell size on the navigation map.
The sampling distance to use when generating the detail mesh, in cell unit.
diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml
index fb23d221274..f46f2912b33 100644
--- a/doc/classes/NavigationServer2D.xml
+++ b/doc/classes/NavigationServer2D.xml
@@ -339,7 +339,7 @@
- Returns the map cell size.
+ Returns the map cell size used to rasterize the navigation mesh vertices.
@@ -431,7 +431,7 @@
- Set the map cell size used to weld the navigation mesh polygons.
+ Sets the map cell size used to rasterize the navigation mesh vertices. Must match with the cell size of the used navigation meshes.
diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml
index 6f406aa629e..ac9646da4a7 100644
--- a/doc/classes/NavigationServer3D.xml
+++ b/doc/classes/NavigationServer3D.xml
@@ -367,11 +367,18 @@
Returns all navigation agents [RID]s that are currently assigned to the requested navigation [param map].
+
+
+
+
+ Returns the map cell height used to rasterize the navigation mesh vertices on the Y axis.
+
+
- Returns the map cell size.
+ Returns the map cell size used to rasterize the navigation mesh vertices on the XZ plane.
@@ -483,12 +490,20 @@
Sets the map active.
+
+
+
+
+
+ Sets the map cell height used to rasterize the navigation mesh vertices on the Y axis. Must match with the cell height of the used navigation meshes.
+
+
- Set the map cell size used to weld the navigation mesh polygons.
+ Sets the map cell size used to rasterize the navigation mesh vertices on the XZ plane. Must match with the cell size of the used navigation meshes.
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index ffb61ab20d3..9baa288acea 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -1952,6 +1952,9 @@
If enabled 2D navigation regions will use edge connections to connect with other navigation regions within proximity of the navigation map edge connection margin. This setting only affects World2D default navigation maps.
+
+ Default cell height for 3D navigation maps. See [method NavigationServer3D.map_set_cell_height].
+
Default cell size for 3D navigation maps. See [method NavigationServer3D.map_set_cell_size].
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index c72b61014b7..5baae478c28 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -166,6 +166,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_or_null(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.get_or_null(p_map);
+ ERR_FAIL_COND_V(map == nullptr, 0);
+
+ return map->get_cell_height();
+}
+
COMMAND_2(map_set_use_edge_connections, RID, p_map, bool, p_enabled) {
NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND(map == nullptr);
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 8c9b1eb1b19..1f2096b61a7 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -107,6 +107,9 @@ public:
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 override;
+ 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 override;
+
COMMAND_2(map_set_use_edge_connections, RID, p_map, bool, p_enabled);
virtual bool map_get_use_edge_connections(RID p_map) const override;
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 57c33a49b57..3f6465d94eb 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -69,6 +69,14 @@ void NavMap::set_cell_size(real_t p_cell_size) {
regenerate_polygons = true;
}
+void NavMap::set_cell_height(real_t p_cell_height) {
+ if (cell_height == p_cell_height) {
+ return;
+ }
+ cell_height = p_cell_height;
+ regenerate_polygons = true;
+}
+
void NavMap::set_use_edge_connections(bool p_enabled) {
if (use_edge_connections == p_enabled) {
return;
@@ -94,9 +102,9 @@ void NavMap::set_link_connection_radius(real_t p_link_connection_radius) {
}
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::floor(p_pos.x / cell_size));
+ const int y = static_cast(Math::floor(p_pos.y / cell_height));
+ const int z = static_cast(Math::floor(p_pos.z / cell_size));
gd::PointKey p;
p.key = 0;
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 2bd94596269..8d529f464e3 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -54,8 +54,9 @@ class NavMap : public NavRid {
Vector3 up = Vector3(0, 1, 0);
/// To find the polygons edges the vertices are displaced in a grid where
- /// each cell has the following cell_size.
- real_t cell_size = 0.25;
+ /// each cell has the following cell_size and cell_height.
+ real_t cell_size = 0.25; // Must match ProjectSettings default 3D cell_size and NavigationMesh cell_size.
+ real_t cell_height = 0.25; // Must match ProjectSettings default 3D cell_height and NavigationMesh cell_height.
bool use_edge_connections = true;
/// This value is used to detect the near edges to connect.
@@ -131,6 +132,9 @@ public:
return cell_size;
}
+ void set_cell_height(real_t p_cell_height);
+ real_t get_cell_height() const { return cell_height; }
+
void set_use_edge_connections(bool p_enabled);
bool get_use_edge_connections() const {
return use_edge_connections;
diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp
index 302b881eb52..bf4fec1ac8a 100644
--- a/modules/navigation/nav_region.cpp
+++ b/modules/navigation/nav_region.cpp
@@ -110,6 +110,10 @@ void NavRegion::update_polygons() {
ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a different `cell_size` than the `cell_size` set on the navigation map.");
}
+ if (!Math::is_equal_approx(double(map->get_cell_height()), double(mesh->get_cell_height()))) {
+ ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to update a navigation region with a navigation mesh that uses a different `cell_height` than the `cell_height` set on the navigation map.");
+ }
+
if (map && Math::rad_to_deg(map->get_up().angle_to(transform.basis.get_column(1))) >= 90.0f) {
ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to update a navigation region transform rotated 90 degrees or more away from the current navigation map UP orientation.");
}
diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h
index e6a432518ce..c3b8c13c053 100644
--- a/scene/resources/navigation_mesh.h
+++ b/scene/resources/navigation_mesh.h
@@ -91,8 +91,8 @@ public:
};
protected:
- float cell_size = 0.25f;
- float cell_height = 0.25f;
+ float cell_size = 0.25f; // Must match ProjectSettings default 3D cell_size and NavigationServer NavMap cell_size.
+ float cell_height = 0.25f; // Must match ProjectSettings default 3D cell_height and NavigationServer NavMap cell_height.
float agent_height = 1.5f;
float agent_radius = 0.5f;
float agent_max_climb = 0.25f;
diff --git a/scene/resources/navigation_polygon.h b/scene/resources/navigation_polygon.h
index 01780c187c8..3ab666eb166 100644
--- a/scene/resources/navigation_polygon.h
+++ b/scene/resources/navigation_polygon.h
@@ -51,7 +51,7 @@ class NavigationPolygon : public Resource {
// Navigation mesh
Ref navigation_mesh;
- real_t cell_size = 1.0f;
+ real_t cell_size = 1.0f; // Must match ProjectSettings default 2D cell_size.
protected:
static void _bind_methods();
diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp
index cc961941cf5..297d219caf3 100644
--- a/scene/resources/world_3d.cpp
+++ b/scene/resources/world_3d.cpp
@@ -67,6 +67,7 @@ RID World3D::get_navigation_map() const {
navigation_map = NavigationServer3D::get_singleton()->map_create();
NavigationServer3D::get_singleton()->map_set_active(navigation_map, true);
NavigationServer3D::get_singleton()->map_set_cell_size(navigation_map, GLOBAL_GET("navigation/3d/default_cell_size"));
+ NavigationServer3D::get_singleton()->map_set_cell_height(navigation_map, GLOBAL_GET("navigation/3d/default_cell_height"));
NavigationServer3D::get_singleton()->map_set_use_edge_connections(navigation_map, GLOBAL_GET("navigation/3d/use_edge_connections"));
NavigationServer3D::get_singleton()->map_set_edge_connection_margin(navigation_map, GLOBAL_GET("navigation/3d/default_edge_connection_margin"));
NavigationServer3D::get_singleton()->map_set_link_connection_radius(navigation_map, GLOBAL_GET("navigation/3d/default_link_connection_radius"));
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index f9f8797b76f..45b85a616ee 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -43,6 +43,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up);
ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size);
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size);
+ ClassDB::bind_method(D_METHOD("map_set_cell_height", "map", "cell_height"), &NavigationServer3D::map_set_cell_height);
+ ClassDB::bind_method(D_METHOD("map_get_cell_height", "map"), &NavigationServer3D::map_get_cell_height);
ClassDB::bind_method(D_METHOD("map_set_use_edge_connections", "map", "enabled"), &NavigationServer3D::map_set_use_edge_connections);
ClassDB::bind_method(D_METHOD("map_get_use_edge_connections", "map"), &NavigationServer3D::map_get_use_edge_connections);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin);
@@ -180,6 +182,7 @@ NavigationServer3D::NavigationServer3D() {
GLOBAL_DEF_BASIC("navigation/2d/default_link_connection_radius", 4);
GLOBAL_DEF_BASIC("navigation/3d/default_cell_size", 0.25);
+ GLOBAL_DEF_BASIC("navigation/3d/default_cell_height", 0.25);
GLOBAL_DEF("navigation/3d/use_edge_connections", true);
GLOBAL_DEF_BASIC("navigation/3d/default_edge_connection_margin", 0.25);
GLOBAL_DEF_BASIC("navigation/3d/default_link_connection_radius", 1.0);
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 23c38532e8c..da3741ed8bd 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -80,6 +80,9 @@ public:
/// Returns the map cell size.
virtual real_t map_get_cell_size(RID p_map) const = 0;
+ virtual void map_set_cell_height(RID p_map, real_t p_height) = 0;
+ virtual real_t map_get_cell_height(RID p_map) const = 0;
+
virtual void map_set_use_edge_connections(RID p_map, bool p_enabled) = 0;
virtual bool map_get_use_edge_connections(RID p_map) const = 0;
diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h
index 23fd8291db4..d2f11ccfa07 100644
--- a/servers/navigation_server_3d_dummy.h
+++ b/servers/navigation_server_3d_dummy.h
@@ -45,6 +45,8 @@ public:
Vector3 map_get_up(RID p_map) const override { return Vector3(); }
void map_set_cell_size(RID p_map, real_t p_cell_size) override {}
real_t map_get_cell_size(RID p_map) const override { return 0; }
+ void map_set_cell_height(RID p_map, real_t p_cell_height) override {}
+ real_t map_get_cell_height(RID p_map) const override { return 0; }
void map_set_use_edge_connections(RID p_map, bool p_enabled) override {}
bool map_get_use_edge_connections(RID p_map) const override { return false; }
void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) override {}