Add means for fixing navmap synchronization errors

This commit is contained in:
Pawel Lampe 2024-02-04 21:31:07 +01:00
parent 4e990cd7e5
commit 9ea8d4fa38
10 changed files with 77 additions and 4 deletions

View file

@ -582,6 +582,13 @@
Returns all navigation link [RID]s that are currently assigned to the requested navigation [param map].
</description>
</method>
<method name="map_get_merge_rasterizer_cell_scale" qualifiers="const">
<return type="float" />
<param index="0" name="map" type="RID" />
<description>
Returns map's internal merge rasterizer cell scale.
</description>
</method>
<method name="map_get_obstacles" qualifiers="const">
<return type="RID[]" />
<param index="0" name="map" type="RID" />
@ -679,6 +686,14 @@
Set the map's link connection radius used to connect links to navigation polygons.
</description>
</method>
<method name="map_set_merge_rasterizer_cell_scale">
<return type="void" />
<param index="0" name="map" type="RID" />
<param index="1" name="scale" type="float" />
<description>
Set the map's internal merge rasterizer cell scale used to control merging sensitivity.
</description>
</method>
<method name="map_set_up">
<return type="void" />
<param index="0" name="map" type="RID" />

View file

@ -2045,6 +2045,9 @@
<member name="navigation/3d/default_up" type="Vector3" setter="" getter="" default="Vector3(0, 1, 0)">
Default up orientation for 3D navigation maps. See [method NavigationServer3D.map_set_up].
</member>
<member name="navigation/3d/merge_rasterizer_cell_scale" type="float" setter="" getter="" default="1.0">
Default merge rasterizer cell scale for 3D navigation maps. See [method NavigationServer3D.map_set_merge_rasterizer_cell_scale].
</member>
<member name="navigation/3d/use_edge_connections" type="bool" setter="" getter="" default="true">
If enabled 3D 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 World3D default navigation maps.
</member>

View file

