Skip to content

Commit

Permalink
Add means for fixing navmap synchronization errors
Browse files Browse the repository at this point in the history
  • Loading branch information
Scony committed Feb 11, 2024
1 parent 4e990cd commit 9ea8d4f
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 4 deletions.
15 changes: 15 additions & 0 deletions doc/classes/NavigationServer3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down Expand Up @@ -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" />
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
14 changes: 14 additions & 0 deletions modules/navigation/godot_navigation_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions modules/navigation/godot_navigation_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ class GodotNavigationServer : public NavigationServer3D {
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;

Expand Down
24 changes: 20 additions & 4 deletions modules/navigation/nav_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.");
}
}
}
Expand Down Expand Up @@ -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");
Expand Down
13 changes: 13 additions & 0 deletions modules/navigation/nav_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -133,6 +139,11 @@ class NavMap : public NavRid {
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;
Expand Down Expand Up @@ -217,6 +228,8 @@ class NavMap : public NavRid {
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
1 change: 1 addition & 0 deletions scene/resources/world_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand Down
3 changes: 3 additions & 0 deletions servers/navigation_server_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions servers/navigation_server_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ class NavigationServer3D : public Object {
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;

Expand Down
2 changes: 2 additions & 0 deletions servers/navigation_server_3d_dummy.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class NavigationServer3DDummy : public NavigationServer3D {
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 {}
Expand Down

0 comments on commit 9ea8d4f

Please sign in to comment.