summaryrefslogtreecommitdiff
path: root/modules/gdnavigation
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdnavigation')
-rw-r--r--modules/gdnavigation/gd_navigation_server.cpp59
-rw-r--r--modules/gdnavigation/gd_navigation_server.h9
-rw-r--r--modules/gdnavigation/nav_map.cpp145
-rw-r--r--modules/gdnavigation/nav_map.h4
-rw-r--r--modules/gdnavigation/nav_region.cpp4
-rw-r--r--modules/gdnavigation/navigation_mesh_editor_plugin.cpp4
-rw-r--r--modules/gdnavigation/navigation_mesh_generator.cpp18
-rw-r--r--modules/gdnavigation/navigation_mesh_generator.h2
-rw-r--r--modules/gdnavigation/rvo_agent.cpp2
9 files changed, 218 insertions, 29 deletions
diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp
index 5bafa5507c..4129d1f65a 100644
--- a/modules/gdnavigation/gd_navigation_server.cpp
+++ b/modules/gdnavigation/gd_navigation_server.cpp
@@ -121,6 +121,7 @@ GdNavigationServer::GdNavigationServer() :
}
GdNavigationServer::~GdNavigationServer() {
+ flush_queries();
memdelete(operations_mutex);
memdelete(commands_mutex);
}
@@ -170,7 +171,7 @@ COMMAND_2(map_set_up, RID, p_map, Vector3, p_up) {
}
Vector3 GdNavigationServer::map_get_up(RID p_map) const {
- NavMap *map = map_owner.getornull(p_map);
+ const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == NULL, Vector3());
return map->get_up();
@@ -184,7 +185,7 @@ COMMAND_2(map_set_cell_size, RID, p_map, real_t, p_cell_size) {
}
real_t GdNavigationServer::map_get_cell_size(RID p_map) const {
- NavMap *map = map_owner.getornull(p_map);
+ const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == NULL, 0);
return map->get_cell_size();
@@ -198,19 +199,47 @@ COMMAND_2(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margi
}
real_t GdNavigationServer::map_get_edge_connection_margin(RID p_map) const {
- NavMap *map = map_owner.getornull(p_map);
+ const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == NULL, 0);
return map->get_edge_connection_margin();
}
Vector<Vector3> GdNavigationServer::map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const {
- NavMap *map = map_owner.getornull(p_map);
+ const NavMap *map = map_owner.getornull(p_map);
ERR_FAIL_COND_V(map == NULL, Vector<Vector3>());
return map->get_path(p_origin, p_destination, p_optimize);
}
+Vector3 GdNavigationServer::map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
+ const NavMap *map = map_owner.getornull(p_map);
+ ERR_FAIL_COND_V(map == NULL, Vector3());
+
+ return map->get_closest_point_to_segment(p_from, p_to, p_use_collision);
+}
+
+Vector3 GdNavigationServer::map_get_closest_point(RID p_map, const Vector3 &p_point) const {
+ const NavMap *map = map_owner.getornull(p_map);
+ ERR_FAIL_COND_V(map == NULL, Vector3());
+
+ return map->get_closest_point(p_point);
+}
+
+Vector3 GdNavigationServer::map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const {
+ const NavMap *map = map_owner.getornull(p_map);
+ ERR_FAIL_COND_V(map == NULL, Vector3());
+
+ return map->get_closest_point_normal(p_point);
+}
+
+RID GdNavigationServer::map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const {
+ const NavMap *map = map_owner.getornull(p_map);
+ ERR_FAIL_COND_V(map == NULL, RID());
+
+ return map->get_closest_point_owner(p_point);
+}
+
RID GdNavigationServer::region_create() const {
auto mut_this = const_cast<GdNavigationServer *>(this);
mut_this->operations_mutex->lock();
@@ -446,12 +475,9 @@ void GdNavigationServer::set_active(bool p_active) const {
mut_this->operations_mutex->unlock();
}
-void GdNavigationServer::step(real_t p_delta_time) {
- if (!active) {
- return;
- }
-
- // With c++ we can't be 100% sure this is called in single thread so use the mutex.
+void GdNavigationServer::flush_queries() {
+ // In c++ we can't be sure that this is performed in the main thread
+ // even with mutable functions.
commands_mutex->lock();
operations_mutex->lock();
for (size_t i(0); i < commands.size(); i++) {
@@ -461,13 +487,24 @@ void GdNavigationServer::step(real_t p_delta_time) {
commands.clear();
operations_mutex->unlock();
commands_mutex->unlock();
+}
- // These are internal operations so don't need to be shielded.
+void GdNavigationServer::process(real_t p_delta_time) {
+ flush_queries();
+
+ if (!active) {
+ return;
+ }
+
+ // In c++ we can't be sure that this is performed in the main thread
+ // even with mutable functions.
+ operations_mutex->lock();
for (int i(0); i < active_maps.size(); i++) {
active_maps[i]->sync();
active_maps[i]->step(p_delta_time);
active_maps[i]->dispatch_callbacks();
}
+ operations_mutex->unlock();
}
#undef COMMAND_1
diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h
index 564e9870a0..0400acf1a3 100644
--- a/modules/gdnavigation/gd_navigation_server.h
+++ b/modules/gdnavigation/gd_navigation_server.h
@@ -103,6 +103,11 @@ public:
virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const;
+ 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;
+ virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const;
+ virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const;
+ virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const;
+
virtual RID region_create() const;
COMMAND_2(region_set_map, RID, p_region, RID, p_map);
COMMAND_2(region_set_transform, RID, p_region, Transform, p_transform);
@@ -126,7 +131,9 @@ public:
COMMAND_1(free, RID, p_object);
virtual void set_active(bool p_active) const;
- virtual void step(real_t p_delta_time);
+
+ void flush_queries();
+ virtual void process(real_t p_delta_time);
};
#undef COMMAND_1
diff --git a/modules/gdnavigation/nav_map.cpp b/modules/gdnavigation/nav_map.cpp
index d1765f4da9..c3880f89b6 100644
--- a/modules/gdnavigation/nav_map.cpp
+++ b/modules/gdnavigation/nav_map.cpp
@@ -401,14 +401,155 @@ Vector<Vector3> NavMap::get_path(Vector3 p_origin, Vector3 p_destination, bool p
return Vector<Vector3>();
}
+Vector3 NavMap::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision) const {
+
+ bool use_collision = p_use_collision;
+ Vector3 closest_point;
+ real_t closest_point_d = 1e20;
+
+ // Find the initial poly and the end poly on this map.
+ for (size_t i(0); i < polygons.size(); i++) {
+ const gd::Polygon &p = polygons[i];
+
+ // For each point cast a face and check the distance to the segment
+ for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) {
+
+ const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos);
+ Vector3 inters;
+ if (f.intersects_segment(p_from, p_to, &inters)) {
+ const real_t d = closest_point_d = p_from.distance_to(inters);
+ if (use_collision == false) {
+ closest_point = inters;
+ use_collision = true;
+ closest_point_d = d;
+ } else if (closest_point_d > d) {
+
+ closest_point = inters;
+ closest_point_d = d;
+ }
+ }
+ }
+
+ if (use_collision == false) {
+
+ for (size_t point_id = 0; point_id < p.points.size(); point_id += 1) {
+
+ Vector3 a, b;
+
+ Geometry::get_closest_points_between_segments(
+ p_from,
+ p_to,
+ p.points[point_id].pos,
+ p.points[(point_id + 1) % p.points.size()].pos,
+ a,
+ b);
+
+ const real_t d = a.distance_to(b);
+ if (d < closest_point_d) {
+
+ closest_point_d = d;
+ closest_point = b;
+ }
+ }
+ }
+ }
+
+ return closest_point;
+}
+
+Vector3 NavMap::get_closest_point(const Vector3 &p_point) const {
+ // TODO this is really not optimal, please redesign the API to directly return all this data
+
+ Vector3 closest_point;
+ real_t closest_point_d = 1e20;
+
+ // Find the initial poly and the end poly on this map.
+ for (size_t i(0); i < polygons.size(); i++) {
+ const gd::Polygon &p = polygons[i];
+
+ // For each point cast a face and check the distance to the point
+ for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) {
+
+ const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos);
+ const Vector3 inters = f.get_closest_point_to(p_point);
+ const real_t d = inters.distance_to(p_point);
+ if (d < closest_point_d) {
+ closest_point = inters;
+ closest_point_d = d;
+ }
+ }
+ }
+
+ return closest_point;
+}
+
+Vector3 NavMap::get_closest_point_normal(const Vector3 &p_point) const {
+ // TODO this is really not optimal, please redesign the API to directly return all this data
+
+ Vector3 closest_point;
+ Vector3 closest_point_normal;
+ real_t closest_point_d = 1e20;
+
+ // Find the initial poly and the end poly on this map.
+ for (size_t i(0); i < polygons.size(); i++) {
+ const gd::Polygon &p = polygons[i];
+
+ // For each point cast a face and check the distance to the point
+ for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) {
+
+ const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos);
+ const Vector3 inters = f.get_closest_point_to(p_point);
+ const real_t d = inters.distance_to(p_point);
+ if (d < closest_point_d) {
+ closest_point = inters;
+ closest_point_normal = f.get_plane().normal;
+ closest_point_d = d;
+ }
+ }
+ }
+
+ return closest_point_normal;
+}
+
+RID NavMap::get_closest_point_owner(const Vector3 &p_point) const {
+ // TODO this is really not optimal, please redesign the API to directly return all this data
+
+ Vector3 closest_point;
+ RID closest_point_owner;
+ real_t closest_point_d = 1e20;
+
+ // Find the initial poly and the end poly on this map.
+ for (size_t i(0); i < polygons.size(); i++) {
+ const gd::Polygon &p = polygons[i];
+
+ // For each point cast a face and check the distance to the point
+ for (size_t point_id = 2; point_id < p.points.size(); point_id += 1) {
+
+ const Face3 f(p.points[point_id - 2].pos, p.points[point_id - 1].pos, p.points[point_id].pos);
+ const Vector3 inters = f.get_closest_point_to(p_point);
+ const real_t d = inters.distance_to(p_point);
+ if (d < closest_point_d) {
+ closest_point = inters;
+ closest_point_owner = p.owner->get_self();
+ closest_point_d = d;
+ }
+ }
+ }
+
+ return closest_point_owner;
+}
+
void NavMap::add_region(NavRegion *p_region) {
regions.push_back(p_region);
regenerate_links = true;
}
void NavMap::remove_region(NavRegion *p_region) {
- regions.push_back(p_region);
- regenerate_links = true;
+ std::vector<NavRegion *>::iterator it = std::find(regions.begin(), regions.end(), p_region);
+ if (it != regions.end()) {
+ regions.erase(it);
+ regenerate_links = true;
+ }
}
bool NavMap::has_agent(RvoAgent *agent) const {
diff --git a/modules/gdnavigation/nav_map.h b/modules/gdnavigation/nav_map.h
index 128a82580c..4543f00926 100644
--- a/modules/gdnavigation/nav_map.h
+++ b/modules/gdnavigation/nav_map.h
@@ -104,6 +104,10 @@ public:
gd::PointKey get_point_key(const Vector3 &p_pos) const;
Vector<Vector3> get_path(Vector3 p_origin, Vector3 p_destination, bool p_optimize) 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;
+ RID get_closest_point_owner(const Vector3 &p_point) const;
void add_region(NavRegion *p_region);
void remove_region(NavRegion *p_region);
diff --git a/modules/gdnavigation/nav_region.cpp b/modules/gdnavigation/nav_region.cpp
index d2d9d8b517..0215821305 100644
--- a/modules/gdnavigation/nav_region.cpp
+++ b/modules/gdnavigation/nav_region.cpp
@@ -78,12 +78,12 @@ void NavRegion::update_polygons() {
if (mesh.is_null())
return;
- PoolVector<Vector3> vertices = mesh->get_vertices();
+ Vector<Vector3> vertices = mesh->get_vertices();
int len = vertices.size();
if (len == 0)
return;
- PoolVector<Vector3>::Read vertices_r = vertices.read();
+ const Vector3 *vertices_r = vertices.ptr();
polygons.resize(mesh->get_polygon_count());
diff --git a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp
index 13c74d5706..28fe0bfd06 100644
--- a/modules/gdnavigation/navigation_mesh_editor_plugin.cpp
+++ b/modules/gdnavigation/navigation_mesh_editor_plugin.cpp
@@ -107,13 +107,13 @@ NavigationMeshEditor::NavigationMeshEditor() {
bake_hbox->add_child(button_bake);
button_bake->set_toggle_mode(true);
button_bake->set_text(TTR("Bake NavMesh"));
- button_bake->connect("pressed", this, "_bake_pressed");
+ button_bake->connect_compat("pressed", this, "_bake_pressed");
button_reset = memnew(ToolButton);
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->connect("pressed", this, "_clear_pressed");
+ button_reset->connect_compat("pressed", this, "_clear_pressed");
bake_info = memnew(Label);
bake_hbox->add_child(bake_info);
diff --git a/modules/gdnavigation/navigation_mesh_generator.cpp b/modules/gdnavigation/navigation_mesh_generator.cpp
index 04b86fabc5..7f8761dac8 100644
--- a/modules/gdnavigation/navigation_mesh_generator.cpp
+++ b/modules/gdnavigation/navigation_mesh_generator.cpp
@@ -90,13 +90,13 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform
Array a = p_mesh->surface_get_arrays(i);
- PoolVector<Vector3> mesh_vertices = a[Mesh::ARRAY_VERTEX];
- PoolVector<Vector3>::Read vr = mesh_vertices.read();
+ Vector<Vector3> mesh_vertices = a[Mesh::ARRAY_VERTEX];
+ const Vector3 *vr = mesh_vertices.ptr();
if (p_mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_INDEX) {
- PoolVector<int> mesh_indices = a[Mesh::ARRAY_INDEX];
- PoolVector<int>::Read ir = mesh_indices.read();
+ Vector<int> mesh_indices = a[Mesh::ARRAY_INDEX];
+ const int *ir = mesh_indices.ptr();
for (int j = 0; j < mesh_vertices.size(); j++) {
_add_vertex(p_xform.xform(vr[j]), p_verticies);
@@ -123,7 +123,7 @@ void NavigationMeshGenerator::_add_mesh(const Ref<Mesh> &p_mesh, const Transform
}
}
-void NavigationMeshGenerator::_add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
+void NavigationMeshGenerator::_add_faces(const PackedVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices) {
int face_count = p_faces.size() / 3;
int current_vertex_count = p_verticies.size() / 3;
@@ -227,7 +227,7 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform,
Error err = QuickHull::build(varr, md);
if (err == OK) {
- PoolVector3Array faces;
+ PackedVector3Array faces;
for (int j = 0; j < md.faces.size(); ++j) {
Geometry::MeshData::Face face = md.faces[j];
@@ -279,11 +279,11 @@ void NavigationMeshGenerator::_parse_geometry(Transform p_accumulated_transform,
void NavigationMeshGenerator::_convert_detail_mesh_to_native_navigation_mesh(const rcPolyMeshDetail *p_detail_mesh, Ref<NavigationMesh> p_nav_mesh) {
- PoolVector<Vector3> nav_vertices;
+ 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.append(Vector3(v[0], v[1], v[2]));
+ nav_vertices.push_back(Vector3(v[0], v[1], v[2]));
}
p_nav_mesh->set_vertices(nav_vertices);
@@ -562,7 +562,7 @@ void NavigationMeshGenerator::bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node)
void NavigationMeshGenerator::clear(Ref<NavigationMesh> p_nav_mesh) {
if (p_nav_mesh.is_valid()) {
p_nav_mesh->clear_polygons();
- p_nav_mesh->set_vertices(PoolVector<Vector3>());
+ p_nav_mesh->set_vertices(Vector<Vector3>());
}
}
diff --git a/modules/gdnavigation/navigation_mesh_generator.h b/modules/gdnavigation/navigation_mesh_generator.h
index 107dee75e2..27a56e1d7a 100644
--- a/modules/gdnavigation/navigation_mesh_generator.h
+++ b/modules/gdnavigation/navigation_mesh_generator.h
@@ -51,7 +51,7 @@ protected:
static void _add_vertex(const Vector3 &p_vec3, Vector<float> &p_verticies);
static void _add_mesh(const Ref<Mesh> &p_mesh, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
- static void _add_faces(const PoolVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
+ static void _add_faces(const PackedVector3Array &p_faces, const Transform &p_xform, Vector<float> &p_verticies, Vector<int> &p_indices);
static void _parse_geometry(Transform p_accumulated_transform, Node *p_node, Vector<float> &p_verticies, Vector<int> &p_indices, int 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);
diff --git a/modules/gdnavigation/rvo_agent.cpp b/modules/gdnavigation/rvo_agent.cpp
index 4d19bc15af..677e525bbf 100644
--- a/modules/gdnavigation/rvo_agent.cpp
+++ b/modules/gdnavigation/rvo_agent.cpp
@@ -74,7 +74,7 @@ void RvoAgent::dispatch_callback() {
callback.id = ObjectID();
}
- Variant::CallError responseCallError;
+ Callable::CallError responseCallError;
callback.new_velocity = Vector3(agent.newVelocity_.x(), agent.newVelocity_.y(), agent.newVelocity_.z());