nav_agent.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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_map_update_id() != map_update_id;
  103. map_update_id = map->get_map_update_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. Variant args[] = { new_velocity };
  130. const Variant *args_p[] = { &args[0] };
  131. Variant return_value;
  132. Callable::CallError call_error;
  133. avoidance_callback.callp(args_p, 1, return_value, call_error);
  134. }
  135. void NavAgent::set_neighbor_distance(real_t p_neighbor_distance) {
  136. neighbor_distance = p_neighbor_distance;
  137. if (use_3d_avoidance) {
  138. rvo_agent_3d.neighborDist_ = neighbor_distance;
  139. } else {
  140. rvo_agent_2d.neighborDist_ = neighbor_distance;
  141. }
  142. agent_dirty = true;
  143. }
  144. void NavAgent::set_max_neighbors(int p_max_neighbors) {
  145. max_neighbors = p_max_neighbors;
  146. if (use_3d_avoidance) {
  147. rvo_agent_3d.maxNeighbors_ = max_neighbors;
  148. } else {
  149. rvo_agent_2d.maxNeighbors_ = max_neighbors;
  150. }
  151. agent_dirty = true;
  152. }
  153. void NavAgent::set_time_horizon_agents(real_t p_time_horizon) {
  154. time_horizon_agents = p_time_horizon;
  155. if (use_3d_avoidance) {
  156. rvo_agent_3d.timeHorizon_ = time_horizon_agents;
  157. } else {
  158. rvo_agent_2d.timeHorizon_ = time_horizon_agents;
  159. }
  160. agent_dirty = true;
  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. }
  171. void NavAgent::set_radius(real_t p_radius) {
  172. radius = p_radius;
  173. if (use_3d_avoidance) {
  174. rvo_agent_3d.radius_ = radius;
  175. } else {
  176. rvo_agent_2d.radius_ = radius;
  177. }
  178. agent_dirty = true;
  179. }
  180. void NavAgent::set_height(real_t p_height) {
  181. height = p_height;
  182. if (use_3d_avoidance) {
  183. rvo_agent_3d.height_ = height;
  184. } else {
  185. rvo_agent_2d.height_ = height;
  186. }
  187. agent_dirty = true;
  188. }
  189. void NavAgent::set_max_speed(real_t p_max_speed) {
  190. max_speed = p_max_speed;
  191. if (avoidance_enabled) {
  192. if (use_3d_avoidance) {
  193. rvo_agent_3d.maxSpeed_ = max_speed;
  194. } else {
  195. rvo_agent_2d.maxSpeed_ = max_speed;
  196. }
  197. }
  198. agent_dirty = true;
  199. }
  200. void NavAgent::set_position(const Vector3 p_position) {
  201. position = p_position;
  202. if (avoidance_enabled) {
  203. if (use_3d_avoidance) {
  204. rvo_agent_3d.position_ = RVO3D::Vector3(p_position.x, p_position.y, p_position.z);
  205. } else {
  206. rvo_agent_2d.elevation_ = p_position.y;
  207. rvo_agent_2d.position_ = RVO2D::Vector2(p_position.x, p_position.z);
  208. }
  209. }
  210. agent_dirty = true;
  211. }
  212. void NavAgent::set_target_position(const Vector3 p_target_position) {
  213. target_position = p_target_position;
  214. }
  215. void NavAgent::set_velocity(const Vector3 p_velocity) {
  216. // Sets the "wanted" velocity for an agent as a suggestion
  217. // This velocity is not guaranteed, RVO simulation will only try to fulfill it
  218. velocity = p_velocity;
  219. if (avoidance_enabled) {
  220. if (use_3d_avoidance) {
  221. rvo_agent_3d.prefVelocity_ = RVO3D::Vector3(velocity.x, velocity.y, velocity.z);
  222. } else {
  223. rvo_agent_2d.prefVelocity_ = RVO2D::Vector2(velocity.x, velocity.z);
  224. }
  225. }
  226. agent_dirty = true;
  227. }
  228. void NavAgent::set_velocity_forced(const Vector3 p_velocity) {
  229. // This function replaces the internal rvo simulation velocity
  230. // should only be used after the agent was teleported
  231. // as it destroys consistency in movement in cramped situations
  232. // use velocity instead to update with a safer "suggestion"
  233. velocity_forced = p_velocity;
  234. if (avoidance_enabled) {
  235. if (use_3d_avoidance) {
  236. rvo_agent_3d.velocity_ = RVO3D::Vector3(p_velocity.x, p_velocity.y, p_velocity.z);
  237. } else {
  238. rvo_agent_2d.velocity_ = RVO2D::Vector2(p_velocity.x, p_velocity.z);
  239. }
  240. }
  241. agent_dirty = true;
  242. }
  243. void NavAgent::update() {
  244. // Updates this agent with the calculated results from the rvo simulation
  245. if (avoidance_enabled) {
  246. if (use_3d_avoidance) {
  247. velocity = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  248. } else {
  249. velocity = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  250. }
  251. }
  252. }
  253. void NavAgent::set_avoidance_mask(uint32_t p_mask) {
  254. avoidance_mask = p_mask;
  255. if (use_3d_avoidance) {
  256. rvo_agent_3d.avoidance_mask_ = avoidance_mask;
  257. } else {
  258. rvo_agent_2d.avoidance_mask_ = avoidance_mask;
  259. }
  260. agent_dirty = true;
  261. }
  262. void NavAgent::set_avoidance_layers(uint32_t p_layers) {
  263. avoidance_layers = p_layers;
  264. if (use_3d_avoidance) {
  265. rvo_agent_3d.avoidance_layers_ = avoidance_layers;
  266. } else {
  267. rvo_agent_2d.avoidance_layers_ = avoidance_layers;
  268. }
  269. agent_dirty = true;
  270. }
  271. void NavAgent::set_avoidance_priority(real_t p_priority) {
  272. ERR_FAIL_COND_MSG(p_priority < 0.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
  273. ERR_FAIL_COND_MSG(p_priority > 1.0, "Avoidance priority must be between 0.0 and 1.0 inclusive.");
  274. avoidance_priority = p_priority;
  275. if (use_3d_avoidance) {
  276. rvo_agent_3d.avoidance_priority_ = avoidance_priority;
  277. } else {
  278. rvo_agent_2d.avoidance_priority_ = avoidance_priority;
  279. }
  280. agent_dirty = true;
  281. };
  282. bool NavAgent::check_dirty() {
  283. const bool was_dirty = agent_dirty;
  284. agent_dirty = false;
  285. return was_dirty;
  286. }
  287. const Dictionary NavAgent::get_avoidance_data() const {
  288. // Returns debug data from RVO simulation internals of this agent.
  289. Dictionary _avoidance_data;
  290. if (use_3d_avoidance) {
  291. _avoidance_data["max_neighbors"] = int(rvo_agent_3d.maxNeighbors_);
  292. _avoidance_data["max_speed"] = float(rvo_agent_3d.maxSpeed_);
  293. _avoidance_data["neighbor_distance"] = float(rvo_agent_3d.neighborDist_);
  294. _avoidance_data["new_velocity"] = Vector3(rvo_agent_3d.newVelocity_.x(), rvo_agent_3d.newVelocity_.y(), rvo_agent_3d.newVelocity_.z());
  295. _avoidance_data["velocity"] = Vector3(rvo_agent_3d.velocity_.x(), rvo_agent_3d.velocity_.y(), rvo_agent_3d.velocity_.z());
  296. _avoidance_data["position"] = Vector3(rvo_agent_3d.position_.x(), rvo_agent_3d.position_.y(), rvo_agent_3d.position_.z());
  297. _avoidance_data["prefered_velocity"] = Vector3(rvo_agent_3d.prefVelocity_.x(), rvo_agent_3d.prefVelocity_.y(), rvo_agent_3d.prefVelocity_.z());
  298. _avoidance_data["radius"] = float(rvo_agent_3d.radius_);
  299. _avoidance_data["time_horizon_agents"] = float(rvo_agent_3d.timeHorizon_);
  300. _avoidance_data["time_horizon_obstacles"] = 0.0;
  301. _avoidance_data["height"] = float(rvo_agent_3d.height_);
  302. _avoidance_data["avoidance_layers"] = int(rvo_agent_3d.avoidance_layers_);
  303. _avoidance_data["avoidance_mask"] = int(rvo_agent_3d.avoidance_mask_);
  304. _avoidance_data["avoidance_priority"] = float(rvo_agent_3d.avoidance_priority_);
  305. } else {
  306. _avoidance_data["max_neighbors"] = int(rvo_agent_2d.maxNeighbors_);
  307. _avoidance_data["max_speed"] = float(rvo_agent_2d.maxSpeed_);
  308. _avoidance_data["neighbor_distance"] = float(rvo_agent_2d.neighborDist_);
  309. _avoidance_data["new_velocity"] = Vector3(rvo_agent_2d.newVelocity_.x(), 0.0, rvo_agent_2d.newVelocity_.y());
  310. _avoidance_data["velocity"] = Vector3(rvo_agent_2d.velocity_.x(), 0.0, rvo_agent_2d.velocity_.y());
  311. _avoidance_data["position"] = Vector3(rvo_agent_2d.position_.x(), 0.0, rvo_agent_2d.position_.y());
  312. _avoidance_data["prefered_velocity"] = Vector3(rvo_agent_2d.prefVelocity_.x(), 0.0, rvo_agent_2d.prefVelocity_.y());
  313. _avoidance_data["radius"] = float(rvo_agent_2d.radius_);
  314. _avoidance_data["time_horizon_agents"] = float(rvo_agent_2d.timeHorizon_);
  315. _avoidance_data["time_horizon_obstacles"] = float(rvo_agent_2d.timeHorizonObst_);
  316. _avoidance_data["height"] = float(rvo_agent_2d.height_);
  317. _avoidance_data["avoidance_layers"] = int(rvo_agent_2d.avoidance_layers_);
  318. _avoidance_data["avoidance_mask"] = int(rvo_agent_2d.avoidance_mask_);
  319. _avoidance_data["avoidance_priority"] = float(rvo_agent_2d.avoidance_priority_);
  320. }
  321. return _avoidance_data;
  322. }
  323. void NavAgent::set_paused(bool p_paused) {
  324. if (paused == p_paused) {
  325. return;
  326. }
  327. paused = p_paused;
  328. if (map) {
  329. if (paused) {
  330. map->remove_agent_as_controlled(this);
  331. } else {
  332. map->set_agent_as_controlled(this);
  333. }
  334. }
  335. }
  336. bool NavAgent::get_paused() const {
  337. return paused;
  338. }