Skip to content

Commit

Permalink
Add NavigationServer random point queries
Browse files Browse the repository at this point in the history
Adds query functions to get random points on navigation mesh to the NavigationServer.
  • Loading branch information
smix8 committed Dec 7, 2023
1 parent a311a4b commit 64a5624
Show file tree
Hide file tree
Showing 17 changed files with 290 additions and 16 deletions.
22 changes: 22 additions & 0 deletions doc/classes/NavigationServer2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
</description>
</method>
<method name="map_get_random_point" qualifiers="const">
<return type="Vector2" />
<param index="0" name="map" type="RID" />
<param index="1" name="navigation_layers" type="int" />
<param index="2" name="uniformly" type="bool" />
<description>
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).
</description>
</method>
<method name="map_get_regions" qualifiers="const">
<return type="RID[]" />
<param index="0" name="map" type="RID" />
Expand Down Expand Up @@ -681,6 +692,17 @@
Returns the [code]ObjectID[/code] of the object which manages this region.
</description>
</method>
<method name="region_get_random_point" qualifiers="const">
<return type="Vector2" />
<param index="0" name="region" type="RID" />
<param index="1" name="navigation_layers" type="int" />
<param index="2" name="uniformly" type="bool" />
<description>
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).
</description>
</method>
<method name="region_get_travel_cost" qualifiers="const">
<return type="float" />
<param index="0" name="region" type="RID" />
Expand Down
22 changes: 22 additions & 0 deletions doc/classes/NavigationServer3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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.
</description>
</method>
<method name="map_get_random_point" qualifiers="const">
<return type="Vector3" />
<param index="0" name="map" type="RID" />
<param index="1" name="navigation_layers" type="int" />
<param index="2" name="uniformly" type="bool" />
<description>
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).
</description>
</method>
<method name="map_get_regions" qualifiers="const">
<return type="RID[]" />
<param index="0" name="map" type="RID" />
Expand Down Expand Up @@ -793,6 +804,17 @@
Returns the [code]ObjectID[/code] of the object which manages this region.
</description>
</method>
<method name="region_get_random_point" qualifiers="const">
<return type="Vector3" />
<param index="0" name="region" type="RID" />
<param index="1" name="navigation_layers" type="int" />
<param index="2" name="uniformly" type="bool" />
<description>
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).
</description>
</method>
<method name="region_get_travel_cost" qualifiers="const">
<return type="float" />
<param index="0" name="region" type="RID" />
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 @@ -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);

Expand Down Expand Up @@ -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);

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 @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
11 changes: 10 additions & 1 deletion modules/navigation/godot_navigation_server_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,12 @@ Vector<Vector2> 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);
Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions modules/navigation/godot_navigation_server_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class GodotNavigationServer2D : public NavigationServer2D {
virtual TypedArray<RID> map_get_agents(RID p_map) const override;
virtual TypedArray<RID> 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;
Expand All @@ -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;

Expand Down
64 changes: 64 additions & 0 deletions modules/navigation/nav_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<NavRegion *> map_regions = get_regions();

if (map_regions.is_empty()) {
return Vector3();
}

LocalVector<const NavRegion *> 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<real_t, uint32_t> 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<real_t, uint32_t>::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();
Expand Down
2 changes: 2 additions & 0 deletions modules/navigation/nav_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading

0 comments on commit 64a5624

Please sign in to comment.