nav_agent.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /**************************************************************************/
  2. /* nav_agent.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "nav_agent.h"
  31. #include "nav_map.h"
  32. void NavAgent::set_avoidance_enabled(bool p_enabled) {
  33. avoidance_enabled = p_enabled;
  34. _update_rvo_agent_properties();
  35. }
  36. void NavAgent::set_use_3d_avoidance(bool p_enabled) {
  37. use_3d_avoidance = p_enabled;
  38. _update_rvo_agent_properties();
  39. }
  40. void NavAgent::_update_rvo_agent_properties() {
  41. if (use_3d_avoidance) {
  42. rvo_agent_3d.neighborDist_ = neighbor_distance;
  43. rvo_agent_3d.maxNeighbors_ = max_neighbors;
  44. rvo_agent_3d.timeHorizon_ = time_horizon_agents;
  45. rvo_agent_3d.timeHorizonObst_ = time_horizon_obstacles;
  46. rvo_agent_3d.radius_ = radius;
  47. rvo_agent_3d.maxSpeed_ = max_speed;
  48. rvo_agent_3d.position_ = RVO3D::Vector3(position.x, position.y, position.z);
  49. // Replacing the internal velocity directly causes major jitter / bugs due to unpredictable velocity jumps, left line here for testing.
  50. //rvo_agent_3d.velocity_ = RVO3D::Vector3(velocity.x, velocity.y ,velocity.z);
  51. rvo_agent_3d.prefVelocity_ = RVO3D::Vector3(velocity.x, velocity.y, velocity.z);
  52. rvo_agent_3d.height_ = height;
  53. rvo_agent_3d.avoidance_layers_ = avoidance_layers;
  54. rvo_agent_3d.avoidance_mask_ = avoidance_mask;
  55. rvo_agent_3d.avoidance_priority_ = avoidance_priority;
  56. } else {
  57. rvo_agent_2d.neighborDist_ = neighbor_distance;
  58. rvo_agent_2d.maxNeighbors_ = max_neighbors;
  59. rvo_agent_2d.timeHorizon_ = time_horizon_agents;
  60. rvo_agent_2d.timeHorizonObst_ = time_horizon_obstacles;
  61. rvo_agent_2d.radius_ = radius;
  62. rvo_agent_2d.maxSpeed_ = max_speed;
  63. rvo_agent_2d.position_ = RVO2D::Vector2(position.x, position.z);
  64. rvo_agent_2d.elevation_ = position.y;
  65. // Replacing the internal velocity directly causes major jitter / bugs due to unpredictable velocity jumps, left line here for testing.
  66. //rvo_agent_2d.velocity_ = RVO2D::Vector2(velocity.x, velocity.z);
  67. rvo_agent_2d.prefVelocity_ = RVO2D::Vector2(velocity.x, velocity.z);
  68. rvo_agent_2d.height_ = height;
  69. rvo_agent_2d.avoidance_layers_ = avoidance_layers;
  70. rvo_agent_2d.avoidance_mask_ = avoidance_mask;
  71. rvo_agent_2d.avoidance_priority_ = avoidance_priority;
  72. }
  73. if (map != nullptr) {
  74. if (avoidance_enabled) {
  75. map->set_agent_as_controlled(this);
  76. } else {
  77. map->remove_agent_as_controlled(this);
  78. }
  79. }
  80. agent_dirty = true;
  81. request_sync();
  82. }
  83. void NavAgent::set_map(NavMap *p_map) {
  84. if (map == p_map) {
  85. return;
  86. }
  87. cancel_sync_request();
  88. if (map) {
  89. map->remove_agent(this);
  90. }
  91. map = p_map;
  92. agent_dirty = true;
  93. if (map) {
  94. map->add_agent(this);
  95. if (avoidance_enabled) {
  96. map->set_agent_as_controlled(this);
  97. }
  98. request_sync();
  99. }
  100. }
  101. bool NavAgent::is_map_changed() {
  102. if (map) {
  103. bool is_changed = map->get_iteration_id() != last_map_iteration_id;
  104. last_map_iteration_id = map->get_iteration_id();
  105. return is_changed;
  106. } else {
  107. return false;
  108. }
  109. }
  110. void NavAgent::set_avoidance_callback(Callable p_callback) {
  111. avoidance_callback = p_callback;
  112. }
  113. bool NavAgent::has_avoidance_callback() const {
  114. return avoidance_callback.is_valid();
  115. }
  116. void NavAgent::dispatch_avoidance_callback() {
  117. if (!avoidance_callback.is_valid()) {
  118. return;
  119. }
  120. Vector3 new_velocity;
  121. if (use_3d_avoidance) {
  122. new_velocity = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  123. } else {
  124. new_velocity = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  125. }
  126. if (clamp_speed) {
  127. new_velocity = new_velocity.limit_length(max_speed);
  128. }
  129. // Invoke the callback with the new velocity.
  130. avoidance_callback.call(new_velocity);
  131. }
  132. void NavAgent::set_neighbor_distance(real_t p_neighbor_distance) {
  133. neighbor_distance = p_neighbor_distance;
  134. if (use_3d_avoidance) {
  135. rvo_agent_3d.neighborDist_ = neighbor_distance;
  136. } else {
  137. rvo_agent_2d.neighborDist_ = neighbor_distance;
  138. }
  139. agent_dirty = true;
  140. request_sync();
  141. }
  142. void NavAgent::set_max_neighbors(int p_max_neighbors) {
  143. max_neighbors = p_max_neighbors;
  144. if (use_3d_avoidance) {
  145. rvo_agent_3d.maxNeighbors_ = max_neighbors;
  146. } else {
  147. rvo_agent_2d.maxNeighbors_ = max_neighbors;
  148. }
  149. agent_dirty = true;
  150. request_sync();
  151. }
  152. void NavAgent::set_time_horizon_agents(real_t p_time_horizon) {
  153. time_horizon_agents = p_time_horizon;
  154. if (use_3d_avoidance) {
  155. rvo_agent_3d.timeHorizon_ = time_horizon_agents;
  156. } else {
  157. rvo_agent_2d.timeHorizon_ = time_horizon_agents;
  158. }
  159. agent_dirty = true;
  160. request_sync();
  161. }
  162. void NavAgent::set_time_horizon_obstacles(real_t p_time_horizon) {
  163. time_horizon_obstacles = p_time_horizon;
  164. if (use_3d_avoidance) {
  165. rvo_agent_3d.timeHorizonObst_ = time_horizon_obstacles;
  166. } else {
  167. rvo_agent_2d.timeHorizonObst_ = time_horizon_obstacles;
  168. }
  169. agent_dirty = true;
  170. request_sync();
  171. }
  172. void NavAgent::set_radius(real_t p_radius) {
  173. radius = p_radius;
  174. if (use_3d_avoidance) {
  175. rvo_agent_3d.radius_ = radius;
  176. } else {
  177. rvo_agent_2d.radius_ = radius;
  178. }
  179. agent_dirty = true;
  180. request_sync();
  181. }
  182. void NavAgent::set_height(real_t p_height) {
  183. height = p_height;
  184. if (use_3d_avoidance) {
  185. rvo_agent_3d.height_ = height;
  186. } else {
  187. rvo_agent_2d.height_ = height;
  188. }
  189. agent_dirty = true;
  190. request_sync();
  191. }
  192. void NavAgent::set_max_speed(real_t p_max_speed) {
  193. max_speed = p_max_speed;
  194. if (avoidance_enabled) {
  195. if (use_3d_avoidance) {
  196. rvo_agent_3d.maxSpeed_ = max_speed;
  197. } else {
  198. rvo_agent_2d.maxSpeed_ = max_speed;
  199. }
  200. }
  201. agent_dirty = true;
  202. request_sync();
  203. }
  204. void NavAgent::set_position(const Vector3 p_position) {
  205. position = p_position;
  206. if (avoidance_enabled) {
  207. if (use_3d_avoidance) {
  208. rvo_agent_3d.position_ = RVO3D::Vector3(p_position.x, p_position.y, p_position.z);
  209. } else {
  210. rvo_agent_2d.elevation_ = p_position.y;
  211. rvo_agent_2d.position_ = RVO2D::Vector2(p_position.x, p_position.z);
  212. }
  213. }
  214. agent_dirty = true;
  215. request_sync();
  216. }
  217. void NavAgent::set_target_position(const Vector3 p_target_position) {
  218. target_position = p_target_position;
  219. }
  220. void NavAgent::set_velocity(const Vector3 p_velocity) {
  221. // Sets the "wanted" velocity for an agent as a suggestion
  222. // This velocity is not guaranteed, RVO simulation will only try to fulfill it
  223. velocity = p_velocity;
  224. if (avoidance_enabled) {
  225. if (use_3d_avoidance) {
  226. rvo_agent_3d.prefVelocity_ = RVO3D::Vector3(velocity.x, velocity.y, velocity.z);
  227. } else {
  228. rvo_agent_2d.prefVelocity_ = RVO2D::Vector2(velocity.x, velocity.z);
  229. }
  230. }
  231. agent_dirty = true;
  232. request_sync();
  233. }
  234. void NavAgent::set_velocity_forced(const Vector3 p_velocity) {
  235. // This function replaces the internal rvo simulation velocity
  236. // should only be used after the agent was teleported
  237. // as it destroys consistency in movement in cramped situations
  238. // use velocity instead to update with a safer "suggestion"
  239. velocity_forced = p_velocity;
  240. if (avoidance_enabled) {
  241. if (use_3d_avoidance) {
  242. rvo_agent_3d.velocity_ = RVO3D::Vector3(p_velocity.x, p_velocity.y, p_velocity.z);
  243. } else {
  244. rvo_agent_2d.velocity_ = RVO2D::Vector2(p_velocity.x, p_velocity.z);
  245. }
  246. }
  247. agent_dirty = true;
  248. request_sync();
  249. }
  250. void NavAgent::update() {
  251. // Updates this agent with the calculated results from the rvo simulation
  252. if (avoidance_enabled) {
  253. if (use_3d_avoidance) {
  254. velocity = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  255. } else {
  256. velocity = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  257. }
  258. }
  259. }
  260. void NavAgent::set_avoidance_mask(uint32_t p_mask) {
  261. avoidance_mask = p_mask;
  262. if (use_3d_avoidance) {
  263. rvo_agent_3d.avoidance_mask_ = avoidance_mask;
  264. } else {
  265. rvo_agent_2d.avoidance_mask_ = avoidance_mask;
  266. }
  267. agent_dirty = true;
  268. request_sync();
  269. }
  270. void NavAgent::set_avoidance_layers(uint32_t p_layers) {
  271. avoidance_layers = p_layers;
  272. if (use_3d_avoidance) {
  273. rvo_agent_3d.avoidance_layers_ = avoidance_layers;
  274. } else {
  275. rvo_agent_2d.avoidance_layers_ = avoidance_layers;
  276. }
  277. agent_dirty = true;
  278. request_sync();
  279. }
  280. void NavAgent::set_avoidance_priority(real_t p_priority) {
  281. ERR_FAIL_COND_MSG(p_priority < 0.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
  282. ERR_FAIL_COND_MSG(p_priority > 1.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
  283. avoidance_priority = p_priority;
  284. if (use_3d_avoidance) {
  285. rvo_agent_3d.avoidance_priority_ = avoidance_priority;
  286. } else {
  287. rvo_agent_2d.avoidance_priority_ = avoidance_priority;
  288. }
  289. agent_dirty = true;
  290. request_sync();
  291. }
  292. bool NavAgent::is_dirty() const {
  293. return agent_dirty;
  294. }
  295. void NavAgent::sync() {
  296. agent_dirty = false;
  297. }
  298. const Dictionary NavAgent::get_avoidance_data() const {
  299. // Returns debug data from RVO simulation internals of this agent.
  300. Dictionary _avoidance_data;
  301. if (use_3d_avoidance) {
  302. _avoidance_data["max_neighbors"] = int(rvo_agent_3d.maxNeighbors_);
  303. _avoidance_data["max_speed"] = float(rvo_agent_3d.maxSpeed_);
  304. _avoidance_data["neighbor_distance"] = float(rvo_agent_3d.neighborDist_);
  305. _avoidance_data["new_velocity"] = Vector3(rvo_agent_3d.newVelocity_.x(), rvo_agent_3d.newVelocity_.y(), rvo_agent_3d.newVelocity_.z());
  306. _avoidance_data["velocity"] = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  307. _avoidance_data["position"] = Vector3(rvo_agent_3d.position_.x(), rvo_agent_3d.position_.y(), rvo_agent_3d.position_.z());
  308. _avoidance_data["preferred_velocity"] = Vector3(rvo_agent_3d.prefVelocity_.x(), rvo_agent_3d.prefVelocity_.y(), rvo_agent_3d.prefVelocity_.z());
  309. _avoidance_data["radius"] = float(rvo_agent_3d.radius_);
  310. _avoidance_data["time_horizon_agents"] = float(rvo_agent_3d.timeHorizon_);
  311. _avoidance_data["time_horizon_obstacles"] = 0.0;
  312. _avoidance_data["height"] = float(rvo_agent_3d.height_);
  313. _avoidance_data["avoidance_layers"] = int(rvo_agent_3d.avoidance_layers_);
  314. _avoidance_data["avoidance_mask"] = int(rvo_agent_3d.avoidance_mask_);
  315. _avoidance_data["avoidance_priority"] = float(rvo_agent_3d.avoidance_priority_);
  316. } else {
  317. _avoidance_data["max_neighbors"] = int(rvo_agent_2d.maxNeighbors_);
  318. _avoidance_data["max_speed"] = float(rvo_agent_2d.maxSpeed_);
  319. _avoidance_data["neighbor_distance"] = float(rvo_agent_2d.neighborDist_);
  320. _avoidance_data["new_velocity"] = Vector3(rvo_agent_2d.newVelocity_.x(), 0.0, rvo_agent_2d.newVelocity_.y());
  321. _avoidance_data["velocity"] = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  322. _avoidance_data["position"] = Vector3(rvo_agent_2d.position_.x(), 0.0, rvo_agent_2d.position_.y());
  323. _avoidance_data["preferred_velocity"] = Vector3(rvo_agent_2d.prefVelocity_.x(), 0.0, rvo_agent_2d.prefVelocity_.y());
  324. _avoidance_data["radius"] = float(rvo_agent_2d.radius_);
  325. _avoidance_data["time_horizon_agents"] = float(rvo_agent_2d.timeHorizon_);
  326. _avoidance_data["time_horizon_obstacles"] = float(rvo_agent_2d.timeHorizonObst_);
  327. _avoidance_data["height"] = float(rvo_agent_2d.height_);
  328. _avoidance_data["avoidance_layers"] = int(rvo_agent_2d.avoidance_layers_);
  329. _avoidance_data["avoidance_mask"] = int(rvo_agent_2d.avoidance_mask_);
  330. _avoidance_data["avoidance_priority"] = float(rvo_agent_2d.avoidance_priority_);
  331. }
  332. return _avoidance_data;
  333. }
  334. void NavAgent::set_paused(bool p_paused) {
  335. if (paused == p_paused) {
  336. return;
  337. }
  338. paused = p_paused;
  339. if (map) {
  340. if (paused) {
  341. map->remove_agent_as_controlled(this);
  342. } else {
  343. map->set_agent_as_controlled(this);
  344. }
  345. }
  346. }
  347. bool NavAgent::get_paused() const {
  348. return paused;
  349. }
  350. void NavAgent::request_sync() {
  351. if (map && !sync_dirty_request_list_element.in_list()) {
  352. map->add_agent_sync_dirty_request(&sync_dirty_request_list_element);
  353. }
  354. }
  355. void NavAgent::cancel_sync_request() {
  356. if (map && sync_dirty_request_list_element.in_list()) {
  357. map->remove_agent_sync_dirty_request(&sync_dirty_request_list_element);
  358. }
  359. }
  360. NavAgent::NavAgent() :
  361. sync_dirty_request_list_element(this) {
  362. }
  363. NavAgent::~NavAgent() {
  364. cancel_sync_request();
  365. }