From f15cb16b1478b10d16df502c02b530b4b0ea670c Mon Sep 17 00:00:00 2001
From: smix8 <52464204+smix8@users.noreply.github.com>
Date: Mon, 3 Oct 2022 11:51:17 +0200
Subject: [PATCH] Fix avoidance calculation on NO_THREADS build
---
doc/classes/NavigationAgent.xml | 1 +
doc/classes/NavigationAgent2D.xml | 1 +
doc/classes/NavigationServer.xml | 1 +
modules/navigation/nav_map.cpp | 9 +++++++++
modules/navigation/nav_map.h | 2 ++
5 files changed, 14 insertions(+)
diff --git a/doc/classes/NavigationAgent.xml b/doc/classes/NavigationAgent.xml
index 5f8eed4619e..e4b0f55dbd9 100644
--- a/doc/classes/NavigationAgent.xml
+++ b/doc/classes/NavigationAgent.xml
@@ -6,6 +6,7 @@
3D agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO (Reciprocal Velocity Obstacles) collision avoidance. The agent needs navigation data to work correctly. By default this node will register to the default [World] navigation map. If this node is a child of a [Navigation] node it will register to the navigation map of the navigation node or the function [method set_navigation] can be used to set the navigation node directly. [NavigationAgent] is physics safe.
[b]Note:[/b] After [method set_target_location] is used it is required to use the [method get_next_location] function once every physics frame to update the internal path logic of the NavigationAgent. The returned vector position from this function should be used as the next movement position for the agent's parent Node.
+ [b]Note:[/b] By default, the expensive calculations for avoidance are done in a thread. In HTML5 exports without thread support, they will be done on the main thread, which can lead to performance issues.
diff --git a/doc/classes/NavigationAgent2D.xml b/doc/classes/NavigationAgent2D.xml
index 9f10fca12e2..10201100bc4 100644
--- a/doc/classes/NavigationAgent2D.xml
+++ b/doc/classes/NavigationAgent2D.xml
@@ -6,6 +6,7 @@
2D agent that is used in navigation to reach a location while avoiding static and dynamic obstacles. The dynamic obstacles are avoided using RVO (Reciprocal Velocity Obstacles) collision avoidance. The agent needs navigation data to work correctly. By default this node will register to the default [World2D] navigation map. If this node is a child of a [Navigation2D] node it will register to the navigation map of the navigation node or the function [method set_navigation] can be used to set the navigation node directly. [NavigationAgent2D] is physics safe.
[b]Note:[/b] After [method set_target_location] is used it is required to use the [method get_next_location] function once every physics frame to update the internal path logic of the NavigationAgent. The returned vector position from this function should be used as the next movement position for the agent's parent Node.
+ [b]Note:[/b] By default, the expensive calculations for avoidance are done in a thread. In HTML5 exports without thread support, they will be done on the main thread, which can lead to performance issues.
diff --git a/doc/classes/NavigationServer.xml b/doc/classes/NavigationServer.xml
index 4637a33b536..663663898e9 100644
--- a/doc/classes/NavigationServer.xml
+++ b/doc/classes/NavigationServer.xml
@@ -10,6 +10,7 @@
For two regions to be connected to each other, they must share a similar edge. An edge is considered connected to another if both of its two vertices are at a distance less than [member Navigation.edge_connection_margin] to the respective other edge's vertex.
To use the collision avoidance system, you may use agents. You can set an agent's target velocity, then the servers will emit a callback with a modified velocity.
[b]Note:[/b] The collision avoidance system ignores regions. Using the modified velocity as-is might lead to pushing and agent outside of a navigable area. This is a limitation of the collision avoidance system, any more complex situation may require the use of the physics engine.
+ [b]Note:[/b] By default, the expensive calculations for avoidance are done in a thread. In HTML5 exports without thread support, they will be done on the main thread, which can lead to performance issues.
This server keeps tracks of any call and executes them during the sync phase. This means that you can request any change to the map, using any thread, without worrying.
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 4fae3e16e84..21fec7c8924 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -690,6 +690,7 @@ void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) {
void NavMap::step(real_t p_deltatime) {
deltatime = p_deltatime;
if (controlled_agents.size() > 0) {
+#ifndef NO_THREADS
if (step_work_pool.get_thread_count() == 0) {
step_work_pool.init();
}
@@ -698,6 +699,12 @@ void NavMap::step(real_t p_deltatime) {
this,
&NavMap::compute_single_step,
controlled_agents.ptr());
+#else
+ for (int i(0); i < static_cast(controlled_agents.size()); i++) {
+ controlled_agents[i]->get_agent()->computeNeighbors(&rvo);
+ controlled_agents[i]->get_agent()->computeNewVelocity(deltatime);
+ }
+#endif // NO_THREADS
}
}
@@ -743,5 +750,7 @@ NavMap::NavMap() {
}
NavMap::~NavMap() {
+#ifndef NO_THREADS
step_work_pool.finish();
+#endif // !NO_THREADS
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index d315aaeeda2..9c827d64e16 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -82,8 +82,10 @@ class NavMap : public NavRid {
/// Change the id each time the map is updated.
uint32_t map_update_id = 0;
+#ifndef NO_THREADS
/// Pooled threads for computing steps
ThreadWorkPool step_work_pool;
+#endif // NO_THREADS
public:
NavMap();