summaryrefslogtreecommitdiff
path: root/modules/navigation
diff options
context:
space:
mode:
Diffstat (limited to 'modules/navigation')
-rw-r--r--modules/navigation/editor/navigation_mesh_editor_plugin.cpp30
-rw-r--r--modules/navigation/godot_navigation_server.cpp88
-rw-r--r--modules/navigation/godot_navigation_server.h12
-rw-r--r--modules/navigation/nav_map.cpp94
-rw-r--r--modules/navigation/nav_map.h20
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp14
6 files changed, 197 insertions, 61 deletions
diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
index 54f7abda8d..557d45b386 100644
--- a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
+++ b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
@@ -60,12 +60,40 @@ void NavigationMeshEditor::_bake_pressed() {
button_bake->set_pressed(false);
ERR_FAIL_COND(!node);
- if (!node->get_navigation_mesh().is_valid()) {
+ Ref<NavigationMesh> navmesh = node->get_navigation_mesh();
+ if (!navmesh.is_valid()) {
err_dialog->set_text(TTR("A NavigationMesh resource must be set or created for this node to work."));
err_dialog->popup_centered();
return;
}
+ String path = navmesh->get_path();
+ if (!path.is_resource_file()) {
+ int srpos = path.find("::");
+ if (srpos != -1) {
+ String base = path.substr(0, srpos);
+ if (ResourceLoader::get_resource_type(base) == "PackedScene") {
+ if (!get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->get_scene_file_path() != base) {
+ err_dialog->set_text(TTR("Cannot generate navigation mesh because it does not belong to the edited scene. Make it unique first."));
+ err_dialog->popup_centered();
+ return;
+ }
+ } else {
+ if (FileAccess::exists(base + ".import")) {
+ err_dialog->set_text(TTR("Cannot generate navigation mesh because it belongs to a resource which was imported."));
+ err_dialog->popup_centered();
+ return;
+ }
+ }
+ }
+ } else {
+ if (FileAccess::exists(path + ".import")) {
+ err_dialog->set_text(TTR("Cannot generate navigation mesh because the resource was imported from another type."));
+ err_dialog->popup_centered();
+ return;
+ }
+ }
+
NavigationMeshGenerator::get_singleton()->clear(node->get_navigation_mesh());
NavigationMeshGenerator::get_singleton()->bake(node->get_navigation_mesh(), node);
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index b9b92b77c9..2b5db6462c 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -731,24 +731,21 @@ COMMAND_1(free, RID, p_object) {
NavMap *map = map_owner.get_or_null(p_object);
// Removes any assigned region
- LocalVector<NavRegion *> regions = map->get_regions();
- for (uint32_t i = 0; i < regions.size(); i++) {
- map->remove_region(regions[i]);
- regions[i]->set_map(nullptr);
+ for (NavRegion *region : map->get_regions()) {
+ map->remove_region(region);
+ region->set_map(nullptr);
}
// Removes any assigned links
- LocalVector<NavLink *> links = map->get_links();
- for (uint32_t i = 0; i < links.size(); i++) {
- map->remove_link(links[i]);
- links[i]->set_map(nullptr);
+ for (NavLink *link : map->get_links()) {
+ map->remove_link(link);
+ link->set_map(nullptr);
}
// Remove any assigned agent
- LocalVector<RvoAgent *> agents = map->get_agents();
- for (uint32_t i = 0; i < agents.size(); i++) {
- map->remove_agent(agents[i]);
- agents[i]->set_map(nullptr);
+ for (RvoAgent *agent : map->get_agents()) {
+ map->remove_agent(agent);
+ agent->set_map(nullptr);
}
int map_index = active_maps.find(map);
@@ -806,9 +803,9 @@ void GodotNavigationServer::flush_queries() {
MutexLock lock(commands_mutex);
MutexLock lock2(operations_mutex);
- for (size_t i(0); i < commands.size(); i++) {
- commands[i]->exec(this);
- memdelete(commands[i]);
+ for (SetCommand *command : commands) {
+ command->exec(this);
+ memdelete(command);
}
commands.clear();
}
@@ -829,6 +826,15 @@ void GodotNavigationServer::process(real_t p_delta_time) {
return;
}
+ int _new_pm_region_count = 0;
+ int _new_pm_agent_count = 0;
+ int _new_pm_link_count = 0;
+ int _new_pm_polygon_count = 0;
+ int _new_pm_edge_count = 0;
+ int _new_pm_edge_merge_count = 0;
+ int _new_pm_edge_connection_count = 0;
+ int _new_pm_edge_free_count = 0;
+
// In c++ we can't be sure that this is performed in the main thread
// even with mutable functions.
MutexLock lock(operations_mutex);
@@ -837,6 +843,15 @@ void GodotNavigationServer::process(real_t p_delta_time) {
active_maps[i]->step(p_delta_time);
active_maps[i]->dispatch_callbacks();
+ _new_pm_region_count += active_maps[i]->get_pm_region_count();
+ _new_pm_agent_count += active_maps[i]->get_pm_agent_count();
+ _new_pm_link_count += active_maps[i]->get_pm_link_count();
+ _new_pm_polygon_count += active_maps[i]->get_pm_polygon_count();
+ _new_pm_edge_count += active_maps[i]->get_pm_edge_count();
+ _new_pm_edge_merge_count += active_maps[i]->get_pm_edge_merge_count();
+ _new_pm_edge_connection_count += active_maps[i]->get_pm_edge_connection_count();
+ _new_pm_edge_free_count += active_maps[i]->get_pm_edge_free_count();
+
// Emit a signal if a map changed.
const uint32_t new_map_update_id = active_maps[i]->get_map_update_id();
if (new_map_update_id != active_maps_update_id[i]) {
@@ -844,6 +859,15 @@ void GodotNavigationServer::process(real_t p_delta_time) {
active_maps_update_id[i] = new_map_update_id;
}
}
+
+ pm_region_count = _new_pm_region_count;
+ pm_agent_count = _new_pm_agent_count;
+ pm_link_count = _new_pm_link_count;
+ pm_polygon_count = _new_pm_polygon_count;
+ pm_edge_count = _new_pm_edge_count;
+ pm_edge_merge_count = _new_pm_edge_merge_count;
+ pm_edge_connection_count = _new_pm_edge_connection_count;
+ pm_edge_free_count = _new_pm_edge_free_count;
}
PathQueryResult GodotNavigationServer::_query_path(const PathQueryParameters &p_parameters) const {
@@ -886,6 +910,40 @@ PathQueryResult GodotNavigationServer::_query_path(const PathQueryParameters &p_
return r_query_result;
}
+int GodotNavigationServer::get_process_info(ProcessInfo p_info) const {
+ switch (p_info) {
+ case INFO_ACTIVE_MAPS: {
+ return active_maps.size();
+ } break;
+ case INFO_REGION_COUNT: {
+ return pm_region_count;
+ } break;
+ case INFO_AGENT_COUNT: {
+ return pm_agent_count;
+ } break;
+ case INFO_LINK_COUNT: {
+ return pm_link_count;
+ } break;
+ case INFO_POLYGON_COUNT: {
+ return pm_polygon_count;
+ } break;
+ case INFO_EDGE_COUNT: {
+ return pm_edge_count;
+ } break;
+ case INFO_EDGE_MERGE_COUNT: {
+ return pm_edge_merge_count;
+ } break;
+ case INFO_EDGE_CONNECTION_COUNT: {
+ return pm_edge_connection_count;
+ } break;
+ case INFO_EDGE_FREE_COUNT: {
+ return pm_edge_free_count;
+ } break;
+ }
+
+ return 0;
+}
+
#undef COMMAND_1
#undef COMMAND_2
#undef COMMAND_4
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 7a6e5bb208..a87a88d3bc 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -81,6 +81,16 @@ class GodotNavigationServer : public NavigationServer3D {
LocalVector<NavMap *> active_maps;
LocalVector<uint32_t> active_maps_update_id;
+ // Performance Monitor
+ int pm_region_count = 0;
+ int pm_agent_count = 0;
+ int pm_link_count = 0;
+ int pm_polygon_count = 0;
+ int pm_edge_count = 0;
+ int pm_edge_merge_count = 0;
+ int pm_edge_connection_count = 0;
+ int pm_edge_free_count = 0;
+
public:
GodotNavigationServer();
virtual ~GodotNavigationServer();
@@ -182,6 +192,8 @@ public:
virtual void process(real_t p_delta_time) override;
virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const override;
+
+ int get_process_info(ProcessInfo p_info) const override;
};
#undef COMMAND_1
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 2a2f8aa1b7..fe255c1ce8 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -103,9 +103,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
float begin_d = 1e20;
float end_d = 1e20;
// Find the initial poly and the end poly on this map.
- for (size_t i(0); i < polygons.size(); i++) {
- const gd::Polygon &p = polygons[i];
-
+ for (const gd::Polygon &p : polygons) {
// Only consider the polygon if it in a region with compatible layers.
if ((p_navigation_layers & p.owner->get_navigation_layers()) == 0) {
continue;
@@ -190,9 +188,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
while (true) {
// Takes the current least_cost_poly neighbors (iterating over its edges) and compute the traveled_distance.
- for (size_t i = 0; i < navigation_polys[least_cost_id].poly->edges.size(); i++) {
- const gd::Edge &edge = navigation_polys[least_cost_id].poly->edges[i];
-
+ for (const gd::Edge &edge : navigation_polys[least_cost_id].poly->edges) {
// Iterate over connections in this edge, then compute the new optimized travel distance assigned to this polygon.
for (int connection_index = 0; connection_index < edge.connections.size(); connection_index++) {
const gd::Edge::Connection &connection = edge.connections[connection_index];
@@ -229,7 +225,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
avp.entry = new_entry;
}
} else {
- // Add the neighbour polygon to the reachable ones.
+ // Add the neighbor polygon to the reachable ones.
gd::NavigationPoly new_navigation_poly = gd::NavigationPoly(connection.polygon);
new_navigation_poly.self_id = navigation_polys.size();
new_navigation_poly.back_navigation_poly_id = least_cost_id;
@@ -240,7 +236,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
new_navigation_poly.entry = new_entry;
navigation_polys.push_back(new_navigation_poly);
- // Add the neighbour polygon to the polygons to visit.
+ // Add the neighbor polygon to the polygons to visit.
to_visit.push_back(navigation_polys.size() - 1);
}
}
@@ -465,9 +461,7 @@ Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector
Vector3 closest_point;
real_t closest_point_d = 1e20;
- for (size_t i(0); i < polygons.size(); i++) {
- const gd::Polygon &p = polygons[i];
-
+ for (const gd::Polygon &p : polygons) {
// For each face check the distance to the segment
for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) {
const Face3 f(p.points[0].pos, p.points[point_id - 1].pos, p.points[point_id].pos);
@@ -611,54 +605,70 @@ void NavMap::remove_agent_as_controlled(RvoAgent *agent) {
}
void NavMap::sync() {
+ // Performance Monitor
+ int _new_pm_region_count = regions.size();
+ int _new_pm_agent_count = agents.size();
+ int _new_pm_link_count = links.size();
+ int _new_pm_polygon_count = pm_polygon_count;
+ int _new_pm_edge_count = pm_edge_count;
+ int _new_pm_edge_merge_count = pm_edge_merge_count;
+ int _new_pm_edge_connection_count = pm_edge_connection_count;
+ int _new_pm_edge_free_count = pm_edge_free_count;
+
// Check if we need to update the links.
if (regenerate_polygons) {
- for (uint32_t r = 0; r < regions.size(); r++) {
- regions[r]->scratch_polygons();
+ for (NavRegion *region : regions) {
+ region->scratch_polygons();
}
regenerate_links = true;
}
- for (uint32_t r = 0; r < regions.size(); r++) {
- if (regions[r]->sync()) {
+ for (NavRegion *region : regions) {
+ if (region->sync()) {
regenerate_links = true;
}
}
- for (uint32_t l = 0; l < links.size(); l++) {
- if (links[l]->check_dirty()) {
+ for (NavLink *link : links) {
+ if (link->check_dirty()) {
regenerate_links = true;
}
}
if (regenerate_links) {
+ _new_pm_polygon_count = 0;
+ _new_pm_edge_count = 0;
+ _new_pm_edge_merge_count = 0;
+ _new_pm_edge_connection_count = 0;
+ _new_pm_edge_free_count = 0;
+
// Remove regions connections.
- for (uint32_t r = 0; r < regions.size(); r++) {
- regions[r]->get_connections().clear();
+ for (NavRegion *region : regions) {
+ region->get_connections().clear();
}
// Resize the polygon count.
int count = 0;
- for (uint32_t r = 0; r < regions.size(); r++) {
- count += regions[r]->get_polygons().size();
+ for (const NavRegion *region : regions) {
+ count += region->get_polygons().size();
}
polygons.resize(count);
// Copy all region polygons in the map.
count = 0;
- for (uint32_t r = 0; r < regions.size(); r++) {
- const LocalVector<gd::Polygon> &polygons_source = regions[r]->get_polygons();
+ for (const NavRegion *region : regions) {
+ const LocalVector<gd::Polygon> &polygons_source = region->get_polygons();
for (uint32_t n = 0; n < polygons_source.size(); n++) {
polygons[count + n] = polygons_source[n];
}
- count += regions[r]->get_polygons().size();
+ count += region->get_polygons().size();
}
+ _new_pm_polygon_count = polygons.size();
+
// Group all edges per key.
HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey> connections;
- for (uint32_t poly_id = 0; poly_id < polygons.size(); poly_id++) {
- gd::Polygon &poly(polygons[poly_id]);
-
+ for (gd::Polygon &poly : polygons) {
for (uint32_t p = 0; p < poly.points.size(); p++) {
int next_point = (p + 1) % poly.points.size();
gd::EdgeKey ek(poly.points[p].key, poly.points[next_point].key);
@@ -666,6 +676,7 @@ void NavMap::sync() {
HashMap<gd::EdgeKey, Vector<gd::Edge::Connection>, gd::EdgeKey>::Iterator connection = connections.find(ek);
if (!connection) {
connections[ek] = Vector<gd::Edge::Connection>();
+ _new_pm_edge_count += 1;
}
if (connections[ek].size() <= 1) {
// Add the polygon/edge tuple to this key.
@@ -691,6 +702,7 @@ void NavMap::sync() {
c1.polygon->edges[c1.edge].connections.push_back(c2);
c2.polygon->edges[c2.edge].connections.push_back(c1);
// Note: The pathway_start/end are full for those connection and do not need to be modified.
+ _new_pm_edge_merge_count += 1;
} else {
CRASH_COND_MSG(E.value.size() != 1, vformat("Number of connection != 1. Found: %d", E.value.size()));
free_edges.push_back(E.value[0]);
@@ -704,6 +716,8 @@ void NavMap::sync() {
// to be connected, create new polygons to remove that small gap is
// not really useful and would result in wasteful computation during
// connection, integration and path finding.
+ _new_pm_edge_free_count = free_edges.size();
+
for (int i = 0; i < free_edges.size(); i++) {
const gd::Edge::Connection &free_edge = free_edges[i];
Vector3 edge_p1 = free_edge.polygon->points[free_edge.edge].pos;
@@ -757,6 +771,7 @@ void NavMap::sync() {
// Add the connection to the region_connection map.
((NavRegion *)free_edge.polygon->owner)->get_connections().push_back(new_connection);
+ _new_pm_edge_connection_count += 1;
}
}
@@ -764,8 +779,7 @@ void NavMap::sync() {
link_polygons.resize(links.size());
// Search for polygons within range of a nav link.
- for (uint32_t l = 0; l < links.size(); l++) {
- const NavLink *link = links[l];
+ for (const NavLink *link : links) {
const Vector3 start = link->get_start_location();
const Vector3 end = link->get_end_location();
@@ -797,9 +811,7 @@ void NavMap::sync() {
}
// Find any polygons within the search radius of the end point.
- for (uint32_t end_index = 0; end_index < polygons.size(); end_index++) {
- gd::Polygon &end_poly = polygons[end_index];
-
+ for (gd::Polygon &end_poly : polygons) {
// For each face check the distance to the end
for (uint32_t end_point_id = 2; end_point_id < end_poly.points.size(); end_point_id += 1) {
const Face3 end_face(end_poly.points[0].pos, end_poly.points[end_point_id - 1].pos, end_poly.points[end_point_id].pos);
@@ -883,8 +895,8 @@ void NavMap::sync() {
// cannot use LocalVector here as RVO library expects std::vector to build KdTree
std::vector<RVO::Agent *> raw_agents;
raw_agents.reserve(agents.size());
- for (size_t i(0); i < agents.size(); i++) {
- raw_agents.push_back(agents[i]->get_agent());
+ for (RvoAgent *agent : agents) {
+ raw_agents.push_back(agent->get_agent());
}
rvo.buildAgentTree(raw_agents);
}
@@ -892,6 +904,16 @@ void NavMap::sync() {
regenerate_polygons = false;
regenerate_links = false;
agents_dirty = false;
+
+ // Performance Monitor
+ pm_region_count = _new_pm_region_count;
+ pm_agent_count = _new_pm_agent_count;
+ pm_link_count = _new_pm_link_count;
+ pm_polygon_count = _new_pm_polygon_count;
+ pm_edge_count = _new_pm_edge_count;
+ pm_edge_merge_count = _new_pm_edge_merge_count;
+ pm_edge_connection_count = _new_pm_edge_connection_count;
+ pm_edge_free_count = _new_pm_edge_free_count;
}
void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) {
@@ -908,8 +930,8 @@ void NavMap::step(real_t p_deltatime) {
}
void NavMap::dispatch_callbacks() {
- for (int i(0); i < static_cast<int>(controlled_agents.size()); i++) {
- controlled_agents[i]->dispatch_callback();
+ for (RvoAgent *agent : controlled_agents) {
+ agent->dispatch_callback();
}
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 321d5560f0..fce7aff3ba 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -89,6 +89,16 @@ class NavMap : public NavRid {
/// Change the id each time the map is updated.
uint32_t map_update_id = 0;
+ // Performance Monitor
+ int pm_region_count = 0;
+ int pm_agent_count = 0;
+ int pm_link_count = 0;
+ int pm_polygon_count = 0;
+ int pm_edge_count = 0;
+ int pm_edge_merge_count = 0;
+ int pm_edge_connection_count = 0;
+ int pm_edge_free_count = 0;
+
public:
NavMap();
~NavMap();
@@ -152,6 +162,16 @@ public:
void step(real_t p_deltatime);
void dispatch_callbacks();
+ // Performance Monitor
+ int get_pm_region_count() const { return pm_region_count; }
+ int get_pm_agent_count() const { return pm_agent_count; }
+ int get_pm_link_count() const { return pm_link_count; }
+ int get_pm_polygon_count() const { return pm_polygon_count; }
+ int get_pm_edge_count() const { return pm_edge_count; }
+ int get_pm_edge_merge_count() const { return pm_edge_merge_count; }
+ int get_pm_edge_connection_count() const { return pm_edge_connection_count; }
+ int get_pm_edge_free_count() const { return pm_edge_free_count; }
+
private:
void compute_single_step(uint32_t index, RvoAgent **agent);
void clip_path(const LocalVector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const;
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index 568e8b9b26..74ff9312fd 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -207,11 +207,11 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
List<uint32_t> shape_owners;
static_body->get_shape_owners(&shape_owners);
for (uint32_t shape_owner : shape_owners) {
+ if (static_body->is_shape_owner_disabled(shape_owner)) {
+ continue;
+ }
const int shape_count = static_body->shape_owner_get_shape_count(shape_owner);
for (int i = 0; i < shape_count; i++) {
- if (static_body->is_shape_owner_disabled(i)) {
- continue;
- }
Ref<Shape3D> s = static_body->shape_owner_get_shape(shape_owner, i);
if (s.is_null()) {
continue;
@@ -266,9 +266,7 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
if (err == OK) {
PackedVector3Array faces;
- for (uint32_t j = 0; j < md.faces.size(); ++j) {
- const Geometry3D::MeshData::Face &face = md.faces[j];
-
+ for (const Geometry3D::MeshData::Face &face : md.faces) {
for (uint32_t k = 2; k < face.indices.size(); ++k) {
faces.push_back(md.vertices[face.indices[0]]);
faces.push_back(md.vertices[face.indices[k - 1]]);
@@ -392,9 +390,7 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
if (err == OK) {
PackedVector3Array faces;
- for (uint32_t j = 0; j < md.faces.size(); ++j) {
- const Geometry3D::MeshData::Face &face = md.faces[j];
-
+ for (const Geometry3D::MeshData::Face &face : md.faces) {
for (uint32_t k = 2; k < face.indices.size(); ++k) {
faces.push_back(md.vertices[face.indices[0]]);
faces.push_back(md.vertices[face.indices[k - 1]]);