1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-10 13:00:37 +00:00

Add NavigationServer random point queries

Adds query functions to get random points on navigation mesh to the NavigationServer.
This commit is contained in:
smix8
2023-10-23 18:16:05 +02:00
parent a311a4b162
commit 64a56245d8
17 changed files with 290 additions and 16 deletions

View File

@@ -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();