nav_agent.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  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. NavAgent::NavAgent() {
  33. }
  34. void NavAgent::set_avoidance_enabled(bool p_enabled) {
  35. avoidance_enabled = p_enabled;
  36. _update_rvo_agent_properties();
  37. }
  38. void NavAgent::set_use_3d_avoidance(bool p_enabled) {
  39. use_3d_avoidance = p_enabled;
  40. _update_rvo_agent_properties();
  41. }
  42. void NavAgent::_update_rvo_agent_properties() {
  43. if (use_3d_avoidance) {
  44. rvo_agent_3d.neighborDist_ = neighbor_distance;
  45. rvo_agent_3d.maxNeighbors_ = max_neighbors;
  46. rvo_agent_3d.timeHorizon_ = time_horizon_agents;
  47. rvo_agent_3d.timeHorizonObst_ = time_horizon_obstacles;
  48. rvo_agent_3d.radius_ = radius;
  49. rvo_agent_3d.maxSpeed_ = max_speed;
  50. rvo_agent_3d.position_ = RVO3D::Vector3(position.x, position.y, position.z);
  51. // Replacing the internal velocity directly causes major jitter / bugs due to unpredictable velocity jumps, left line here for testing.
  52. //rvo_agent_3d.velocity_ = RVO3D::Vector3(velocity.x, velocity.y ,velocity.z);
  53. rvo_agent_3d.prefVelocity_ = RVO3D::Vector3(velocity.x, velocity.y, velocity.z);
  54. rvo_agent_3d.height_ = height;
  55. rvo_agent_3d.avoidance_layers_ = avoidance_layers;
  56. rvo_agent_3d.avoidance_mask_ = avoidance_mask;
  57. rvo_agent_3d.avoidance_priority_ = avoidance_priority;
  58. } else {
  59. rvo_agent_2d.neighborDist_ = neighbor_distance;
  60. rvo_agent_2d.maxNeighbors_ = max_neighbors;
  61. rvo_agent_2d.timeHorizon_ = time_horizon_agents;
  62. rvo_agent_2d.timeHorizonObst_ = time_horizon_obstacles;
  63. rvo_agent_2d.radius_ = radius;
  64. rvo_agent_2d.maxSpeed_ = max_speed;
  65. rvo_agent_2d.position_ = RVO2D::Vector2(position.x, position.z);
  66. rvo_agent_2d.elevation_ = position.y;
  67. // Replacing the internal velocity directly causes major jitter / bugs due to unpredictable velocity jumps, left line here for testing.
  68. //rvo_agent_2d.velocity_ = RVO2D::Vector2(velocity.x, velocity.z);
  69. rvo_agent_2d.prefVelocity_ = RVO2D::Vector2(velocity.x, velocity.z);
  70. rvo_agent_2d.height_ = height;
  71. rvo_agent_2d.avoidance_layers_ = avoidance_layers;
  72. rvo_agent_2d.avoidance_mask_ = avoidance_mask;
  73. rvo_agent_2d.avoidance_priority_ = avoidance_priority;
  74. }
  75. if (map != nullptr) {
  76. if (avoidance_enabled) {
  77. map->set_agent_as_controlled(this);
  78. } else {
  79. map->remove_agent_as_controlled(this);
  80. }
  81. }
  82. agent_dirty = true;
  83. }
  84. void NavAgent::set_map(NavMap *p_map) {
  85. if (map == p_map) {
  86. return;
  87. }
  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. }
  99. }
  100. bool NavAgent::is_map_changed() {
  101. if (map) {
  102. bool is_changed = map->get_iteration_id() != last_map_iteration_id;
  103. last_map_iteration_id = map->get_iteration_id();
  104. return is_changed;
  105. } else {
  106. return false;
  107. }
  108. }
  109. void NavAgent::set_avoidance_callback(Callable p_callback) {
  110. avoidance_callback = p_callback;
  111. }
  112. bool NavAgent::has_avoidance_callback() const {
  113. return avoidance_callback.is_valid();
  114. }
  115. void NavAgent::dispatch_avoidance_callback() {
  116. if (!avoidance_callback.is_valid()) {
  117. return;
  118. }
  119. Vector3 new_velocity;
  120. if (use_3d_avoidance) {
  121. new_velocity = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  122. } else {
  123. new_velocity = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  124. }
  125. if (clamp_speed) {
  126. new_velocity = new_velocity.limit_length(max_speed);
  127. }
  128. // Invoke the callback with the new velocity.
  129. avoidance_callback.call(new_velocity);
  130. }
  131. void NavAgent::set_neighbor_distance(real_t p_neighbor_distance) {
  132. neighbor_distance = p_neighbor_distance;
  133. if (use_3d_avoidance) {
  134. rvo_agent_3d.neighborDist_ = neighbor_distance;
  135. } else {
  136. rvo_agent_2d.neighborDist_ = neighbor_distance;
  137. }
  138. agent_dirty = true;
  139. }
  140. void NavAgent::set_max_neighbors(int p_max_neighbors) {
  141. max_neighbors = p_max_neighbors;
  142. if (use_3d_avoidance) {
  143. rvo_agent_3d.maxNeighbors_ = max_neighbors;
  144. } else {
  145. rvo_agent_2d.maxNeighbors_ = max_neighbors;
  146. }
  147. agent_dirty = true;
  148. }
  149. void NavAgent::set_time_horizon_agents(real_t p_time_horizon) {
  150. time_horizon_agents = p_time_horizon;
  151. if (use_3d_avoidance) {
  152. rvo_agent_3d.timeHorizon_ = time_horizon_agents;
  153. } else {
  154. rvo_agent_2d.timeHorizon_ = time_horizon_agents;
  155. }
  156. agent_dirty = true;
  157. }
  158. void NavAgent::set_time_horizon_obstacles(real_t p_time_horizon) {
  159. time_horizon_obstacles = p_time_horizon;
  160. if (use_3d_avoidance) {
  161. rvo_agent_3d.timeHorizonObst_ = time_horizon_obstacles;
  162. } else {
  163. rvo_agent_2d.timeHorizonObst_ = time_horizon_obstacles;
  164. }
  165. agent_dirty = true;
  166. }
  167. void NavAgent::set_radius(real_t p_radius) {
  168. radius = p_radius;
  169. if (use_3d_avoidance) {
  170. rvo_agent_3d.radius_ = radius;
  171. } else {
  172. rvo_agent_2d.radius_ = radius;
  173. }
  174. agent_dirty = true;
  175. }
  176. void NavAgent::set_height(real_t p_height) {
  177. height = p_height;
  178. if (use_3d_avoidance) {
  179. rvo_agent_3d.height_ = height;
  180. } else {
  181. rvo_agent_2d.height_ = height;
  182. }
  183. agent_dirty = true;
  184. }
  185. void NavAgent::set_max_speed(real_t p_max_speed) {
  186. max_speed = p_max_speed;
  187. if (avoidance_enabled) {
  188. if (use_3d_avoidance) {
  189. rvo_agent_3d.maxSpeed_ = max_speed;
  190. } else {
  191. rvo_agent_2d.maxSpeed_ = max_speed;
  192. }
  193. }
  194. agent_dirty = true;
  195. }
  196. void NavAgent::set_position(const Vector3 p_position) {
  197. position = p_position;
  198. if (avoidance_enabled) {
  199. if (use_3d_avoidance) {
  200. rvo_agent_3d.position_ = RVO3D::Vector3(p_position.x, p_position.y, p_position.z);
  201. } else {
  202. rvo_agent_2d.elevation_ = p_position.y;
  203. rvo_agent_2d.position_ = RVO2D::Vector2(p_position.x, p_position.z);
  204. }
  205. }
  206. agent_dirty = true;
  207. }
  208. void NavAgent::set_target_position(const Vector3 p_target_position) {
  209. target_position = p_target_position;
  210. }
  211. void NavAgent::set_velocity(const Vector3 p_velocity) {
  212. // Sets the "wanted" velocity for an agent as a suggestion
  213. // This velocity is not guaranteed, RVO simulation will only try to fulfill it
  214. velocity = p_velocity;
  215. if (avoidance_enabled) {
  216. if (use_3d_avoidance) {
  217. rvo_agent_3d.prefVelocity_ = RVO3D::Vector3(velocity.x, velocity.y, velocity.z);
  218. } else {
  219. rvo_agent_2d.prefVelocity_ = RVO2D::Vector2(velocity.x, velocity.z);
  220. }
  221. }
  222. agent_dirty = true;
  223. }
  224. void NavAgent::set_velocity_forced(const Vector3 p_velocity) {
  225. // This function replaces the internal rvo simulation velocity
  226. // should only be used after the agent was teleported
  227. // as it destroys consistency in movement in cramped situations
  228. // use velocity instead to update with a safer "suggestion"
  229. velocity_forced = p_velocity;
  230. if (avoidance_enabled) {
  231. if (use_3d_avoidance) {
  232. rvo_agent_3d.velocity_ = RVO3D::Vector3(p_velocity.x, p_velocity.y, p_velocity.z);
  233. } else {
  234. rvo_agent_2d.velocity_ = RVO2D::Vector2(p_velocity.x, p_velocity.z);
  235. }
  236. }
  237. agent_dirty = true;
  238. }
  239. void NavAgent::update() {
  240. // Updates this agent with the calculated results from the rvo simulation
  241. if (avoidance_enabled) {
  242. if (use_3d_avoidance) {
  243. velocity = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  244. } else {
  245. velocity = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  246. }
  247. }
  248. }
  249. void NavAgent::set_avoidance_mask(uint32_t p_mask) {
  250. avoidance_mask = p_mask;
  251. if (use_3d_avoidance) {
  252. rvo_agent_3d.avoidance_mask_ = avoidance_mask;
  253. } else {
  254. rvo_agent_2d.avoidance_mask_ = avoidance_mask;
  255. }
  256. agent_dirty = true;
  257. }
  258. void NavAgent::set_avoidance_layers(uint32_t p_layers) {
  259. avoidance_layers = p_layers;
  260. if (use_3d_avoidance) {
  261. rvo_agent_3d.avoidance_layers_ = avoidance_layers;
  262. } else {
  263. rvo_agent_2d.avoidance_layers_ = avoidance_layers;
  264. }
  265. agent_dirty = true;
  266. }
  267. void NavAgent::set_avoidance_priority(real_t p_priority) {
  268. ERR_FAIL_COND_MSG(p_priority < 0.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
  269. ERR_FAIL_COND_MSG(p_priority > 1.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
  270. avoidance_priority = p_priority;
  271. if (use_3d_avoidance) {
  272. rvo_agent_3d.avoidance_priority_ = avoidance_priority;
  273. } else {
  274. rvo_agent_2d.avoidance_priority_ = avoidance_priority;
  275. }
  276. agent_dirty = true;
  277. }
  278. bool NavAgent::check_dirty() {
  279. const bool was_dirty = agent_dirty;
  280. agent_dirty = false;
  281. return was_dirty;
  282. }
  283. const Dictionary NavAgent::get_avoidance_data() const {
  284. // Returns debug data from RVO simulation internals of this agent.
  285. Dictionary _avoidance_data;
  286. if (use_3d_avoidance) {
  287. _avoidance_data["max_neighbors"] = int(rvo_agent_3d.maxNeighbors_);
  288. _avoidance_data["max_speed"] = float(rvo_agent_3d.maxSpeed_);
  289. _avoidance_data["neighbor_distance"] = float(rvo_agent_3d.neighborDist_);
  290. _avoidance_data["new_velocity"] = Vector3(rvo_agent_3d.newVelocity_.x(), rvo_agent_3d.newVelocity_.y(), rvo_agent_3d.newVelocity_.z());
  291. _avoidance_data["velocity"] = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  292. _avoidance_data["position"] = Vector3(rvo_agent_3d.position_.x(), rvo_agent_3d.position_.y(), rvo_agent_3d.position_.z());
  293. _avoidance_data["preferred_velocity"] = Vector3(rvo_agent_3d.prefVelocity_.x(), rvo_agent_3d.prefVelocity_.y(), rvo_agent_3d.prefVelocity_.z());
  294. _avoidance_data["radius"] = float(rvo_agent_3d.radius_);
  295. _avoidance_data["time_horizon_agents"] = float(rvo_agent_3d.timeHorizon_);
  296. _avoidance_data["time_horizon_obstacles"] = 0.0;
  297. _avoidance_data["height"] = float(rvo_agent_3d.height_);
  298. _avoidance_data["avoidance_layers"] = int(rvo_agent_3d.avoidance_layers_);
  299. _avoidance_data["avoidance_mask"] = int(rvo_agent_3d.avoidance_mask_);
  300. _avoidance_data["avoidance_priority"] = float(rvo_agent_3d.avoidance_priority_);
  301. } else {
  302. _avoidance_data["max_neighbors"] = int(rvo_agent_2d.maxNeighbors_);
  303. _avoidance_data["max_speed"] = float(rvo_agent_2d.maxSpeed_);
  304. _avoidance_data["neighbor_distance"] = float(rvo_agent_2d.neighborDist_);
  305. _avoidance_data["new_velocity"] = Vector3(rvo_agent_2d.newVelocity_.x(), 0.0, rvo_agent_2d.newVelocity_.y());
  306. _avoidance_data["velocity"] = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  307. _avoidance_data["position"] = Vector3(rvo_agent_2d.position_.x(), 0.0, rvo_agent_2d.position_.y());
  308. _avoidance_data["preferred_velocity"] = Vector3(rvo_agent_2d.prefVelocity_.x(), 0.0, rvo_agent_2d.prefVelocity_.y());
  309. _avoidance_data["radius"] = float(rvo_agent_2d.radius_);
  310. _avoidance_data["time_horizon_agents"] = float(rvo_agent_2d.timeHorizon_);
  311. _avoidance_data["time_horizon_obstacles"] = float(rvo_agent_2d.timeHorizonObst_);
  312. _avoidance_data["height"] = float(rvo_agent_2d.height_);
  313. _avoidance_data["avoidance_layers"] = int(rvo_agent_2d.avoidance_layers_);
  314. _avoidance_data["avoidance_mask"] = int(rvo_agent_2d.avoidance_mask_);
  315. _avoidance_data["avoidance_priority"] = float(rvo_agent_2d.avoidance_priority_);
  316. }
  317. return _avoidance_data;
  318. }
  319. void NavAgent::set_paused(bool p_paused) {
  320. if (paused == p_paused) {
  321. return;
  322. }
  323. paused = p_paused;
  324. if (map) {
  325. if (paused) {
  326. map->remove_agent_as_controlled(this);
  327. } else {
  328. map->set_agent_as_controlled(this);
  329. }
  330. }
  331. }
  332. bool NavAgent::get_paused() const {
  333. return paused;
  334. }