@ -180,6 +180,20 @@ real_t GodotNavigationServer::map_get_cell_height(RID p_map) const {
return map->get_cell_height();
}
COMMAND_2(map_set_merge_rasterizer_cell_scale, RID, p_map, float, p_value) {
NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_NULL(map);
map->set_merge_rasterizer_cell_scale(p_value);
}
float GodotNavigationServer::map_get_merge_rasterizer_cell_scale(RID p_map) const {
NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_NULL_V(map, false);
return map->get_merge_rasterizer_cell_scale();
}
COMMAND_2(map_set_use_edge_connections, RID, p_map, bool, p_enabled) {
NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_NULL(map);

View file

@ -117,6 +117,9 @@ public:
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_merge_rasterizer_cell_scale, RID, p_map, float, p_value);
virtual float map_get_merge_rasterizer_cell_scale(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;

View file

@ -67,6 +67,7 @@ void NavMap::set_cell_size(real_t p_cell_size) {
return;
}
cell_size = p_cell_size;
_update_merge_rasterizer_cell_dimensions();
regenerate_polygons = true;
}
@ -75,6 +76,16 @@ void NavMap::set_cell_height(real_t p_cell_height) {
return;
}
cell_height = p_cell_height;
_update_merge_rasterizer_cell_dimensions();
regenerate_polygons = true;
}
void NavMap::set_merge_rasterizer_cell_scale(float p_value) {
if (merge_rasterizer_cell_scale == p_value) {
return;
}
merge_rasterizer_cell_scale = p_value;
_update_merge_rasterizer_cell_dimensions();
regenerate_polygons = true;
}
@ -103,9 +114,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 = static_cast<int>(Math::floor(p_pos.x / cell_size));
const int y = static_cast<int>(Math::floor(p_pos.y / cell_height));
const int z = static_cast<int>(Math::floor(p_pos.z / cell_size));
const int x = static_cast<int>(Math::floor(p_pos.x / merge_rasterizer_cell_size));
const int y = static_cast<int>(Math::floor(p_pos.y / merge_rasterizer_cell_height));
const int z = static_cast<int>(Math::floor(p_pos.z / merge_rasterizer_cell_size));
gd::PointKey p;
p.key = 0;
@ -923,7 +934,7 @@ void NavMap::sync() {
connections[ek].push_back(new_connection);
} else {
// The edge is already connected with another edge, skip.
ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to merge a navigation mesh polygon edge with another already-merged edge. This is usually caused by crossing edges, overlapping polygons, or a mismatch of the NavigationMesh / NavigationPolygon baked 'cell_size' and navigation map 'cell_size'.");
ERR_PRINT_ONCE("Navigation map synchronization error. Attempted to merge a navigation mesh polygon edge with another already-merged edge. This is usually caused by crossing edges, overlapping polygons, or a mismatch of the NavigationMesh / NavigationPolygon baked 'cell_size' and navigation map 'cell_size'. If you're certain none of above is the case, change 'navigation/3d/merge_rasterizer_cell_scale' to 0.001.");
}
}
}
@ -1365,6 +1376,11 @@ void NavMap::clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys
}
}
void NavMap::_update_merge_rasterizer_cell_dimensions() {
merge_rasterizer_cell_size = cell_size * merge_rasterizer_cell_scale;
merge_rasterizer_cell_height = cell_height * merge_rasterizer_cell_scale;
}
NavMap::NavMap() {
avoidance_use_multiple_threads = GLOBAL_GET("navigation/avoidance/thread_model/avoidance_use_multiple_threads");
avoidance_use_high_priority_threads = GLOBAL_GET("navigation/avoidance/thread_model/avoidance_use_high_priority_threads");

View file

@ -56,6 +56,12 @@ class NavMap : public NavRid {
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.
// For the inter-region merging to work, internal rasterization is performed.
float merge_rasterizer_cell_size = 0.25;
float merge_rasterizer_cell_height = 0.25;
// This value is used to control sensitivity of internal rasterizer.
float merge_rasterizer_cell_scale = 1.0;
bool use_edge_connections = true;
/// This value is used to detect the near edges to connect.
real_t edge_connection_margin = 0.25;
@ -133,6 +139,11 @@ public:
void set_cell_height(real_t p_cell_height);
real_t get_cell_height() const { return cell_height; }
void set_merge_rasterizer_cell_scale(float p_value);
float get_merge_rasterizer_cell_scale() const {
return merge_rasterizer_cell_scale;
}
void set_use_edge_connections(bool p_enabled);
bool get_use_edge_connections() const {
return use_edge_connections;
@ -217,6 +228,8 @@ private:
void _update_rvo_obstacles_tree_2d();
void _update_rvo_agents_tree_2d();
void _update_rvo_agents_tree_3d();
void _update_merge_rasterizer_cell_dimensions();
};
#endif // NAV_MAP_H

View file

@ -69,6 +69,7 @@ RID World3D::get_navigation_map() const {
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_up(navigation_map, GLOBAL_GET("navigation/3d/default_up"));
NavigationServer3D::get_singleton()->map_set_merge_rasterizer_cell_scale(navigation_map, GLOBAL_GET("navigation/3d/merge_rasterizer_cell_scale"));
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"));

View file

@ -45,6 +45,8 @@ void NavigationServer3D::_bind_methods() {
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_merge_rasterizer_cell_scale", "map", "scale"), &NavigationServer3D::map_set_merge_rasterizer_cell_scale);
ClassDB::bind_method(D_METHOD("map_get_merge_rasterizer_cell_scale", "map"), &NavigationServer3D::map_get_merge_rasterizer_cell_scale);
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);
@ -222,6 +224,7 @@ NavigationServer3D::NavigationServer3D() {
GLOBAL_DEF_BASIC(PropertyInfo(Variant::FLOAT, "navigation/3d/default_cell_size", PROPERTY_HINT_RANGE, "0.001,100,0.001,or_greater"), 0.25);
GLOBAL_DEF_BASIC("navigation/3d/default_cell_height", 0.25);
GLOBAL_DEF("navigation/3d/default_up", Vector3(0, 1, 0));
GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "navigation/3d/merge_rasterizer_cell_scale", PROPERTY_HINT_RANGE, "0.001,1,0.001,or_greater"), 1.0);
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);

View file

@ -84,6 +84,9 @@ public:
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_merge_rasterizer_cell_scale(RID p_map, float p_value) = 0;
virtual float map_get_merge_rasterizer_cell_scale(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;

View file

@ -47,6 +47,8 @@ public:
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_merge_rasterizer_cell_scale(RID p_map, float p_value) override {}
float map_get_merge_rasterizer_cell_scale(RID p_map) const override { return 1.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 {}