summaryrefslogtreecommitdiff
path: root/modules/navigation
diff options
context:
space:
mode:
Diffstat (limited to 'modules/navigation')
-rw-r--r--modules/navigation/SCsub2
-rw-r--r--modules/navigation/editor/navigation_mesh_editor_plugin.cpp62
-rw-r--r--modules/navigation/editor/navigation_mesh_editor_plugin.h60
-rw-r--r--modules/navigation/godot_navigation_server.cpp526
-rw-r--r--modules/navigation/godot_navigation_server.h137
-rw-r--r--modules/navigation/nav_base.h64
-rw-r--r--modules/navigation/nav_link.cpp60
-rw-r--r--modules/navigation/nav_link.h73
-rw-r--r--modules/navigation/nav_map.cpp436
-rw-r--r--modules/navigation/nav_map.h118
-rw-r--r--modules/navigation/nav_region.cpp66
-rw-r--r--modules/navigation/nav_region.h87
-rw-r--r--modules/navigation/nav_rid.h58
-rw-r--r--modules/navigation/nav_utils.h88
-rw-r--r--modules/navigation/navigation_mesh_generator.cpp270
-rw-r--r--modules/navigation/navigation_mesh_generator.h66
-rw-r--r--modules/navigation/register_types.cpp58
-rw-r--r--modules/navigation/register_types.h58
-rw-r--r--modules/navigation/rvo_agent.cpp58
-rw-r--r--modules/navigation/rvo_agent.h58
20 files changed, 1656 insertions, 749 deletions
diff --git a/modules/navigation/SCsub b/modules/navigation/SCsub
index 24a6b12639..0b0822db2d 100644
--- a/modules/navigation/SCsub
+++ b/modules/navigation/SCsub
@@ -57,7 +57,7 @@ env.modules_sources += thirdparty_obj
module_obj = []
env_navigation.add_source_files(module_obj, "*.cpp")
-if env["tools"]:
+if env.editor_build:
env_navigation.add_source_files(module_obj, "editor/*.cpp")
env.modules_sources += module_obj
diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
index c243e3e6e3..54f7abda8d 100644
--- a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
+++ b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* navigation_mesh_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* navigation_mesh_editor_plugin.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "navigation_mesh_editor_plugin.h"
@@ -110,7 +110,7 @@ NavigationMeshEditor::NavigationMeshEditor() {
button_reset->set_flat(true);
bake_hbox->add_child(button_reset);
// No button text, we only use a revert icon which is set when entering the tree.
- button_reset->set_tooltip(TTR("Clear the navigation mesh."));
+ button_reset->set_tooltip_text(TTR("Clear the navigation mesh."));
button_reset->connect("pressed", callable_mp(this, &NavigationMeshEditor::_clear_pressed));
bake_info = memnew(Label);
@@ -145,7 +145,7 @@ void NavigationMeshEditorPlugin::make_visible(bool p_visible) {
NavigationMeshEditorPlugin::NavigationMeshEditorPlugin() {
navigation_mesh_editor = memnew(NavigationMeshEditor);
- EditorNode::get_singleton()->get_main_control()->add_child(navigation_mesh_editor);
+ EditorNode::get_singleton()->get_main_screen_control()->add_child(navigation_mesh_editor);
add_control_to_container(CONTAINER_SPATIAL_EDITOR_MENU, navigation_mesh_editor->bake_hbox);
navigation_mesh_editor->hide();
navigation_mesh_editor->bake_hbox->hide();
diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.h b/modules/navigation/editor/navigation_mesh_editor_plugin.h
index bc9e4185b7..010be411d6 100644
--- a/modules/navigation/editor/navigation_mesh_editor_plugin.h
+++ b/modules/navigation/editor/navigation_mesh_editor_plugin.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* navigation_mesh_editor_plugin.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* navigation_mesh_editor_plugin.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef NAVIGATION_MESH_EDITOR_PLUGIN_H
#define NAVIGATION_MESH_EDITOR_PLUGIN_H
@@ -35,6 +35,8 @@
#include "editor/editor_plugin.h"
+class AcceptDialog;
+class HBoxContainer;
class NavigationRegion3D;
class NavigationMeshEditor : public Control {
diff --git a/modules/navigation/godot_navigation_server.cpp b/modules/navigation/godot_navigation_server.cpp
index bcbc721dbb..9b5d78d465 100644
--- a/modules/navigation/godot_navigation_server.cpp
+++ b/modules/navigation/godot_navigation_server.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* godot_navigation_server.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* godot_navigation_server.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "godot_navigation_server.h"
@@ -36,6 +36,8 @@
#include "navigation_mesh_generator.h"
#endif
+using namespace NavigationUtilities;
+
/// Creates a struct for each function and a function that once called creates
/// an instance of that struct with the submitted parameters.
/// Then, that struct is stored in an array; the `sync` function consume that array.
@@ -50,7 +52,7 @@
server->MERGE(_cmd_, F_NAME)(d_0); \
} \
}; \
- void GodotNavigationServer::F_NAME(T_0 D_0) const { \
+ void GodotNavigationServer::F_NAME(T_0 D_0) { \
auto cmd = memnew(MERGE(F_NAME, _command)( \
D_0)); \
add_command(cmd); \
@@ -71,7 +73,7 @@
server->MERGE(_cmd_, F_NAME)(d_0, d_1); \
} \
}; \
- void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1) const { \
+ void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1) { \
auto cmd = memnew(MERGE(F_NAME, _command)( \
D_0, \
D_1)); \
@@ -79,34 +81,34 @@
} \
void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1)
-#define COMMAND_4(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3) \
- struct MERGE(F_NAME, _command) : public SetCommand { \
- T_0 d_0; \
- T_1 d_1; \
- T_2 d_2; \
- T_3 d_3; \
- MERGE(F_NAME, _command) \
- ( \
- T_0 p_d_0, \
- T_1 p_d_1, \
- T_2 p_d_2, \
- T_3 p_d_3) : \
- d_0(p_d_0), \
- d_1(p_d_1), \
- d_2(p_d_2), \
- d_3(p_d_3) {} \
- virtual void exec(GodotNavigationServer *server) override { \
- server->MERGE(_cmd_, F_NAME)(d_0, d_1, d_2, d_3); \
- } \
- }; \
- void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) const { \
- auto cmd = memnew(MERGE(F_NAME, _command)( \
- D_0, \
- D_1, \
- D_2, \
- D_3)); \
- add_command(cmd); \
- } \
+#define COMMAND_4(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3) \
+ struct MERGE(F_NAME, _command) : public SetCommand { \
+ T_0 d_0; \
+ T_1 d_1; \
+ T_2 d_2; \
+ T_3 d_3; \
+ MERGE(F_NAME, _command) \
+ ( \
+ T_0 p_d_0, \
+ T_1 p_d_1, \
+ T_2 p_d_2, \
+ T_3 p_d_3) : \
+ d_0(p_d_0), \
+ d_1(p_d_1), \
+ d_2(p_d_2), \
+ d_3(p_d_3) {} \
+ virtual void exec(GodotNavigationServer *server) override { \
+ server->MERGE(_cmd_, F_NAME)(d_0, d_1, d_2, d_3); \
+ } \
+ }; \
+ void GodotNavigationServer::F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) { \
+ auto cmd = memnew(MERGE(F_NAME, _command)( \
+ D_0, \
+ D_1, \
+ D_2, \
+ D_3)); \
+ add_command(cmd); \
+ } \
void GodotNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
GodotNavigationServer::GodotNavigationServer() {}
@@ -115,16 +117,14 @@ GodotNavigationServer::~GodotNavigationServer() {
flush_queries();
}
-void GodotNavigationServer::add_command(SetCommand *command) const {
- GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
- {
- MutexLock lock(commands_mutex);
- mut_this->commands.push_back(command);
- }
+void GodotNavigationServer::add_command(SetCommand *command) {
+ MutexLock lock(commands_mutex);
+
+ commands.push_back(command);
}
-Array GodotNavigationServer::get_maps() const {
- Array all_map_rids;
+TypedArray<RID> GodotNavigationServer::get_maps() const {
+ TypedArray<RID> all_map_rids;
List<RID> maps_owned;
map_owner.get_owned_list(&maps_owned);
if (maps_owned.size()) {
@@ -135,12 +135,12 @@ Array GodotNavigationServer::get_maps() const {
return all_map_rids;
}
-RID GodotNavigationServer::map_create() const {
- GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
- MutexLock lock(mut_this->operations_mutex);
+RID GodotNavigationServer::map_create() {
+ MutexLock lock(operations_mutex);
+
RID rid = map_owner.make_rid();
- NavMap *space = map_owner.get_or_null(rid);
- space->set_self(rid);
+ NavMap *map = map_owner.get_or_null(rid);
+ map->set_self(rid);
return rid;
}
@@ -210,11 +210,25 @@ real_t GodotNavigationServer::map_get_edge_connection_margin(RID p_map) const {
return map->get_edge_connection_margin();
}
+COMMAND_2(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius) {
+ NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND(map == nullptr);
+
+ map->set_link_connection_radius(p_connection_radius);
+}
+
+real_t GodotNavigationServer::map_get_link_connection_radius(RID p_map) const {
+ const NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND_V(map == nullptr, 0);
+
+ return map->get_link_connection_radius();
+}
+
Vector<Vector3> GodotNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, Vector<Vector3>());
- return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers);
+ return map->get_path(p_origin, p_destination, p_optimize, p_navigation_layers, nullptr, nullptr, nullptr);
}
Vector3 GodotNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
@@ -245,22 +259,44 @@ RID GodotNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3
return map->get_closest_point_owner(p_point);
}
-Array GodotNavigationServer::map_get_regions(RID p_map) const {
- Array regions_rids;
+TypedArray<RID> GodotNavigationServer::map_get_links(RID p_map) const {
+ TypedArray<RID> link_rids;
+ const NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND_V(map == nullptr, link_rids);
+
+ const LocalVector<NavLink *> links = map->get_links();
+ link_rids.resize(links.size());
+
+ for (uint32_t i = 0; i < links.size(); i++) {
+ link_rids[i] = links[i]->get_self();
+ }
+ return link_rids;
+}
+
+TypedArray<RID> GodotNavigationServer::map_get_regions(RID p_map) const {
+ TypedArray<RID> regions_rids;
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, regions_rids);
- for (NavRegion *region : map->get_regions()) {
- regions_rids.push_back(region->get_self());
+
+ const LocalVector<NavRegion *> regions = map->get_regions();
+ regions_rids.resize(regions.size());
+
+ for (uint32_t i = 0; i < regions.size(); i++) {
+ regions_rids[i] = regions[i]->get_self();
}
return regions_rids;
}
-Array GodotNavigationServer::map_get_agents(RID p_map) const {
- Array agents_rids;
+TypedArray<RID> GodotNavigationServer::map_get_agents(RID p_map) const {
+ TypedArray<RID> agents_rids;
const NavMap *map = map_owner.get_or_null(p_map);
ERR_FAIL_COND_V(map == nullptr, agents_rids);
- for (RvoAgent *agent : map->get_agents()) {
- agents_rids.push_back(agent->get_self());
+
+ const LocalVector<RvoAgent *> agents = map->get_agents();
+ agents_rids.resize(agents.size());
+
+ for (uint32_t i = 0; i < agents.size(); i++) {
+ agents_rids[i] = agents[i]->get_self();
}
return agents_rids;
}
@@ -268,6 +304,7 @@ Array GodotNavigationServer::map_get_agents(RID p_map) const {
RID GodotNavigationServer::region_get_map(RID p_region) const {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND_V(region == nullptr, RID());
+
if (region->get_map()) {
return region->get_map()->get_self();
}
@@ -277,15 +314,16 @@ RID GodotNavigationServer::region_get_map(RID p_region) const {
RID GodotNavigationServer::agent_get_map(RID p_agent) const {
RvoAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND_V(agent == nullptr, RID());
+
if (agent->get_map()) {
return agent->get_map()->get_self();
}
return RID();
}
-RID GodotNavigationServer::region_create() const {
- GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
- MutexLock lock(mut_this->operations_mutex);
+RID GodotNavigationServer::region_create() {
+ MutexLock lock(operations_mutex);
+
RID rid = region_owner.make_rid();
NavRegion *reg = region_owner.get_or_null(rid);
reg->set_self(rid);
@@ -351,9 +389,24 @@ real_t GodotNavigationServer::region_get_travel_cost(RID p_region) const {
return region->get_travel_cost();
}
+COMMAND_2(region_set_owner_id, RID, p_region, ObjectID, p_owner_id) {
+ NavRegion *region = region_owner.get_or_null(p_region);
+ ERR_FAIL_COND(region == nullptr);
+
+ region->set_owner_id(p_owner_id);
+}
+
+ObjectID GodotNavigationServer::region_get_owner_id(RID p_region) const {
+ const NavRegion *region = region_owner.get_or_null(p_region);
+ ERR_FAIL_COND_V(region == nullptr, ObjectID());
+
+ return region->get_owner_id();
+}
+
bool GodotNavigationServer::region_owns_point(RID p_region, const Vector3 &p_point) const {
const NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND_V(region == nullptr, false);
+
if (region->get_map()) {
RID closest_point_owner = map_get_closest_point_owner(region->get_map()->get_self(), p_point);
return closest_point_owner == region->get_self();
@@ -375,20 +428,20 @@ uint32_t GodotNavigationServer::region_get_navigation_layers(RID p_region) const
return region->get_navigation_layers();
}
-COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh) {
+COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navigation_mesh) {
NavRegion *region = region_owner.get_or_null(p_region);
ERR_FAIL_COND(region == nullptr);
- region->set_mesh(p_nav_mesh);
+ region->set_mesh(p_navigation_mesh);
}
-void GodotNavigationServer::region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const {
- ERR_FAIL_COND(r_mesh.is_null());
- ERR_FAIL_COND(p_node == nullptr);
+void GodotNavigationServer::region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) {
+ ERR_FAIL_COND(p_navigation_mesh.is_null());
+ ERR_FAIL_COND(p_root_node == nullptr);
#ifndef _3D_DISABLED
- NavigationMeshGenerator::get_singleton()->clear(r_mesh);
- NavigationMeshGenerator::get_singleton()->bake(r_mesh, p_node);
+ NavigationMeshGenerator::get_singleton()->clear(p_navigation_mesh);
+ NavigationMeshGenerator::get_singleton()->bake(p_navigation_mesh, p_root_node);
#endif
}
@@ -413,9 +466,148 @@ Vector3 GodotNavigationServer::region_get_connection_pathway_end(RID p_region, i
return region->get_connection_pathway_end(p_connection_id);
}
-RID GodotNavigationServer::agent_create() const {
- GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
- MutexLock lock(mut_this->operations_mutex);
+RID GodotNavigationServer::link_create() {
+ MutexLock lock(operations_mutex);
+
+ RID rid = link_owner.make_rid();
+ NavLink *link = link_owner.get_or_null(rid);
+ link->set_self(rid);
+ return rid;
+}
+
+COMMAND_2(link_set_map, RID, p_link, RID, p_map) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ if (link->get_map() != nullptr) {
+ if (link->get_map()->get_self() == p_map) {
+ return; // Pointless
+ }
+
+ link->get_map()->remove_link(link);
+ link->set_map(nullptr);
+ }
+
+ if (p_map.is_valid()) {
+ NavMap *map = map_owner.get_or_null(p_map);
+ ERR_FAIL_COND(map == nullptr);
+
+ map->add_link(link);
+ link->set_map(map);
+ }
+}
+
+RID GodotNavigationServer::link_get_map(const RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, RID());
+
+ if (link->get_map()) {
+ return link->get_map()->get_self();
+ }
+ return RID();
+}
+
+COMMAND_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_bidirectional(p_bidirectional);
+}
+
+bool GodotNavigationServer::link_is_bidirectional(RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, false);
+
+ return link->is_bidirectional();
+}
+
+COMMAND_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_navigation_layers(p_navigation_layers);
+}
+
+uint32_t GodotNavigationServer::link_get_navigation_layers(const RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, 0);
+
+ return link->get_navigation_layers();
+}
+
+COMMAND_2(link_set_start_location, RID, p_link, Vector3, p_location) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_start_location(p_location);
+}
+
+Vector3 GodotNavigationServer::link_get_start_location(RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, Vector3());
+
+ return link->get_start_location();
+}
+
+COMMAND_2(link_set_end_location, RID, p_link, Vector3, p_location) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_end_location(p_location);
+}
+
+Vector3 GodotNavigationServer::link_get_end_location(RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, Vector3());
+
+ return link->get_end_location();
+}
+
+COMMAND_2(link_set_enter_cost, RID, p_link, real_t, p_enter_cost) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_enter_cost(p_enter_cost);
+}
+
+real_t GodotNavigationServer::link_get_enter_cost(const RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, 0);
+
+ return link->get_enter_cost();
+}
+
+COMMAND_2(link_set_travel_cost, RID, p_link, real_t, p_travel_cost) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_travel_cost(p_travel_cost);
+}
+
+real_t GodotNavigationServer::link_get_travel_cost(const RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, 0);
+
+ return link->get_travel_cost();
+}
+
+COMMAND_2(link_set_owner_id, RID, p_link, ObjectID, p_owner_id) {
+ NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND(link == nullptr);
+
+ link->set_owner_id(p_owner_id);
+}
+
+ObjectID GodotNavigationServer::link_get_owner_id(RID p_link) const {
+ const NavLink *link = link_owner.get_or_null(p_link);
+ ERR_FAIL_COND_V(link == nullptr, ObjectID());
+
+ return link->get_owner_id();
+}
+
+RID GodotNavigationServer::agent_create() {
+ MutexLock lock(operations_mutex);
+
RID rid = agent_owner.make_rid();
RvoAgent *agent = agent_owner.get_or_null(rid);
agent->set_self(rid);
@@ -449,11 +641,11 @@ COMMAND_2(agent_set_map, RID, p_agent, RID, p_map) {
}
}
-COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist) {
+COMMAND_2(agent_set_neighbor_distance, RID, p_agent, real_t, p_distance) {
RvoAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND(agent == nullptr);
- agent->get_agent()->neighborDist_ = p_dist;
+ agent->get_agent()->neighborDist_ = p_distance;
}
COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count) {
@@ -519,14 +711,14 @@ bool GodotNavigationServer::agent_is_map_changed(RID p_agent) const {
return agent->is_map_changed();
}
-COMMAND_4(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata) {
+COMMAND_4(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata) {
RvoAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND(agent == nullptr);
- agent->set_callback(p_receiver == nullptr ? ObjectID() : p_receiver->get_instance_id(), p_method, p_udata);
+ agent->set_callback(p_object_id, p_method, p_udata);
if (agent->get_map()) {
- if (p_receiver == nullptr) {
+ if (p_object_id == ObjectID()) {
agent->get_map()->remove_agent_as_controlled(agent);
} else {
agent->get_map()->set_agent_as_controlled(agent);
@@ -539,15 +731,22 @@ COMMAND_1(free, RID, p_object) {
NavMap *map = map_owner.get_or_null(p_object);
// Removes any assigned region
- std::vector<NavRegion *> regions = map->get_regions();
- for (size_t i(0); i < regions.size(); i++) {
+ 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);
}
+ // 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);
+ }
+
// Remove any assigned agent
- std::vector<RvoAgent *> agents = map->get_agents();
- for (size_t i(0); i < agents.size(); i++) {
+ 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);
}
@@ -568,6 +767,17 @@ COMMAND_1(free, RID, p_object) {
region_owner.free(p_object);
+ } else if (link_owner.owns(p_object)) {
+ NavLink *link = link_owner.get_or_null(p_object);
+
+ // Removes this link from the map if assigned
+ if (link->get_map() != nullptr) {
+ link->get_map()->remove_link(link);
+ link->set_map(nullptr);
+ }
+
+ link_owner.free(p_object);
+
} else if (agent_owner.owns(p_object)) {
RvoAgent *agent = agent_owner.get_or_null(p_object);
@@ -584,10 +794,10 @@ COMMAND_1(free, RID, p_object) {
}
}
-void GodotNavigationServer::set_active(bool p_active) const {
- GodotNavigationServer *mut_this = const_cast<GodotNavigationServer *>(this);
- MutexLock lock(mut_this->operations_mutex);
- mut_this->active = p_active;
+void GodotNavigationServer::set_active(bool p_active) {
+ MutexLock lock(operations_mutex);
+
+ active = p_active;
}
void GodotNavigationServer::flush_queries() {
@@ -595,6 +805,7 @@ void GodotNavigationServer::flush_queries() {
// even with mutable functions.
MutexLock lock(commands_mutex);
MutexLock lock2(operations_mutex);
+
for (size_t i(0); i < commands.size(); i++) {
commands[i]->exec(this);
memdelete(commands[i]);
@@ -618,6 +829,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);
@@ -626,6 +846,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]) {
@@ -633,6 +862,89 @@ 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 {
+ PathQueryResult r_query_result;
+
+ const NavMap *map = map_owner.get_or_null(p_parameters.map);
+ ERR_FAIL_COND_V(map == nullptr, r_query_result);
+
+ // run the pathfinding
+
+ if (p_parameters.pathfinding_algorithm == PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR) {
+ // while postprocessing is still part of map.get_path() need to check and route it here for the correct "optimize" post-processing
+ if (p_parameters.path_postprocessing == PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL) {
+ r_query_result.path = map->get_path(
+ p_parameters.start_position,
+ p_parameters.target_position,
+ true,
+ p_parameters.navigation_layers,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_TYPES) ? &r_query_result.path_types : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_RIDS) ? &r_query_result.path_rids : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_OWNERS) ? &r_query_result.path_owner_ids : nullptr);
+ } else if (p_parameters.path_postprocessing == PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED) {
+ r_query_result.path = map->get_path(
+ p_parameters.start_position,
+ p_parameters.target_position,
+ false,
+ p_parameters.navigation_layers,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_TYPES) ? &r_query_result.path_types : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_RIDS) ? &r_query_result.path_rids : nullptr,
+ p_parameters.metadata_flags.has_flag(PathMetadataFlags::PATH_INCLUDE_OWNERS) ? &r_query_result.path_owner_ids : nullptr);
+ }
+ } else {
+ return r_query_result;
+ }
+
+ // add path postprocessing
+
+ // add path stats
+
+ 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
diff --git a/modules/navigation/godot_navigation_server.h b/modules/navigation/godot_navigation_server.h
index 8e7e99888c..a87a88d3bc 100644
--- a/modules/navigation/godot_navigation_server.h
+++ b/modules/navigation/godot_navigation_server.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* godot_navigation_server.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* godot_navigation_server.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef GODOT_NAVIGATION_SERVER_H
#define GODOT_NAVIGATION_SERVER_H
@@ -36,6 +36,7 @@
#include "core/templates/rid_owner.h"
#include "servers/navigation_server_3d.h"
+#include "nav_link.h"
#include "nav_map.h"
#include "nav_region.h"
#include "rvo_agent.h"
@@ -45,16 +46,16 @@
#define MERGE_INTERNAL(A, B) A##B
#define MERGE(A, B) MERGE_INTERNAL(A, B)
-#define COMMAND_1(F_NAME, T_0, D_0) \
- virtual void F_NAME(T_0 D_0) const override; \
+#define COMMAND_1(F_NAME, T_0, D_0) \
+ virtual void F_NAME(T_0 D_0) override; \
void MERGE(_cmd_, F_NAME)(T_0 D_0)
-#define COMMAND_2(F_NAME, T_0, D_0, T_1, D_1) \
- virtual void F_NAME(T_0 D_0, T_1 D_1) const override; \
+#define COMMAND_2(F_NAME, T_0, D_0, T_1, D_1) \
+ virtual void F_NAME(T_0 D_0, T_1 D_1) override; \
void MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1)
-#define COMMAND_4_DEF(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, D_3_DEF) \
- virtual void F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3 = D_3_DEF) const override; \
+#define COMMAND_4_DEF(F_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, D_3_DEF) \
+ virtual void F_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3 = D_3_DEF) override; \
void MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3)
class GodotNavigationServer;
@@ -69,8 +70,9 @@ class GodotNavigationServer : public NavigationServer3D {
/// Mutex used to make any operation threadsafe.
Mutex operations_mutex;
- std::vector<SetCommand *> commands;
+ LocalVector<SetCommand *> commands;
+ mutable RID_Owner<NavLink> link_owner;
mutable RID_Owner<NavMap> map_owner;
mutable RID_Owner<NavRegion> region_owner;
mutable RID_Owner<RvoAgent> agent_owner;
@@ -79,15 +81,25 @@ 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();
- void add_command(SetCommand *command) const;
+ void add_command(SetCommand *command);
- virtual Array get_maps() const override;
+ virtual TypedArray<RID> get_maps() const override;
- virtual RID map_create() const override;
+ virtual RID map_create() override;
COMMAND_2(map_set_active, RID, p_map, bool, p_active);
virtual bool map_is_active(RID p_map) const override;
@@ -100,6 +112,9 @@ public:
COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin);
virtual real_t map_get_edge_connection_margin(RID p_map) const override;
+ COMMAND_2(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius);
+ virtual real_t map_get_link_connection_radius(RID p_map) const override;
+
virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const override;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const override;
@@ -107,18 +122,22 @@ public:
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const override;
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const override;
- virtual Array map_get_regions(RID p_map) const override;
- virtual Array map_get_agents(RID p_map) const override;
+ virtual TypedArray<RID> map_get_links(RID p_map) const override;
+ virtual TypedArray<RID> map_get_regions(RID p_map) const override;
+ virtual TypedArray<RID> map_get_agents(RID p_map) const override;
virtual void map_force_update(RID p_map) override;
- virtual RID region_create() const override;
+ virtual RID region_create() override;
COMMAND_2(region_set_enter_cost, RID, p_region, real_t, p_enter_cost);
virtual real_t region_get_enter_cost(RID p_region) const override;
COMMAND_2(region_set_travel_cost, RID, p_region, real_t, p_travel_cost);
virtual real_t region_get_travel_cost(RID p_region) const override;
+ COMMAND_2(region_set_owner_id, RID, p_region, ObjectID, p_owner_id);
+ virtual ObjectID region_get_owner_id(RID p_region) const override;
+
virtual bool region_owns_point(RID p_region, const Vector3 &p_point) const override;
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
@@ -126,16 +145,34 @@ public:
COMMAND_2(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers);
virtual uint32_t region_get_navigation_layers(RID p_region) const override;
COMMAND_2(region_set_transform, RID, p_region, Transform3D, p_transform);
- COMMAND_2(region_set_navmesh, RID, p_region, Ref<NavigationMesh>, p_nav_mesh);
- virtual void region_bake_navmesh(Ref<NavigationMesh> r_mesh, Node *p_node) const override;
+ COMMAND_2(region_set_navigation_mesh, RID, p_region, Ref<NavigationMesh>, p_navigation_mesh);
+ virtual void region_bake_navigation_mesh(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) override;
virtual int region_get_connections_count(RID p_region) const override;
virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override;
virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override;
- virtual RID agent_create() const override;
+ virtual RID link_create() override;
+ COMMAND_2(link_set_map, RID, p_link, RID, p_map);
+ virtual RID link_get_map(RID p_link) const override;
+ COMMAND_2(link_set_bidirectional, RID, p_link, bool, p_bidirectional);
+ virtual bool link_is_bidirectional(RID p_link) const override;
+ COMMAND_2(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers);
+ virtual uint32_t link_get_navigation_layers(RID p_link) const override;
+ COMMAND_2(link_set_start_location, RID, p_link, Vector3, p_location);
+ virtual Vector3 link_get_start_location(RID p_link) const override;
+ COMMAND_2(link_set_end_location, RID, p_link, Vector3, p_location);
+ virtual Vector3 link_get_end_location(RID p_link) const override;
+ COMMAND_2(link_set_enter_cost, RID, p_link, real_t, p_enter_cost);
+ virtual real_t link_get_enter_cost(RID p_link) const override;
+ COMMAND_2(link_set_travel_cost, RID, p_link, real_t, p_travel_cost);
+ virtual real_t link_get_travel_cost(RID p_link) const override;
+ COMMAND_2(link_set_owner_id, RID, p_link, ObjectID, p_owner_id);
+ virtual ObjectID link_get_owner_id(RID p_link) const override;
+
+ virtual RID agent_create() override;
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
virtual RID agent_get_map(RID p_agent) const override;
- COMMAND_2(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist);
+ COMMAND_2(agent_set_neighbor_distance, RID, p_agent, real_t, p_distance);
COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count);
COMMAND_2(agent_set_time_horizon, RID, p_agent, real_t, p_time);
COMMAND_2(agent_set_radius, RID, p_agent, real_t, p_radius);
@@ -145,14 +182,18 @@ public:
COMMAND_2(agent_set_position, RID, p_agent, Vector3, p_position);
COMMAND_2(agent_set_ignore_y, RID, p_agent, bool, p_ignore);
virtual bool agent_is_map_changed(RID p_agent) const override;
- COMMAND_4_DEF(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, Variant());
+ COMMAND_4_DEF(agent_set_callback, RID, p_agent, ObjectID, p_object_id, StringName, p_method, Variant, p_udata, Variant());
COMMAND_1(free, RID, p_object);
- virtual void set_active(bool p_active) const override;
+ virtual void set_active(bool p_active) override;
void flush_queries();
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_base.h b/modules/navigation/nav_base.h
new file mode 100644
index 0000000000..e729f7d408
--- /dev/null
+++ b/modules/navigation/nav_base.h
@@ -0,0 +1,64 @@
+/**************************************************************************/
+/* nav_base.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef NAV_BASE_H
+#define NAV_BASE_H
+
+#include "nav_rid.h"
+#include "nav_utils.h"
+#include "servers/navigation/navigation_utilities.h"
+
+class NavMap;
+
+class NavBase : public NavRid {
+protected:
+ uint32_t navigation_layers = 1;
+ float enter_cost = 0.0;
+ float travel_cost = 1.0;
+ ObjectID owner_id;
+ NavigationUtilities::PathSegmentType type;
+
+public:
+ NavigationUtilities::PathSegmentType get_type() const { return type; }
+
+ void set_navigation_layers(uint32_t p_navigation_layers) { navigation_layers = p_navigation_layers; }
+ uint32_t get_navigation_layers() const { return navigation_layers; }
+
+ void set_enter_cost(float p_enter_cost) { enter_cost = MAX(p_enter_cost, 0.0); }
+ float get_enter_cost() const { return enter_cost; }
+
+ void set_travel_cost(float p_travel_cost) { travel_cost = MAX(p_travel_cost, 0.0); }
+ float get_travel_cost() const { return travel_cost; }
+
+ void set_owner_id(ObjectID p_owner_id) { owner_id = p_owner_id; }
+ ObjectID get_owner_id() const { return owner_id; }
+};
+
+#endif // NAV_BASE_H
diff --git a/modules/navigation/nav_link.cpp b/modules/navigation/nav_link.cpp
new file mode 100644
index 0000000000..05d2b21487
--- /dev/null
+++ b/modules/navigation/nav_link.cpp
@@ -0,0 +1,60 @@
+/**************************************************************************/
+/* nav_link.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#include "nav_link.h"
+
+#include "nav_map.h"
+
+void NavLink::set_map(NavMap *p_map) {
+ map = p_map;
+ link_dirty = true;
+}
+
+void NavLink::set_bidirectional(bool p_bidirectional) {
+ bidirectional = p_bidirectional;
+ link_dirty = true;
+}
+
+void NavLink::set_start_location(const Vector3 p_location) {
+ start_location = p_location;
+ link_dirty = true;
+}
+
+void NavLink::set_end_location(const Vector3 p_location) {
+ end_location = p_location;
+ link_dirty = true;
+}
+
+bool NavLink::check_dirty() {
+ const bool was_dirty = link_dirty;
+
+ link_dirty = false;
+ return was_dirty;
+}
diff --git a/modules/navigation/nav_link.h b/modules/navigation/nav_link.h
new file mode 100644
index 0000000000..47c1211db8
--- /dev/null
+++ b/modules/navigation/nav_link.h
@@ -0,0 +1,73 @@
+/**************************************************************************/
+/* nav_link.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
+
+#ifndef NAV_LINK_H
+#define NAV_LINK_H
+
+#include "nav_base.h"
+#include "nav_utils.h"
+
+class NavLink : public NavBase {
+ NavMap *map = nullptr;
+ bool bidirectional = true;
+ Vector3 start_location;
+ Vector3 end_location;
+
+ bool link_dirty = true;
+
+public:
+ NavLink() {
+ type = NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_LINK;
+ }
+
+ void set_map(NavMap *p_map);
+ NavMap *get_map() const {
+ return map;
+ }
+
+ void set_bidirectional(bool p_bidirectional);
+ bool is_bidirectional() const {
+ return bidirectional;
+ }
+
+ void set_start_location(Vector3 p_location);
+ Vector3 get_start_location() const {
+ return start_location;
+ }
+
+ void set_end_location(Vector3 p_location);
+ Vector3 get_end_location() const {
+ return end_location;
+ }
+
+ bool check_dirty();
+};
+
+#endif // NAV_LINK_H
diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp
index 17d6e0a0a1..fd735f8793 100644
--- a/modules/navigation/nav_map.cpp
+++ b/modules/navigation/nav_map.cpp
@@ -1,42 +1,55 @@
-/*************************************************************************/
-/* nav_map.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* nav_map.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "nav_map.h"
+#include "core/object/worker_thread_pool.h"
+#include "nav_link.h"
#include "nav_region.h"
#include "rvo_agent.h"
-
#include <algorithm>
#define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a)))
+// Helper macro
+#define APPEND_METADATA(poly) \
+ if (r_path_types) { \
+ r_path_types->push_back(poly->owner->get_type()); \
+ } \
+ if (r_path_rids) { \
+ r_path_rids->push_back(poly->owner->get_self()); \
+ } \
+ if (r_path_owners) { \
+ r_path_owners->push_back(poly->owner->get_owner_id()); \
+ }
+
void NavMap::set_up(Vector3 p_up) {
up = p_up;
regenerate_polygons = true;
@@ -52,6 +65,11 @@ void NavMap::set_edge_connection_margin(float p_edge_connection_margin) {
regenerate_links = true;
}
+void NavMap::set_link_connection_radius(float p_link_connection_radius) {
+ link_connection_radius = p_link_connection_radius;
+ regenerate_links = true;
+}
+
gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
const int x = int(Math::floor(p_pos.x / cell_size));
const int y = int(Math::floor(p_pos.y / cell_size));
@@ -65,7 +83,18 @@ gd::PointKey NavMap::get_point_key(const Vector3 &p_pos) const {
return p;
}
-Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers) const {
+Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const {
+ // Clear metadata outputs.
+ if (r_path_types) {
+ r_path_types->clear();
+ }
+ if (r_path_rids) {
+ r_path_rids->clear();
+ }
+ if (r_path_owners) {
+ r_path_owners->clear();
+ }
+
// Find the start poly and the end poly on this map.
const gd::Polygon *begin_poly = nullptr;
const gd::Polygon *end_poly = nullptr;
@@ -109,6 +138,24 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
return Vector<Vector3>();
}
if (begin_poly == end_poly) {
+ if (r_path_types) {
+ r_path_types->resize(2);
+ r_path_types->write[0] = begin_poly->owner->get_type();
+ r_path_types->write[1] = end_poly->owner->get_type();
+ }
+
+ if (r_path_rids) {
+ r_path_rids->resize(2);
+ (*r_path_rids)[0] = begin_poly->owner->get_self();
+ (*r_path_rids)[1] = end_poly->owner->get_self();
+ }
+
+ if (r_path_owners) {
+ r_path_owners->resize(2);
+ r_path_owners->write[0] = begin_poly->owner->get_owner_id();
+ r_path_owners->write[1] = end_poly->owner->get_owner_id();
+ }
+
Vector<Vector3> path;
path.resize(2);
path.write[0] = begin_point;
@@ -117,7 +164,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
}
// List of all reachable navigation polys.
- std::vector<gd::NavigationPoly> navigation_polys;
+ LocalVector<gd::NavigationPoly> navigation_polys;
navigation_polys.reserve(polygons.size() * 0.75);
// Add the start polygon to the reachable navigation polygons.
@@ -134,20 +181,17 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
// This is an implementation of the A* algorithm.
int least_cost_id = 0;
+ int prev_least_cost_id = -1;
bool found_route = false;
const gd::Polygon *reachable_end = nullptr;
float reachable_d = 1e30;
bool is_reachable = true;
- gd::NavigationPoly *prev_least_cost_poly = nullptr;
-
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++) {
- gd::NavigationPoly *least_cost_poly = &navigation_polys[least_cost_id];
-
- const gd::Edge &edge = least_cost_poly->poly->edges[i];
+ const gd::Edge &edge = navigation_polys[least_cost_id].poly->edges[i];
// 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++) {
@@ -158,32 +202,31 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
continue;
}
- float region_enter_cost = 0.0;
- float region_travel_cost = least_cost_poly->poly->owner->get_travel_cost();
+ const gd::NavigationPoly &least_cost_poly = navigation_polys[least_cost_id];
+ float poly_enter_cost = 0.0;
+ float poly_travel_cost = least_cost_poly.poly->owner->get_travel_cost();
- if (prev_least_cost_poly != nullptr && !(prev_least_cost_poly->poly->owner->get_self() == least_cost_poly->poly->owner->get_self())) {
- region_enter_cost = least_cost_poly->poly->owner->get_enter_cost();
+ if (prev_least_cost_id != -1 && (navigation_polys[prev_least_cost_id].poly->owner->get_self() != least_cost_poly.poly->owner->get_self())) {
+ poly_enter_cost = least_cost_poly.poly->owner->get_enter_cost();
}
- prev_least_cost_poly = least_cost_poly;
+ prev_least_cost_id = least_cost_id;
Vector3 pathway[2] = { connection.pathway_start, connection.pathway_end };
- const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly->entry, pathway);
- const float new_distance = (least_cost_poly->entry.distance_to(new_entry) * region_travel_cost) + region_enter_cost + least_cost_poly->traveled_distance;
+ const Vector3 new_entry = Geometry3D::get_closest_point_to_segment(least_cost_poly.entry, pathway);
+ const float new_distance = (least_cost_poly.entry.distance_to(new_entry) * poly_travel_cost) + poly_enter_cost + least_cost_poly.traveled_distance;
- const std::vector<gd::NavigationPoly>::iterator it = std::find(
- navigation_polys.begin(),
- navigation_polys.end(),
- gd::NavigationPoly(connection.polygon));
+ int64_t already_visited_polygon_index = navigation_polys.find(gd::NavigationPoly(connection.polygon));
- if (it != navigation_polys.end()) {
+ if (already_visited_polygon_index != -1) {
// Polygon already visited, check if we can reduce the travel cost.
- if (new_distance < it->traveled_distance) {
- it->back_navigation_poly_id = least_cost_id;
- it->back_navigation_edge = connection.edge;
- it->back_navigation_edge_pathway_start = connection.pathway_start;
- it->back_navigation_edge_pathway_end = connection.pathway_end;
- it->traveled_distance = new_distance;
- it->entry = new_entry;
+ gd::NavigationPoly &avp = navigation_polys[already_visited_polygon_index];
+ if (new_distance < avp.traveled_distance) {
+ avp.back_navigation_poly_id = least_cost_id;
+ avp.back_navigation_edge = connection.edge;
+ avp.back_navigation_edge_pathway_start = connection.pathway_start;
+ avp.back_navigation_edge_pathway_end = connection.pathway_end;
+ avp.traveled_distance = new_distance;
+ avp.entry = new_entry;
}
} else {
// Add the neighbour polygon to the reachable ones.
@@ -236,6 +279,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
to_visit.clear();
to_visit.push_back(0);
least_cost_id = 0;
+ prev_least_cost_id = -1;
reachable_end = nullptr;
@@ -293,6 +337,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
gd::NavigationPoly *p = apex_poly;
path.push_back(end_point);
+ APPEND_METADATA(end_poly);
while (p) {
// Set left and right points of the pathway between polygons.
@@ -309,7 +354,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
left_poly = p;
left_portal = left;
} else {
- clip_path(navigation_polys, path, apex_poly, right_portal, right_poly);
+ clip_path(navigation_polys, path, apex_poly, right_portal, right_poly, r_path_types, r_path_rids, r_path_owners);
apex_point = right_portal;
p = right_poly;
@@ -317,7 +362,9 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
apex_poly = p;
left_portal = apex_point;
right_portal = apex_point;
+
path.push_back(apex_point);
+ APPEND_METADATA(apex_poly->poly);
skip = true;
}
}
@@ -328,7 +375,7 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
right_poly = p;
right_portal = right;
} else {
- clip_path(navigation_polys, path, apex_poly, left_portal, left_poly);
+ clip_path(navigation_polys, path, apex_poly, left_portal, left_poly, r_path_types, r_path_rids, r_path_owners);
apex_point = left_portal;
p = left_poly;
@@ -336,7 +383,9 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
apex_poly = p;
right_portal = apex_point;
left_portal = apex_point;
+
path.push_back(apex_point);
+ APPEND_METADATA(apex_poly->poly);
}
}
@@ -352,27 +401,62 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
// If the last point is not the begin point, add it to the list.
if (path[path.size() - 1] != begin_point) {
path.push_back(begin_point);
+ APPEND_METADATA(begin_poly);
}
path.reverse();
+ if (r_path_types) {
+ r_path_types->reverse();
+ }
+ if (r_path_rids) {
+ r_path_rids->reverse();
+ }
+ if (r_path_owners) {
+ r_path_owners->reverse();
+ }
} else {
path.push_back(end_point);
+ APPEND_METADATA(end_poly);
// Add mid points
int np_id = least_cost_id;
while (np_id != -1 && navigation_polys[np_id].back_navigation_poly_id != -1) {
- int prev = navigation_polys[np_id].back_navigation_edge;
- int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size();
- Vector3 point = (navigation_polys[np_id].poly->points[prev].pos + navigation_polys[np_id].poly->points[prev_n].pos) * 0.5;
- path.push_back(point);
+ if (navigation_polys[np_id].back_navigation_edge != -1) {
+ int prev = navigation_polys[np_id].back_navigation_edge;
+ int prev_n = (navigation_polys[np_id].back_navigation_edge + 1) % navigation_polys[np_id].poly->points.size();
+ Vector3 point = (navigation_polys[np_id].poly->points[prev].pos + navigation_polys[np_id].poly->points[prev_n].pos) * 0.5;
+
+ path.push_back(point);
+ APPEND_METADATA(navigation_polys[np_id].poly);
+ } else {
+ path.push_back(navigation_polys[np_id].entry);
+ APPEND_METADATA(navigation_polys[np_id].poly);
+ }
+
np_id = navigation_polys[np_id].back_navigation_poly_id;
}
path.push_back(begin_point);
+ APPEND_METADATA(begin_poly);
+
path.reverse();
+ if (r_path_types) {
+ r_path_types->reverse();
+ }
+ if (r_path_rids) {
+ r_path_rids->reverse();
+ }
+ if (r_path_owners) {
+ r_path_owners->reverse();
+ }
}
+ // Ensure post conditions (path arrays MUST match in size).
+ CRASH_COND(r_path_types && path.size() != r_path_types->size());
+ CRASH_COND(r_path_rids && path.size() != r_path_rids->size());
+ CRASH_COND(r_path_owners && path.size() != r_path_owners->size());
+
return path;
}
@@ -470,15 +554,28 @@ void NavMap::add_region(NavRegion *p_region) {
}
void NavMap::remove_region(NavRegion *p_region) {
- const std::vector<NavRegion *>::iterator it = std::find(regions.begin(), regions.end(), p_region);
- if (it != regions.end()) {
- regions.erase(it);
+ int64_t region_index = regions.find(p_region);
+ if (region_index != -1) {
+ regions.remove_at_unordered(region_index);
+ regenerate_links = true;
+ }
+}
+
+void NavMap::add_link(NavLink *p_link) {
+ links.push_back(p_link);
+ regenerate_links = true;
+}
+
+void NavMap::remove_link(NavLink *p_link) {
+ int64_t link_index = links.find(p_link);
+ if (link_index != -1) {
+ links.remove_at_unordered(link_index);
regenerate_links = true;
}
}
bool NavMap::has_agent(RvoAgent *agent) const {
- return std::find(agents.begin(), agents.end(), agent) != agents.end();
+ return (agents.find(agent) != -1);
}
void NavMap::add_agent(RvoAgent *agent) {
@@ -490,15 +587,15 @@ void NavMap::add_agent(RvoAgent *agent) {
void NavMap::remove_agent(RvoAgent *agent) {
remove_agent_as_controlled(agent);
- const std::vector<RvoAgent *>::iterator it = std::find(agents.begin(), agents.end(), agent);
- if (it != agents.end()) {
- agents.erase(it);
+ int64_t agent_index = agents.find(agent);
+ if (agent_index != -1) {
+ agents.remove_at_unordered(agent_index);
agents_dirty = true;
}
}
void NavMap::set_agent_as_controlled(RvoAgent *agent) {
- const bool exist = std::find(controlled_agents.begin(), controlled_agents.end(), agent) != controlled_agents.end();
+ const bool exist = (controlled_agents.find(agent) != -1);
if (!exist) {
ERR_FAIL_COND(!has_agent(agent));
controlled_agents.push_back(agent);
@@ -506,62 +603,88 @@ void NavMap::set_agent_as_controlled(RvoAgent *agent) {
}
void NavMap::remove_agent_as_controlled(RvoAgent *agent) {
- const std::vector<RvoAgent *>::iterator it = std::find(controlled_agents.begin(), controlled_agents.end(), agent);
- if (it != controlled_agents.end()) {
- controlled_agents.erase(it);
+ int64_t active_avoidance_agent_index = controlled_agents.find(agent);
+ if (active_avoidance_agent_index != -1) {
+ controlled_agents.remove_at_unordered(active_avoidance_agent_index);
+ agents_dirty = true;
}
}
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 (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
regions[r]->scratch_polygons();
}
regenerate_links = true;
}
- for (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
if (regions[r]->sync()) {
regenerate_links = true;
}
}
+ for (uint32_t l = 0; l < links.size(); l++) {
+ if (links[l]->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 (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
regions[r]->get_connections().clear();
}
// Resize the polygon count.
int count = 0;
- for (size_t r(0); r < regions.size(); r++) {
+ for (uint32_t r = 0; r < regions.size(); r++) {
count += regions[r]->get_polygons().size();
}
polygons.resize(count);
// Copy all region polygons in the map.
count = 0;
- for (size_t r(0); r < regions.size(); r++) {
- std::copy(
- regions[r]->get_polygons().data(),
- regions[r]->get_polygons().data() + regions[r]->get_polygons().size(),
- polygons.begin() + count);
+ for (uint32_t r = 0; r < regions.size(); r++) {
+ const LocalVector<gd::Polygon> &polygons_source = regions[r]->get_polygons();
+ for (uint32_t n = 0; n < polygons_source.size(); n++) {
+ polygons[count + n] = polygons_source[n];
+ }
count += regions[r]->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 (size_t poly_id(0); poly_id < polygons.size(); poly_id++) {
+ for (uint32_t poly_id = 0; poly_id < polygons.size(); poly_id++) {
gd::Polygon &poly(polygons[poly_id]);
- for (size_t p(0); p < poly.points.size(); p++) {
+ 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);
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.
@@ -587,6 +710,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]);
@@ -600,6 +724,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;
@@ -652,7 +778,122 @@ void NavMap::sync() {
free_edge.polygon->edges[free_edge.edge].connections.push_back(new_connection);
// Add the connection to the region_connection map.
- free_edge.polygon->owner->get_connections().push_back(new_connection);
+ ((NavRegion *)free_edge.polygon->owner)->get_connections().push_back(new_connection);
+ _new_pm_edge_connection_count += 1;
+ }
+ }
+
+ uint32_t link_poly_idx = 0;
+ 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];
+ const Vector3 start = link->get_start_location();
+ const Vector3 end = link->get_end_location();
+
+ gd::Polygon *closest_start_polygon = nullptr;
+ real_t closest_start_distance = link_connection_radius;
+ Vector3 closest_start_point;
+
+ gd::Polygon *closest_end_polygon = nullptr;
+ real_t closest_end_distance = link_connection_radius;
+ Vector3 closest_end_point;
+
+ // Create link to any polygons within the search radius of the start point.
+ for (uint32_t start_index = 0; start_index < polygons.size(); start_index++) {
+ gd::Polygon &start_poly = polygons[start_index];
+
+ // For each face check the distance to the start
+ for (uint32_t start_point_id = 2; start_point_id < start_poly.points.size(); start_point_id += 1) {
+ const Face3 start_face(start_poly.points[0].pos, start_poly.points[start_point_id - 1].pos, start_poly.points[start_point_id].pos);
+ const Vector3 start_point = start_face.get_closest_point_to(start);
+ const real_t start_distance = start_point.distance_to(start);
+
+ // Pick the polygon that is within our radius and is closer than anything we've seen yet.
+ if (start_distance <= link_connection_radius && start_distance < closest_start_distance) {
+ closest_start_distance = start_distance;
+ closest_start_point = start_point;
+ closest_start_polygon = &start_poly;
+ }
+ }
+ }
+
+ // 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 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);
+ const Vector3 end_point = end_face.get_closest_point_to(end);
+ const real_t end_distance = end_point.distance_to(end);
+
+ // Pick the polygon that is within our radius and is closer than anything we've seen yet.
+ if (end_distance <= link_connection_radius && end_distance < closest_end_distance) {
+ closest_end_distance = end_distance;
+ closest_end_point = end_point;
+ closest_end_polygon = &end_poly;
+ }
+ }
+ }
+
+ // If we have both a start and end point, then create a synthetic polygon to route through.
+ if (closest_start_polygon && closest_end_polygon) {
+ gd::Polygon &new_polygon = link_polygons[link_poly_idx++];
+ new_polygon.owner = link;
+
+ new_polygon.edges.clear();
+ new_polygon.edges.resize(4);
+ new_polygon.points.clear();
+ new_polygon.points.reserve(4);
+
+ // Build a set of vertices that create a thin polygon going from the start to the end point.
+ new_polygon.points.push_back({ closest_start_point, get_point_key(closest_start_point) });
+ new_polygon.points.push_back({ closest_start_point, get_point_key(closest_start_point) });
+ new_polygon.points.push_back({ closest_end_point, get_point_key(closest_end_point) });
+ new_polygon.points.push_back({ closest_end_point, get_point_key(closest_end_point) });
+
+ Vector3 center;
+ for (int p = 0; p < 4; ++p) {
+ center += new_polygon.points[p].pos;
+ }
+ new_polygon.center = center / real_t(new_polygon.points.size());
+ new_polygon.clockwise = true;
+
+ // Setup connections to go forward in the link.
+ {
+ gd::Edge::Connection entry_connection;
+ entry_connection.polygon = &new_polygon;
+ entry_connection.edge = -1;
+ entry_connection.pathway_start = new_polygon.points[0].pos;
+ entry_connection.pathway_end = new_polygon.points[1].pos;
+ closest_start_polygon->edges[0].connections.push_back(entry_connection);
+
+ gd::Edge::Connection exit_connection;
+ exit_connection.polygon = closest_end_polygon;
+ exit_connection.edge = -1;
+ exit_connection.pathway_start = new_polygon.points[2].pos;
+ exit_connection.pathway_end = new_polygon.points[3].pos;
+ new_polygon.edges[2].connections.push_back(exit_connection);
+ }
+
+ // If the link is bi-directional, create connections from the end to the start.
+ if (link->is_bidirectional()) {
+ gd::Edge::Connection entry_connection;
+ entry_connection.polygon = &new_polygon;
+ entry_connection.edge = -1;
+ entry_connection.pathway_start = new_polygon.points[2].pos;
+ entry_connection.pathway_end = new_polygon.points[3].pos;
+ closest_end_polygon->edges[0].connections.push_back(entry_connection);
+
+ gd::Edge::Connection exit_connection;
+ exit_connection.polygon = closest_start_polygon;
+ exit_connection.edge = -1;
+ exit_connection.pathway_start = new_polygon.points[0].pos;
+ exit_connection.pathway_end = new_polygon.points[1].pos;
+ new_polygon.edges[0].connections.push_back(exit_connection);
+ }
}
}
@@ -662,6 +903,7 @@ void NavMap::sync() {
// Update agents tree.
if (agents_dirty) {
+ // 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++) {
@@ -673,6 +915,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) {
@@ -683,14 +935,8 @@ 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) {
- if (step_work_pool.get_thread_count() == 0) {
- step_work_pool.init();
- }
- step_work_pool.do_work(
- controlled_agents.size(),
- this,
- &NavMap::compute_single_step,
- controlled_agents.data());
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &NavMap::compute_single_step, controlled_agents.ptr(), controlled_agents.size(), -1, true, SNAME("NavigationMapAgents"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
}
}
@@ -700,7 +946,7 @@ void NavMap::dispatch_callbacks() {
}
}
-void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const {
+void NavMap::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 {
Vector3 from = path[path.size() - 1];
if (from.is_equal_approx(p_to_point)) {
@@ -726,6 +972,7 @@ void NavMap::clip_path(const std::vector<gd::NavigationPoly> &p_navigation_polys
if (cut_plane.intersects_segment(pathway_start, pathway_end, &inters)) {
if (!inters.is_equal_approx(p_to_point) && !inters.is_equal_approx(path[path.size() - 1])) {
path.push_back(inters);
+ APPEND_METADATA(from_poly->poly);
}
}
}
@@ -736,5 +983,4 @@ NavMap::NavMap() {
}
NavMap::~NavMap() {
- step_work_pool.finish();
}
diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h
index 2036dbecd7..fce7aff3ba 100644
--- a/modules/navigation/nav_map.h
+++ b/modules/navigation/nav_map.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* nav_map.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* nav_map.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef NAV_MAP_H
#define NAV_MAP_H
@@ -34,15 +34,15 @@
#include "nav_rid.h"
#include "core/math/math_defs.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/rb_map.h"
-#include "core/templates/thread_work_pool.h"
#include "nav_utils.h"
#include <KdTree.h>
+class NavLink;
class NavRegion;
class RvoAgent;
-class NavRegion;
class NavMap : public NavRid {
/// Map Up
@@ -55,13 +55,21 @@ class NavMap : public NavRid {
/// This value is used to detect the near edges to connect.
real_t edge_connection_margin = 0.25;
+ /// This value is used to limit how far links search to find polygons to connect to.
+ real_t link_connection_radius = 1.0;
+
bool regenerate_polygons = true;
bool regenerate_links = true;
- std::vector<NavRegion *> regions;
+ /// Map regions
+ LocalVector<NavRegion *> regions;
+
+ /// Map links
+ LocalVector<NavLink *> links;
+ LocalVector<gd::Polygon> link_polygons;
/// Map polygons
- std::vector<gd::Polygon> polygons;
+ LocalVector<gd::Polygon> polygons;
/// Rvo world
RVO::KdTree rvo;
@@ -70,10 +78,10 @@ class NavMap : public NavRid {
bool agents_dirty = false;
/// All the Agents (even the controlled one)
- std::vector<RvoAgent *> agents;
+ LocalVector<RvoAgent *> agents;
/// Controlled agents
- std::vector<RvoAgent *> controlled_agents;
+ LocalVector<RvoAgent *> controlled_agents;
/// Physics delta time
real_t deltatime = 0.0;
@@ -81,8 +89,15 @@ class NavMap : public NavRid {
/// Change the id each time the map is updated.
uint32_t map_update_id = 0;
- /// Pooled threads for computing steps
- ThreadWorkPool step_work_pool;
+ // 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();
@@ -103,9 +118,14 @@ public:
return edge_connection_margin;
}
+ void set_link_connection_radius(float p_link_connection_radius);
+ float get_link_connection_radius() const {
+ return link_connection_radius;
+ }
+
gd::PointKey get_point_key(const Vector3 &p_pos) const;
- Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
+ Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers, Vector<int32_t> *r_path_types, TypedArray<RID> *r_path_rids, Vector<int64_t> *r_path_owners) const;
Vector3 get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const;
Vector3 get_closest_point(const Vector3 &p_point) const;
Vector3 get_closest_point_normal(const Vector3 &p_point) const;
@@ -114,14 +134,20 @@ public:
void add_region(NavRegion *p_region);
void remove_region(NavRegion *p_region);
- const std::vector<NavRegion *> &get_regions() const {
+ const LocalVector<NavRegion *> &get_regions() const {
return regions;
}
+ void add_link(NavLink *p_link);
+ void remove_link(NavLink *p_link);
+ const LocalVector<NavLink *> &get_links() const {
+ return links;
+ }
+
bool has_agent(RvoAgent *agent) const;
void add_agent(RvoAgent *agent);
void remove_agent(RvoAgent *agent);
- const std::vector<RvoAgent *> &get_agents() const {
+ const LocalVector<RvoAgent *> &get_agents() const {
return agents;
}
@@ -136,9 +162,19 @@ 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 std::vector<gd::NavigationPoly> &p_navigation_polys, Vector<Vector3> &path, const gd::NavigationPoly *from_poly, const Vector3 &p_to_point, const gd::NavigationPoly *p_to_poly) const;
+ 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;
};
#endif // NAV_MAP_H
diff --git a/modules/navigation/nav_region.cpp b/modules/navigation/nav_region.cpp
index 88740807eb..797c523627 100644
--- a/modules/navigation/nav_region.cpp
+++ b/modules/navigation/nav_region.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* nav_region.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* nav_region.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "nav_region.h"
@@ -40,14 +40,6 @@ void NavRegion::set_map(NavMap *p_map) {
}
}
-void NavRegion::set_navigation_layers(uint32_t p_navigation_layers) {
- navigation_layers = p_navigation_layers;
-}
-
-uint32_t NavRegion::get_navigation_layers() const {
- return navigation_layers;
-}
-
void NavRegion::set_transform(Transform3D p_transform) {
transform = p_transform;
polygons_dirty = true;
diff --git a/modules/navigation/nav_region.h b/modules/navigation/nav_region.h
index 484856ae36..0942aa22f0 100644
--- a/modules/navigation/nav_region.h
+++ b/modules/navigation/nav_region.h
@@ -1,62 +1,56 @@
-/*************************************************************************/
-/* nav_region.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* nav_region.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef NAV_REGION_H
#define NAV_REGION_H
#include "scene/resources/navigation_mesh.h"
-#include "nav_rid.h"
+#include "nav_base.h"
#include "nav_utils.h"
-#include <vector>
-
-class NavMap;
-class NavRegion;
-
-class NavRegion : public NavRid {
+class NavRegion : public NavBase {
NavMap *map = nullptr;
Transform3D transform;
Ref<NavigationMesh> mesh;
- uint32_t navigation_layers = 1;
- float enter_cost = 0.0;
- float travel_cost = 1.0;
Vector<gd::Edge::Connection> connections;
bool polygons_dirty = true;
/// Cache
- std::vector<gd::Polygon> polygons;
+ LocalVector<gd::Polygon> polygons;
public:
- NavRegion() {}
+ NavRegion() {
+ type = NavigationUtilities::PathSegmentType::PATH_SEGMENT_TYPE_REGION;
+ }
void scratch_polygons() {
polygons_dirty = true;
@@ -67,15 +61,6 @@ public:
return map;
}
- void set_enter_cost(float p_enter_cost) { enter_cost = MAX(p_enter_cost, 0.0); }
- float get_enter_cost() const { return enter_cost; }
-
- void set_travel_cost(float p_travel_cost) { travel_cost = MAX(p_travel_cost, 0.0); }
- float get_travel_cost() const { return travel_cost; }
-
- void set_navigation_layers(uint32_t p_navigation_layers);
- uint32_t get_navigation_layers() const;
-
void set_transform(Transform3D transform);
const Transform3D &get_transform() const {
return transform;
@@ -93,7 +78,7 @@ public:
Vector3 get_connection_pathway_start(int p_connection_id) const;
Vector3 get_connection_pathway_end(int p_connection_id) const;
- std::vector<gd::Polygon> const &get_polygons() const {
+ LocalVector<gd::Polygon> const &get_polygons() const {
return polygons;
}
diff --git a/modules/navigation/nav_rid.h b/modules/navigation/nav_rid.h
index 31e20440d2..6229985a8d 100644
--- a/modules/navigation/nav_rid.h
+++ b/modules/navigation/nav_rid.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* nav_rid.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* nav_rid.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef NAV_RID_H
#define NAV_RID_H
diff --git a/modules/navigation/nav_utils.h b/modules/navigation/nav_utils.h
index a9f4e0e2fc..50437469aa 100644
--- a/modules/navigation/nav_utils.h
+++ b/modules/navigation/nav_utils.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* nav_utils.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* nav_utils.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef NAV_UTILS_H
#define NAV_UTILS_H
@@ -34,10 +34,9 @@
#include "core/math/vector3.h"
#include "core/templates/hash_map.h"
#include "core/templates/hashfuncs.h"
-#include "core/templates/vector.h"
-#include <vector>
+#include "core/templates/local_vector.h"
-class NavRegion;
+class NavBase;
namespace gd {
struct Polygon;
@@ -79,30 +78,37 @@ struct Point {
};
struct Edge {
- /// This edge ID
- int this_edge = -1;
-
/// The gateway in the edge, as, in some case, the whole edge might not be navigable.
struct Connection {
+ /// Polygon that this connection leads to.
Polygon *polygon = nullptr;
+
+ /// Edge of the source polygon where this connection starts from.
int edge = -1;
+
+ /// Point on the edge where the gateway leading to the poly starts.
Vector3 pathway_start;
+
+ /// Point on the edge where the gateway leading to the poly ends.
Vector3 pathway_end;
};
+
+ /// Connections from this edge to other polygons.
Vector<Connection> connections;
};
struct Polygon {
- NavRegion *owner = nullptr;
+ /// Navigation region or link that contains this polygon.
+ const NavBase *owner = nullptr;
/// The points of this `Polygon`
- std::vector<Point> points;
+ LocalVector<Point> points;
- /// Are the points clockwise ?
+ /// Are the points clockwise?
bool clockwise;
/// The edges of this `Polygon`
- std::vector<Edge> edges;
+ LocalVector<Edge> edges;
/// The center of this `Polygon`
Vector3 center;
@@ -115,7 +121,7 @@ struct NavigationPoly {
/// Those 4 variables are used to travel the path backwards.
int back_navigation_poly_id = -1;
- uint32_t back_navigation_edge = UINT32_MAX;
+ int back_navigation_edge = -1;
Vector3 back_navigation_edge_pathway_start;
Vector3 back_navigation_edge_pathway_end;
@@ -124,6 +130,8 @@ struct NavigationPoly {
/// The distance to the destination.
float traveled_distance = 0.0;
+ NavigationPoly() { poly = nullptr; }
+
NavigationPoly(const Polygon *p_poly) :
poly(p_poly) {}
diff --git a/modules/navigation/navigation_mesh_generator.cpp b/modules/navigation/navigation_mesh_generator.cpp
index 6e8ac77f79..fff7a02fc4 100644
--- a/modules/navigation/navigation_mesh_generator.cpp
+++ b/modules/navigation/navigation_mesh_generator.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* navigation_mesh_generator.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* navigation_mesh_generator.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef _3D_DISABLED
@@ -42,6 +42,7 @@
#include "scene/resources/concave_polygon_shape_3d.h"
#include "scene/resources/convex_polygon_shape_3d.h"
#include "scene/resources/cylinder_shape_3d.h"
+#include "scene/resources/height_map_shape_3d.h"
#include "scene/resources/primitive_meshes.h"
#include "scene/resources/shape_3d.h"
#include "scene/resources/sphere_shape_3d.h"
@@ -206,6 +207,9 @@ 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++) {
Ref<Shape3D> s = static_body->shape_owner_get_shape(shape_owner, i);
@@ -262,10 +266,10 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
if (err == OK) {
PackedVector3Array faces;
- for (int j = 0; j < md.faces.size(); ++j) {
- Geometry3D::MeshData::Face face = md.faces[j];
+ for (uint32_t j = 0; j < md.faces.size(); ++j) {
+ const Geometry3D::MeshData::Face &face = md.faces[j];
- for (int k = 2; k < face.indices.size(); ++k) {
+ 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]]);
faces.push_back(md.vertices[face.indices[k]]);
@@ -275,6 +279,50 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
_add_faces(faces, transform, p_vertices, p_indices);
}
}
+
+ HeightMapShape3D *heightmap_shape = Object::cast_to<HeightMapShape3D>(*s);
+ if (heightmap_shape) {
+ int heightmap_depth = heightmap_shape->get_map_depth();
+ int heightmap_width = heightmap_shape->get_map_width();
+
+ if (heightmap_depth >= 2 && heightmap_width >= 2) {
+ const Vector<real_t> &map_data = heightmap_shape->get_map_data();
+
+ Vector2 heightmap_gridsize(heightmap_width - 1, heightmap_depth - 1);
+ Vector2 start = heightmap_gridsize * -0.5;
+
+ Vector<Vector3> vertex_array;
+ vertex_array.resize((heightmap_depth - 1) * (heightmap_width - 1) * 6);
+ int map_data_current_index = 0;
+
+ for (int d = 0; d < heightmap_depth - 1; d++) {
+ for (int w = 0; w < heightmap_width - 1; w++) {
+ if (map_data_current_index + 1 + heightmap_depth < map_data.size()) {
+ float top_left_height = map_data[map_data_current_index];
+ float top_right_height = map_data[map_data_current_index + 1];
+ float bottom_left_height = map_data[map_data_current_index + heightmap_depth];
+ float bottom_right_height = map_data[map_data_current_index + 1 + heightmap_depth];
+
+ Vector3 top_left = Vector3(start.x + w, top_left_height, start.y + d);
+ Vector3 top_right = Vector3(start.x + w + 1.0, top_right_height, start.y + d);
+ Vector3 bottom_left = Vector3(start.x + w, bottom_left_height, start.y + d + 1.0);
+ Vector3 bottom_right = Vector3(start.x + w + 1.0, bottom_right_height, start.y + d + 1.0);
+
+ vertex_array.push_back(top_right);
+ vertex_array.push_back(bottom_left);
+ vertex_array.push_back(top_left);
+ vertex_array.push_back(top_right);
+ vertex_array.push_back(bottom_right);
+ vertex_array.push_back(bottom_left);
+ }
+ map_data_current_index += 1;
+ }
+ }
+ if (vertex_array.size() > 0) {
+ _add_faces(vertex_array, transform, p_vertices, p_indices);
+ }
+ }
+ }
}
}
}
@@ -344,10 +392,10 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
if (err == OK) {
PackedVector3Array faces;
- for (int j = 0; j < md.faces.size(); ++j) {
- Geometry3D::MeshData::Face face = md.faces[j];
+ for (uint32_t j = 0; j < md.faces.size(); ++j) {
+ const Geometry3D::MeshData::Face &face = md.faces[j];
- for (int k = 2; k < face.indices.size(); ++k) {
+ 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]]);
faces.push_back(md.vertices[face.indices[k]]);
@@ -362,6 +410,50 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
PackedVector3Array faces = Variant(dict["faces"]);
_add_faces(faces, shapes[i], p_vertices, p_indices);
} break;
+ case PhysicsServer3D::SHAPE_HEIGHTMAP: {
+ Dictionary dict = data;
+ ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights"
+ int heightmap_depth = dict["depth"];
+ int heightmap_width = dict["width"];
+
+ if (heightmap_depth >= 2 && heightmap_width >= 2) {
+ const Vector<real_t> &map_data = dict["heights"];
+
+ Vector2 heightmap_gridsize(heightmap_width - 1, heightmap_depth - 1);
+ Vector2 start = heightmap_gridsize * -0.5;
+
+ Vector<Vector3> vertex_array;
+ vertex_array.resize((heightmap_depth - 1) * (heightmap_width - 1) * 6);
+ int map_data_current_index = 0;
+
+ for (int d = 0; d < heightmap_depth - 1; d++) {
+ for (int w = 0; w < heightmap_width - 1; w++) {
+ if (map_data_current_index + 1 + heightmap_depth < map_data.size()) {
+ float top_left_height = map_data[map_data_current_index];
+ float top_right_height = map_data[map_data_current_index + 1];
+ float bottom_left_height = map_data[map_data_current_index + heightmap_depth];
+ float bottom_right_height = map_data[map_data_current_index + 1 + heightmap_depth];
+
+ Vector3 top_left = Vector3(start.x + w, top_left_height, start.y + d);
+ Vector3 top_right = Vector3(start.x + w + 1.0, top_right_height, start.y + d);
+ Vector3 bottom_left = Vector3(start.x + w, bottom_left_height, start.y + d + 1.0);
+ Vector3 bottom_right = Vector3(start.x + w + 1.0, bottom_right_height, start.y + d + 1.0);
+
+ vertex_array.push_back(top_right);
+ vertex_array.push_back(bottom_left);
+ vertex_array.push_back(top_left);
+ vertex_array.push_back(top_right);
+ vertex_array.push_back(bottom_right);
+ vertex_array.push_back(bottom_left);
+ }
+ map_data_current_index += 1;
+ }
+ }
+ if (vertex_array.size() > 0) {
+ _add_faces(vertex_array, shapes[i], p_vertices, p_indices);
+ }
+ }
+ } break;
default: {
WARN_PRINT("Unsupported collision shape type.");
} break;
@@ -378,14 +470,14 @@ void NavigationMeshGenerator::_parse_geometry(const Transform3D &p_navmesh_trans
}
}
-void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) {
+void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_navigation_mesh) {
Vector<Vector3> nav_vertices;
for (int i = 0; i < p_detail_mesh->nverts; i++) {
const float *v = &p_detail_mesh->verts[i * 3];
nav_vertices.push_back(Vector3(v[0], v[1], v[2]));
}
- p_nav_mesh->set_vertices(nav_vertices);
+ p_navigation_mesh->set_vertices(nav_vertices);
for (int i = 0; i < p_detail_mesh->nmeshes; i++) {
const unsigned int *m = &p_detail_mesh->meshes[i * 4];
@@ -400,13 +492,13 @@ void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(con
nav_indices.write[0] = ((int)(bverts + tris[j * 4 + 0]));
nav_indices.write[1] = ((int)(bverts + tris[j * 4 + 2]));
nav_indices.write[2] = ((int)(bverts + tris[j * 4 + 1]));
- p_nav_mesh->add_polygon(nav_indices);
+ p_navigation_mesh->add_polygon(nav_indices);
}
}
}
void NavigationMeshGenerator::_build_recast_navigation_mesh(
- Ref<NavigationMesh> p_nav_mesh,
+ Ref<NavigationMesh> p_navigation_mesh,
#ifdef TOOLS_ENABLED
EditorProgress *ep,
#endif
@@ -436,42 +528,42 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
rcConfig cfg;
memset(&cfg, 0, sizeof(cfg));
- cfg.cs = p_nav_mesh->get_cell_size();
- cfg.ch = p_nav_mesh->get_cell_height();
- cfg.walkableSlopeAngle = p_nav_mesh->get_agent_max_slope();
- cfg.walkableHeight = (int)Math::ceil(p_nav_mesh->get_agent_height() / cfg.ch);
- cfg.walkableClimb = (int)Math::floor(p_nav_mesh->get_agent_max_climb() / cfg.ch);
- cfg.walkableRadius = (int)Math::ceil(p_nav_mesh->get_agent_radius() / cfg.cs);
- cfg.maxEdgeLen = (int)(p_nav_mesh->get_edge_max_length() / p_nav_mesh->get_cell_size());
- cfg.maxSimplificationError = p_nav_mesh->get_edge_max_error();
- cfg.minRegionArea = (int)(p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size());
- cfg.mergeRegionArea = (int)(p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size());
- cfg.maxVertsPerPoly = (int)p_nav_mesh->get_verts_per_poly();
- cfg.detailSampleDist = MAX(p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance(), 0.1f);
- cfg.detailSampleMaxError = p_nav_mesh->get_cell_height() * p_nav_mesh->get_detail_sample_max_error();
-
- if (!Math::is_equal_approx((float)cfg.walkableHeight * cfg.ch, p_nav_mesh->get_agent_height())) {
+ cfg.cs = p_navigation_mesh->get_cell_size();
+ cfg.ch = p_navigation_mesh->get_cell_height();
+ cfg.walkableSlopeAngle = p_navigation_mesh->get_agent_max_slope();
+ cfg.walkableHeight = (int)Math::ceil(p_navigation_mesh->get_agent_height() / cfg.ch);
+ cfg.walkableClimb = (int)Math::floor(p_navigation_mesh->get_agent_max_climb() / cfg.ch);
+ cfg.walkableRadius = (int)Math::ceil(p_navigation_mesh->get_agent_radius() / cfg.cs);
+ cfg.maxEdgeLen = (int)(p_navigation_mesh->get_edge_max_length() / p_navigation_mesh->get_cell_size());
+ cfg.maxSimplificationError = p_navigation_mesh->get_edge_max_error();
+ cfg.minRegionArea = (int)(p_navigation_mesh->get_region_min_size() * p_navigation_mesh->get_region_min_size());
+ cfg.mergeRegionArea = (int)(p_navigation_mesh->get_region_merge_size() * p_navigation_mesh->get_region_merge_size());
+ cfg.maxVertsPerPoly = (int)p_navigation_mesh->get_vertices_per_polygon();
+ cfg.detailSampleDist = MAX(p_navigation_mesh->get_cell_size() * p_navigation_mesh->get_detail_sample_distance(), 0.1f);
+ cfg.detailSampleMaxError = p_navigation_mesh->get_cell_height() * p_navigation_mesh->get_detail_sample_max_error();
+
+ if (!Math::is_equal_approx((float)cfg.walkableHeight * cfg.ch, p_navigation_mesh->get_agent_height())) {
WARN_PRINT("Property agent_height is ceiled to cell_height voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.walkableClimb * cfg.ch, p_nav_mesh->get_agent_max_climb())) {
+ if (!Math::is_equal_approx((float)cfg.walkableClimb * cfg.ch, p_navigation_mesh->get_agent_max_climb())) {
WARN_PRINT("Property agent_max_climb is floored to cell_height voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.walkableRadius * cfg.cs, p_nav_mesh->get_agent_radius())) {
+ if (!Math::is_equal_approx((float)cfg.walkableRadius * cfg.cs, p_navigation_mesh->get_agent_radius())) {
WARN_PRINT("Property agent_radius is ceiled to cell_size voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.maxEdgeLen * cfg.cs, p_nav_mesh->get_edge_max_length())) {
+ if (!Math::is_equal_approx((float)cfg.maxEdgeLen * cfg.cs, p_navigation_mesh->get_edge_max_length())) {
WARN_PRINT("Property edge_max_length is rounded to cell_size voxel units and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.minRegionArea, p_nav_mesh->get_region_min_size() * p_nav_mesh->get_region_min_size())) {
+ if (!Math::is_equal_approx((float)cfg.minRegionArea, p_navigation_mesh->get_region_min_size() * p_navigation_mesh->get_region_min_size())) {
WARN_PRINT("Property region_min_size is converted to int and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.mergeRegionArea, p_nav_mesh->get_region_merge_size() * p_nav_mesh->get_region_merge_size())) {
+ if (!Math::is_equal_approx((float)cfg.mergeRegionArea, p_navigation_mesh->get_region_merge_size() * p_navigation_mesh->get_region_merge_size())) {
WARN_PRINT("Property region_merge_size is converted to int and loses precision.");
}
- if (!Math::is_equal_approx((float)cfg.maxVertsPerPoly, p_nav_mesh->get_verts_per_poly())) {
- WARN_PRINT("Property verts_per_poly is converted to int and loses precision.");
+ if (!Math::is_equal_approx((float)cfg.maxVertsPerPoly, p_navigation_mesh->get_vertices_per_polygon())) {
+ WARN_PRINT("Property vertices_per_polygon is converted to int and loses precision.");
}
- if (p_nav_mesh->get_cell_size() * p_nav_mesh->get_detail_sample_distance() < 0.1f) {
+ if (p_navigation_mesh->get_cell_size() * p_navigation_mesh->get_detail_sample_distance() < 0.1f) {
WARN_PRINT("Property detail_sample_distance is clamped to 0.1 world units as the resulting value from multiplying with cell_size is too low.");
}
@@ -482,13 +574,9 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
cfg.bmax[1] = bmax[1];
cfg.bmax[2] = bmax[2];
- AABB baking_aabb = p_nav_mesh->get_filter_baking_aabb();
-
- bool aabb_has_no_volume = baking_aabb.has_no_volume();
-
- if (!aabb_has_no_volume) {
- Vector3 baking_aabb_offset = p_nav_mesh->get_filter_baking_aabb_offset();
-
+ AABB baking_aabb = p_navigation_mesh->get_filter_baking_aabb();
+ if (baking_aabb.has_volume()) {
+ Vector3 baking_aabb_offset = p_navigation_mesh->get_filter_baking_aabb_offset();
cfg.bmin[0] = baking_aabb.position[0] + baking_aabb_offset.x;
cfg.bmin[1] = baking_aabb.position[1] + baking_aabb_offset.y;
cfg.bmin[2] = baking_aabb.position[2] + baking_aabb_offset.z;
@@ -539,13 +627,13 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
ERR_FAIL_COND(!rcRasterizeTriangles(&ctx, verts, nverts, tris, tri_areas.ptr(), ntris, *hf, cfg.walkableClimb));
}
- if (p_nav_mesh->get_filter_low_hanging_obstacles()) {
+ if (p_navigation_mesh->get_filter_low_hanging_obstacles()) {
rcFilterLowHangingWalkableObstacles(&ctx, cfg.walkableClimb, *hf);
}
- if (p_nav_mesh->get_filter_ledge_spans()) {
+ if (p_navigation_mesh->get_filter_ledge_spans()) {
rcFilterLedgeSpans(&ctx, cfg.walkableHeight, cfg.walkableClimb, *hf);
}
- if (p_nav_mesh->get_filter_walkable_low_height_spans()) {
+ if (p_navigation_mesh->get_filter_walkable_low_height_spans()) {
rcFilterWalkableLowHeightSpans(&ctx, cfg.walkableHeight, *hf);
}
@@ -577,10 +665,10 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
}
#endif
- if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
+ if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) {
ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf));
ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
- } else if (p_nav_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
+ } else if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) {
ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea));
} else {
ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea));
@@ -622,7 +710,7 @@ void NavigationMeshGenerator::_build_recast_navigation_mesh(
}
#endif
- _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_nav_mesh);
+ _convert_detail_mesh_to_native_navigation_mesh(detail_mesh, p_navigation_mesh);
rcFreePolyMesh(poly_mesh);
poly_mesh = nullptr;
@@ -641,8 +729,8 @@ NavigationMeshGenerator::NavigationMeshGenerator() {
NavigationMeshGenerator::~NavigationMeshGenerator() {
}
-void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node) {
- ERR_FAIL_COND_MSG(!p_nav_mesh.is_valid(), "Invalid navigation mesh.");
+void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node) {
+ ERR_FAIL_COND_MSG(!p_navigation_mesh.is_valid(), "Invalid navigation mesh.");
#ifdef TOOLS_ENABLED
EditorProgress *ep(nullptr);
@@ -667,17 +755,17 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
List<Node *> parse_nodes;
- if (p_nav_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_NAVMESH_CHILDREN) {
- parse_nodes.push_back(p_node);
+ if (p_navigation_mesh->get_source_geometry_mode() == NavigationMesh::SOURCE_GEOMETRY_ROOT_NODE_CHILDREN) {
+ parse_nodes.push_back(p_root_node);
} else {
- p_node->get_tree()->get_nodes_in_group(p_nav_mesh->get_source_group_name(), &parse_nodes);
+ p_root_node->get_tree()->get_nodes_in_group(p_navigation_mesh->get_source_group_name(), &parse_nodes);
}
- Transform3D navmesh_xform = Object::cast_to<Node3D>(p_node)->get_global_transform().affine_inverse();
+ Transform3D navmesh_xform = Object::cast_to<Node3D>(p_root_node)->get_global_transform().affine_inverse();
for (Node *E : parse_nodes) {
- NavigationMesh::ParsedGeometryType geometry_type = p_nav_mesh->get_parsed_geometry_type();
- uint32_t collision_mask = p_nav_mesh->get_collision_mask();
- bool recurse_children = p_nav_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
+ NavigationMesh::ParsedGeometryType geometry_type = p_navigation_mesh->get_parsed_geometry_type();
+ uint32_t collision_mask = p_navigation_mesh->get_collision_mask();
+ bool recurse_children = p_navigation_mesh->get_source_geometry_mode() != NavigationMesh::SOURCE_GEOMETRY_GROUPS_EXPLICIT;
_parse_geometry(navmesh_xform, E, vertices, indices, geometry_type, collision_mask, recurse_children);
}
@@ -689,7 +777,7 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
rcPolyMeshDetail *detail_mesh = nullptr;
_build_recast_navigation_mesh(
- p_nav_mesh,
+ p_navigation_mesh,
#ifdef TOOLS_ENABLED
ep,
#endif
@@ -728,16 +816,16 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
#endif
}
-void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_nav_mesh) {
- if (p_nav_mesh.is_valid()) {
- p_nav_mesh->clear_polygons();
- p_nav_mesh->set_vertices(Vector<Vector3>());
+void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_navigation_mesh) {
+ if (p_navigation_mesh.is_valid()) {
+ p_navigation_mesh->clear_polygons();
+ p_navigation_mesh->set_vertices(Vector<Vector3>());
}
}
void NavigationMeshGenerator::_bind_methods() {
- ClassDB::bind_method(D_METHOD("bake", "nav_mesh", "root_node"), &NavigationMeshGenerator::bake);
- ClassDB::bind_method(D_METHOD("clear", "nav_mesh"), &NavigationMeshGenerator::clear);
+ ClassDB::bind_method(D_METHOD("bake", "navigation_mesh", "root_node"), &NavigationMeshGenerator::bake);
+ ClassDB::bind_method(D_METHOD("clear", "navigation_mesh"), &NavigationMeshGenerator::clear);
}
#endif
diff --git a/modules/navigation/navigation_mesh_generator.h b/modules/navigation/navigation_mesh_generator.h
index 8cc1531b53..4399c422e2 100644
--- a/modules/navigation/navigation_mesh_generator.h
+++ b/modules/navigation/navigation_mesh_generator.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* navigation_mesh_generator.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* navigation_mesh_generator.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef NAVIGATION_MESH_GENERATOR_H
#define NAVIGATION_MESH_GENERATOR_H
@@ -55,9 +55,9 @@ protected:
static void _add_faces(const PackedVector3Array &p_faces, const Transform3D &p_xform, Vector<float> &p_vertices, Vector<int> &p_indices);
static void _parse_geometry(const Transform3D &p_navmesh_transform, Node *p_node, Vector<float> &p_vertices, Vector<int> &p_indices, NavigationMesh::ParsedGeometryType p_generate_from, uint32_t p_collision_mask, bool p_recurse_children);
- static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh);
+ static void _convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_navigation_mesh);
static void _build_recast_navigation_mesh(
- Ref<NavigationMesh> p_nav_mesh,
+ Ref<NavigationMesh> p_navigation_mesh,
#ifdef TOOLS_ENABLED
EditorProgress *ep,
#endif
@@ -75,8 +75,8 @@ public:
NavigationMeshGenerator();
~NavigationMeshGenerator();
- void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node);
- void clear(Ref<NavigationMesh> p_nav_mesh);
+ void bake(Ref<NavigationMesh> p_navigation_mesh, Node *p_root_node);
+ void clear(Ref<NavigationMesh> p_navigation_mesh);
};
#endif
diff --git a/modules/navigation/register_types.cpp b/modules/navigation/register_types.cpp
index 62ae2c7f02..6ba5e90c2e 100644
--- a/modules/navigation/register_types.cpp
+++ b/modules/navigation/register_types.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* register_types.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* register_types.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "register_types.h"
diff --git a/modules/navigation/register_types.h b/modules/navigation/register_types.h
index c4dbd19ed3..b07c3b9308 100644
--- a/modules/navigation/register_types.h
+++ b/modules/navigation/register_types.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* register_types.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* register_types.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef NAVIGATION_REGISTER_TYPES_H
#define NAVIGATION_REGISTER_TYPES_H
diff --git a/modules/navigation/rvo_agent.cpp b/modules/navigation/rvo_agent.cpp
index 4ec72ad43f..979ef0d917 100644
--- a/modules/navigation/rvo_agent.cpp
+++ b/modules/navigation/rvo_agent.cpp
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* rvo_agent.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* rvo_agent.cpp */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#include "rvo_agent.h"
diff --git a/modules/navigation/rvo_agent.h b/modules/navigation/rvo_agent.h
index 54baab404e..7b19907b2b 100644
--- a/modules/navigation/rvo_agent.h
+++ b/modules/navigation/rvo_agent.h
@@ -1,32 +1,32 @@
-/*************************************************************************/
-/* rvo_agent.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
+/**************************************************************************/
+/* rvo_agent.h */
+/**************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/**************************************************************************/
+/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
+/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/**************************************************************************/
#ifndef RVO_AGENT_H
#define RVO_AGENT_H