Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NavigationServer random point queries #75098

Merged
merged 1 commit into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading