From 64a56245d8dfca272f6f60a6ef24b8bd08c29c83 Mon Sep 17 00:00:00 2001 From: smix8 <52464204+smix8@users.noreply.github.com> Date: Mon, 23 Oct 2023 18:16:05 +0200 Subject: [PATCH] Add NavigationServer random point queries Adds query functions to get random points on navigation mesh to the NavigationServer. --- doc/classes/NavigationServer2D.xml | 22 +++ doc/classes/NavigationServer3D.xml | 22 +++ .../navigation/godot_navigation_server.cpp | 14 ++ modules/navigation/godot_navigation_server.h | 3 + .../navigation/godot_navigation_server_2d.cpp | 11 +- .../navigation/godot_navigation_server_2d.h | 2 + modules/navigation/nav_map.cpp | 64 ++++++++ modules/navigation/nav_map.h | 2 + modules/navigation/nav_region.cpp | 140 ++++++++++++++++-- modules/navigation/nav_region.h | 6 + modules/navigation/nav_utils.h | 2 + servers/navigation_server_2d.cpp | 3 + servers/navigation_server_2d.h | 4 + servers/navigation_server_2d_dummy.h | 2 + servers/navigation_server_3d.cpp | 3 + servers/navigation_server_3d.h | 4 + servers/navigation_server_3d_dummy.h | 2 + 17 files changed, 290 insertions(+), 16 deletions(-) diff --git a/doc/classes/NavigationServer2D.xml b/doc/classes/NavigationServer2D.xml index a25f048df3f2..e1c79ad8a882 100644 --- a/doc/classes/NavigationServer2D.xml +++ b/doc/classes/NavigationServer2D.xml @@ -445,6 +445,17 @@ Returns the navigation path to reach the destination from the origin. [param navigation_layers] is a bitmask of all region navigation layers that are allowed to be in the path. + + + + + + + Returns a random position picked from all map region polygons with matching [param navigation_layers]. + If [param uniformly] is [code]true[/code], all map regions, polygons, and faces are weighted by their surface area (slower). + If [param uniformly] is [code]false[/code], just a random region and a random polygon are picked (faster). + + @@ -681,6 +692,17 @@ Returns the [code]ObjectID[/code] of the object which manages this region. + + + + + + + Returns a random position picked from all region polygons with matching [param navigation_layers]. + If [param uniformly] is [code]true[/code], all region polygons and faces are weighted by their surface area (slower). + If [param uniformly] is [code]false[/code], just a random polygon and face is picked (faster). + + diff --git a/doc/classes/NavigationServer3D.xml b/doc/classes/NavigationServer3D.xml index b56b86f435db..46b669794736 100644 --- a/doc/classes/NavigationServer3D.xml +++ b/doc/classes/NavigationServer3D.xml @@ -502,6 +502,17 @@ Returns the navigation path to reach the destination from the origin. [param navigation_layers] is a bitmask of all region navigation layers that are allowed to be in the path. + + + + + + + Returns a random position picked from all map region polygons with matching [param navigation_layers]. + If [param uniformly] is [code]true[/code], all map regions, polygons, and faces are weighted by their surface area (slower). + If [param uniformly] is [code]false[/code], just a random region and a random polygon are picked (faster). + + @@ -793,6 +804,17 @@ Returns the [code]ObjectID[/code] of the object which manages this region. + + + + + + + Returns a random position picked from all region polygons with matching [param navigation_layers]. + If [param uniformly] is [code]true[/code], all region polygons and faces are weighted by their surface area (slower). + If [param uniformly] is [code]false[/code], just a random polygon and face is picked (faster). + + diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp index 6a3bf6793e47..5a28f8b8efcf 100644 --- a/modules/navigation/godot_navigation_server.cpp +++ b/modules/navigation/godot_navigation_server.cpp @@ -331,6 +331,13 @@ RID GodotNavigationServer::agent_get_map(RID p_agent) const { return RID(); } +Vector3 GodotNavigationServer::map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const { + const NavMap *map = map_owner.get_or_null(p_map); + ERR_FAIL_NULL_V(map, Vector3()); + + return map->get_random_point(p_navigation_layers, p_uniformly); +} + RID GodotNavigationServer::region_create() { MutexLock lock(operations_mutex); @@ -498,6 +505,13 @@ Vector3 GodotNavigationServer::region_get_connection_pathway_end(RID p_region, i return region->get_connection_pathway_end(p_connection_id); } +Vector3 GodotNavigationServer::region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const { + const NavRegion *region = region_owner.get_or_null(p_region); + ERR_FAIL_NULL_V(region, Vector3()); + + return region->get_random_point(p_navigation_layers, p_uniformly); +} + RID GodotNavigationServer::link_create() { MutexLock lock(operations_mutex); diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h index 4ead4fc398b7..3a76f83b0919 100644 --- a/modules/navigation/godot_navigation_server.h +++ b/modules/navigation/godot_navigation_server.h @@ -140,6 +140,8 @@ class GodotNavigationServer : public NavigationServer3D { virtual void map_force_update(RID p_map) override; + virtual Vector3 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const override; + virtual RID region_create() override; COMMAND_2(region_set_enabled, RID, p_region, bool, p_enabled); @@ -170,6 +172,7 @@ class GodotNavigationServer : public NavigationServer3D { virtual int region_get_connections_count(RID p_region) const override; virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override; virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override; + virtual Vector3 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override; virtual RID link_create() override; COMMAND_2(link_set_map, RID, p_link, RID, p_map); diff --git a/modules/navigation/godot_navigation_server_2d.cpp b/modules/navigation/godot_navigation_server_2d.cpp index b54729e06fc3..142d6181a11a 100644 --- a/modules/navigation/godot_navigation_server_2d.cpp +++ b/modules/navigation/godot_navigation_server_2d.cpp @@ -259,8 +259,12 @@ Vector FORWARD_5_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2 Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); -RID FORWARD_0(region_create); +Vector2 GodotNavigationServer2D::map_get_random_point(RID p_map, uint32_t p_naviation_layers, bool p_uniformly) const { + Vector3 result = NavigationServer3D::get_singleton()->map_get_random_point(p_map, p_naviation_layers, p_uniformly); + return v3_to_v2(result); +} +RID FORWARD_0(region_create); void FORWARD_2(region_set_enabled, RID, p_region, bool, p_enabled, rid_to_rid, bool_to_bool); bool FORWARD_1_C(region_get_enabled, RID, p_region, rid_to_rid); void FORWARD_2(region_set_use_edge_connections, RID, p_region, bool, p_enabled, rid_to_rid, bool_to_bool); @@ -287,6 +291,11 @@ int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid); Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int); Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int); +Vector2 GodotNavigationServer2D::region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const { + Vector3 result = NavigationServer3D::get_singleton()->region_get_random_point(p_region, p_navigation_layers, p_uniformly); + return v3_to_v2(result); +} + RID FORWARD_0(link_create); void FORWARD_2(link_set_map, RID, p_link, RID, p_map, rid_to_rid, rid_to_rid); diff --git a/modules/navigation/godot_navigation_server_2d.h b/modules/navigation/godot_navigation_server_2d.h index 337f5f40d8f5..88dee0ce697a 100644 --- a/modules/navigation/godot_navigation_server_2d.h +++ b/modules/navigation/godot_navigation_server_2d.h @@ -76,6 +76,7 @@ class GodotNavigationServer2D : public NavigationServer2D { virtual TypedArray map_get_agents(RID p_map) const override; virtual TypedArray map_get_obstacles(RID p_map) const override; virtual void map_force_update(RID p_map) override; + virtual Vector2 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const override; virtual RID region_create() override; virtual void region_set_enabled(RID p_region, bool p_enabled) override; @@ -98,6 +99,7 @@ class GodotNavigationServer2D : public NavigationServer2D { virtual int region_get_connections_count(RID p_region) const override; virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override; virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override; + virtual Vector2 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override; virtual RID link_create() override; diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 7a0799a735d5..2add9f5ef5fd 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -769,6 +769,70 @@ void NavMap::remove_agent_as_controlled(NavAgent *agent) { } } +Vector3 NavMap::get_random_point(uint32_t p_navigation_layers, bool p_uniformly) const { + const LocalVector map_regions = get_regions(); + + if (map_regions.is_empty()) { + return Vector3(); + } + + LocalVector accessible_regions; + + for (const NavRegion *region : map_regions) { + if (!region->get_enabled() || (p_navigation_layers & region->get_navigation_layers()) == 0) { + continue; + } + accessible_regions.push_back(region); + } + + if (accessible_regions.is_empty()) { + // All existing region polygons are disabled. + return Vector3(); + } + + if (p_uniformly) { + real_t accumulated_region_surface_area = 0; + RBMap accessible_regions_area_map; + + for (uint32_t accessible_region_index = 0; accessible_region_index < accessible_regions.size(); accessible_region_index++) { + const NavRegion *region = accessible_regions[accessible_region_index]; + + real_t region_surface_area = region->get_surface_area(); + + if (region_surface_area == 0.0f) { + continue; + } + + accessible_regions_area_map[accumulated_region_surface_area] = accessible_region_index; + accumulated_region_surface_area += region_surface_area; + } + if (accessible_regions_area_map.is_empty() || accumulated_region_surface_area == 0) { + // All faces have no real surface / no area. + return Vector3(); + } + + real_t random_accessible_regions_area_map = Math::random(real_t(0), accumulated_region_surface_area); + + RBMap::Iterator E = accessible_regions_area_map.find_closest(random_accessible_regions_area_map); + ERR_FAIL_COND_V(!E, Vector3()); + uint32_t random_region_index = E->value; + ERR_FAIL_INDEX_V(random_region_index, accessible_regions.size(), Vector3()); + + const NavRegion *random_region = accessible_regions[random_region_index]; + ERR_FAIL_NULL_V(random_region, Vector3()); + + return random_region->get_random_point(p_navigation_layers, p_uniformly); + + } else { + uint32_t random_region_index = Math::random(int(0), accessible_regions.size() - 1); + + const NavRegion *random_region = accessible_regions[random_region_index]; + ERR_FAIL_NULL_V(random_region, Vector3()); + + return random_region->get_random_point(p_navigation_layers, p_uniformly); + } +} + void NavMap::sync() { // Performance Monitor int _new_pm_region_count = regions.size(); diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index 5d78c14627c3..e8cbe7e2474e 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -190,6 +190,8 @@ class NavMap : public NavRid { return map_update_id; } + Vector3 get_random_point(uint32_t p_navigation_layers, bool p_uniformly) const; + void sync(); void step(real_t p_deltatime); void dispatch_callbacks(); diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp index 09697c7be0f8..11b775935800 100644 --- a/modules/navigation/nav_region.cpp +++ b/modules/navigation/nav_region.cpp @@ -100,6 +100,88 @@ Vector3 NavRegion::get_connection_pathway_end(int p_connection_id) const { return connections[p_connection_id].pathway_end; } +Vector3 NavRegion::get_random_point(uint32_t p_navigation_layers, bool p_uniformly) const { + if (!get_enabled()) { + return Vector3(); + } + + const LocalVector ®ion_polygons = get_polygons(); + + if (region_polygons.is_empty()) { + return Vector3(); + } + + if (p_uniformly) { + real_t accumulated_area = 0; + RBMap region_area_map; + + for (uint32_t rp_index = 0; rp_index < region_polygons.size(); rp_index++) { + const gd::Polygon ®ion_polygon = region_polygons[rp_index]; + real_t polyon_area = region_polygon.surface_area; + + if (polyon_area == 0.0) { + continue; + } + region_area_map[accumulated_area] = rp_index; + accumulated_area += polyon_area; + } + if (region_area_map.is_empty() || accumulated_area == 0) { + // All polygons have no real surface / no area. + return Vector3(); + } + + real_t region_area_map_pos = Math::random(real_t(0), accumulated_area); + + RBMap::Iterator region_E = region_area_map.find_closest(region_area_map_pos); + ERR_FAIL_COND_V(!region_E, Vector3()); + uint32_t rrp_polygon_index = region_E->value; + ERR_FAIL_INDEX_V(rrp_polygon_index, region_polygons.size(), Vector3()); + + const gd::Polygon &rr_polygon = region_polygons[rrp_polygon_index]; + + real_t accumulated_polygon_area = 0; + RBMap polygon_area_map; + + for (uint32_t rpp_index = 2; rpp_index < rr_polygon.points.size(); rpp_index++) { + real_t face_area = Face3(rr_polygon.points[0].pos, rr_polygon.points[rpp_index - 1].pos, rr_polygon.points[rpp_index].pos).get_area(); + + if (face_area == 0.0) { + continue; + } + polygon_area_map[accumulated_polygon_area] = rpp_index; + accumulated_polygon_area += face_area; + } + if (polygon_area_map.is_empty() || accumulated_polygon_area == 0) { + // All faces have no real surface / no area. + return Vector3(); + } + + real_t polygon_area_map_pos = Math::random(real_t(0), accumulated_polygon_area); + + RBMap::Iterator polygon_E = polygon_area_map.find_closest(polygon_area_map_pos); + ERR_FAIL_COND_V(!polygon_E, Vector3()); + uint32_t rrp_face_index = polygon_E->value; + ERR_FAIL_INDEX_V(rrp_face_index, rr_polygon.points.size(), Vector3()); + + const Face3 face(rr_polygon.points[0].pos, rr_polygon.points[rrp_face_index - 1].pos, rr_polygon.points[rrp_face_index].pos); + + Vector3 face_random_position = face.get_random_point_inside(); + return face_random_position; + + } else { + uint32_t rrp_polygon_index = Math::random(int(0), region_polygons.size() - 1); + + const gd::Polygon &rr_polygon = region_polygons[rrp_polygon_index]; + + uint32_t rrp_face_index = Math::random(int(2), rr_polygon.points.size() - 1); + + const Face3 face(rr_polygon.points[0].pos, rr_polygon.points[rrp_face_index - 1].pos, rr_polygon.points[rrp_face_index].pos); + + Vector3 face_random_position = face.get_random_point_inside(); + return face_random_position; + } +} + bool NavRegion::sync() { bool something_changed = polygons_dirty /* || something_dirty? */; @@ -113,6 +195,7 @@ void NavRegion::update_polygons() { return; } polygons.clear(); + surface_area = 0.0; polygons_dirty = false; if (map == nullptr) { @@ -147,21 +230,46 @@ void NavRegion::update_polygons() { polygons.resize(mesh->get_polygon_count()); + real_t _new_region_surface_area = 0.0; + // Build - for (size_t i(0); i < polygons.size(); i++) { - gd::Polygon &p = polygons[i]; - p.owner = this; + int navigation_mesh_polygon_index = 0; + for (gd::Polygon &polygon : polygons) { + polygon.owner = this; + polygon.surface_area = 0.0; - Vector mesh_poly = mesh->get_polygon(i); - const int *indices = mesh_poly.ptr(); + Vector navigation_mesh_polygon = mesh->get_polygon(navigation_mesh_polygon_index); + navigation_mesh_polygon_index += 1; + + int navigation_mesh_polygon_size = navigation_mesh_polygon.size(); + if (navigation_mesh_polygon_size < 3) { + continue; + } + + const int *indices = navigation_mesh_polygon.ptr(); bool valid(true); - p.points.resize(mesh_poly.size()); - p.edges.resize(mesh_poly.size()); - Vector3 center; + polygon.points.resize(navigation_mesh_polygon_size); + polygon.edges.resize(navigation_mesh_polygon_size); + + real_t _new_polygon_surface_area = 0.0; + + for (int j(2); j < navigation_mesh_polygon_size; j++) { + const Face3 face = Face3( + transform.xform(vertices_r[indices[0]]), + transform.xform(vertices_r[indices[j - 1]]), + transform.xform(vertices_r[indices[j]])); + + _new_polygon_surface_area += face.get_area(); + } + + polygon.surface_area = _new_polygon_surface_area; + _new_region_surface_area += _new_polygon_surface_area; + + Vector3 polygon_center; real_t sum(0); - for (int j(0); j < mesh_poly.size(); j++) { + for (int j(0); j < navigation_mesh_polygon_size; j++) { int idx = indices[j]; if (idx < 0 || idx >= len) { valid = false; @@ -169,10 +277,10 @@ void NavRegion::update_polygons() { } Vector3 point_position = transform.xform(vertices_r[idx]); - p.points[j].pos = point_position; - p.points[j].key = map->get_point_key(point_position); + polygon.points[j].pos = point_position; + polygon.points[j].key = map->get_point_key(point_position); - center += point_position; // Composing the center of the polygon + polygon_center += point_position; // Composing the center of the polygon if (j >= 2) { Vector3 epa = transform.xform(vertices_r[indices[j - 2]]); @@ -186,9 +294,11 @@ void NavRegion::update_polygons() { ERR_BREAK_MSG(!valid, "The navigation mesh set in this region is not valid!"); } - p.clockwise = sum > 0; - if (mesh_poly.size() != 0) { - p.center = center / real_t(mesh_poly.size()); + polygon.clockwise = sum > 0; + if (!navigation_mesh_polygon.is_empty()) { + polygon.center = polygon_center / real_t(navigation_mesh_polygon.size()); } } + + surface_area = _new_region_surface_area; } diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h index 6a8ebe533629..a9cfc53c7ea6 100644 --- a/modules/navigation/nav_region.h +++ b/modules/navigation/nav_region.h @@ -50,6 +50,8 @@ class NavRegion : public NavBase { /// Cache LocalVector polygons; + real_t surface_area = 0.0; + public: NavRegion() { type = NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_REGION; @@ -93,6 +95,10 @@ class NavRegion : public NavBase { return polygons; } + Vector3 get_random_point(uint32_t p_navigation_layers, bool p_uniformly) const; + + real_t get_surface_area() const { return surface_area; }; + bool sync(); private: diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h index 6ddd8b90780b..aa5ccc96dc83 100644 --- a/modules/navigation/nav_utils.h +++ b/modules/navigation/nav_utils.h @@ -112,6 +112,8 @@ struct Polygon { /// The center of this `Polygon` Vector3 center; + + real_t surface_area = 0.0; }; struct NavigationPoly { diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp index 3804b45e1a93..d37bbcfff0de 100644 --- a/servers/navigation_server_2d.cpp +++ b/servers/navigation_server_2d.cpp @@ -59,6 +59,8 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer2D::map_force_update); + ClassDB::bind_method(D_METHOD("map_get_random_point", "map", "navigation_layers", "uniformly"), &NavigationServer2D::map_get_random_point); + ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer2D::query_path); ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create); @@ -82,6 +84,7 @@ void NavigationServer2D::_bind_methods() { ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end); + ClassDB::bind_method(D_METHOD("region_get_random_point", "region", "navigation_layers", "uniformly"), &NavigationServer2D::region_get_random_point); ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer2D::link_create); ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer2D::link_set_map); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index 0afd794c26c6..66bfface3e68 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -103,6 +103,8 @@ class NavigationServer2D : public Object { virtual void map_force_update(RID p_map) = 0; + virtual Vector2 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const = 0; + /// Creates a new region. virtual RID region_create() = 0; @@ -145,6 +147,8 @@ class NavigationServer2D : public Object { virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0; virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0; + virtual Vector2 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const = 0; + /// Creates a new link between positions in the nav map. virtual RID link_create() = 0; diff --git a/servers/navigation_server_2d_dummy.h b/servers/navigation_server_2d_dummy.h index d64a9454aacc..d380ca5242e9 100644 --- a/servers/navigation_server_2d_dummy.h +++ b/servers/navigation_server_2d_dummy.h @@ -58,6 +58,7 @@ class NavigationServer2DDummy : public NavigationServer2D { TypedArray map_get_agents(RID p_map) const override { return TypedArray(); } TypedArray map_get_obstacles(RID p_map) const override { return TypedArray(); } void map_force_update(RID p_map) override {} + Vector2 map_get_random_point(RID p_map, uint32_t p_naviation_layers, bool p_uniformly) const override { return Vector2(); }; RID region_create() override { return RID(); } void region_set_enabled(RID p_region, bool p_enabled) override {} @@ -80,6 +81,7 @@ class NavigationServer2DDummy : public NavigationServer2D { int region_get_connections_count(RID p_region) const override { return 0; } Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override { return Vector2(); } Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override { return Vector2(); } + Vector2 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override { return Vector2(); }; RID link_create() override { return RID(); } void link_set_map(RID p_link, RID p_map) override {} diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp index eccacd3ea81f..874809a6d7df 100644 --- a/servers/navigation_server_3d.cpp +++ b/servers/navigation_server_3d.cpp @@ -64,6 +64,8 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer3D::map_force_update); + ClassDB::bind_method(D_METHOD("map_get_random_point", "map", "navigation_layers", "uniformly"), &NavigationServer3D::map_get_random_point); + ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer3D::query_path); ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create); @@ -90,6 +92,7 @@ void NavigationServer3D::_bind_methods() { ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer3D::region_get_connections_count); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start); ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end); + ClassDB::bind_method(D_METHOD("region_get_random_point", "region", "navigation_layers", "uniformly"), &NavigationServer3D::region_get_random_point); ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer3D::link_create); ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer3D::link_set_map); diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index 53d33d0058de..96587afefaf8 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -114,6 +114,8 @@ class NavigationServer3D : public Object { virtual void map_force_update(RID p_map) = 0; + virtual Vector3 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const = 0; + /// Creates a new region. virtual RID region_create() = 0; @@ -161,6 +163,8 @@ class NavigationServer3D : public Object { virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0; virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0; + virtual Vector3 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const = 0; + /// Creates a new link between positions in the nav map. virtual RID link_create() = 0; diff --git a/servers/navigation_server_3d_dummy.h b/servers/navigation_server_3d_dummy.h index 525802232802..7bd3eec93797 100644 --- a/servers/navigation_server_3d_dummy.h +++ b/servers/navigation_server_3d_dummy.h @@ -58,6 +58,7 @@ class NavigationServer3DDummy : public NavigationServer3D { Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const override { return Vector3(); } Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const override { return Vector3(); } RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const override { return RID(); } + Vector3 map_get_random_point(RID p_map, uint32_t p_navigation_layers, bool p_uniformly) const override { return Vector3(); } TypedArray map_get_links(RID p_map) const override { return TypedArray(); } TypedArray map_get_regions(RID p_map) const override { return TypedArray(); } TypedArray map_get_agents(RID p_map) const override { return TypedArray(); } @@ -87,6 +88,7 @@ class NavigationServer3DDummy : public NavigationServer3D { int region_get_connections_count(RID p_region) const override { return 0; } Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override { return Vector3(); } Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override { return Vector3(); } + Vector3 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override { return Vector3(); } RID link_create() override { return RID(); } void link_set_map(RID p_link, RID p_map) override {} RID link_get_map(RID p_link) const override { return RID(); }