Skip to content

Commit

Permalink
Merge pull request #75098 from smix8/map_random_point_queries_4.x
Browse files Browse the repository at this point in the history
Add NavigationServer random point queries
  • Loading branch information
akien-mga committed Dec 11, 2023
2 parents 6882e50 + 64a5624 commit 9eb47ce
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 9eb47ce

Please sign in to comment.