summaryrefslogtreecommitdiffstats
path: root/modules/navigation/2d
diff options
context:
space:
mode:
Diffstat (limited to 'modules/navigation/2d')
-rw-r--r--modules/navigation/2d/godot_navigation_server_2d.cpp5
-rw-r--r--modules/navigation/2d/godot_navigation_server_2d.h1
-rw-r--r--modules/navigation/2d/nav_mesh_generator_2d.cpp195
3 files changed, 77 insertions, 124 deletions
diff --git a/modules/navigation/2d/godot_navigation_server_2d.cpp b/modules/navigation/2d/godot_navigation_server_2d.cpp
index bf69adc14c..2af125d434 100644
--- a/modules/navigation/2d/godot_navigation_server_2d.cpp
+++ b/modules/navigation/2d/godot_navigation_server_2d.cpp
@@ -318,6 +318,11 @@ int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid);
Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
+Vector2 GodotNavigationServer2D::region_get_closest_point(RID p_region, const Vector2 &p_point) const {
+ Vector3 result = NavigationServer3D::get_singleton()->region_get_closest_point(p_region, v2_to_v3(p_point));
+ return v3_to_v2(result);
+}
+
Vector2 GodotNavigationServer2D::region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const {
Vector3 result = NavigationServer3D::get_singleton()->region_get_random_point(p_region, p_navigation_layers, p_uniformly);
return v3_to_v2(result);
diff --git a/modules/navigation/2d/godot_navigation_server_2d.h b/modules/navigation/2d/godot_navigation_server_2d.h
index ea77fa5e6e..1579ca2907 100644
--- a/modules/navigation/2d/godot_navigation_server_2d.h
+++ b/modules/navigation/2d/godot_navigation_server_2d.h
@@ -101,6 +101,7 @@ public:
virtual int region_get_connections_count(RID p_region) const override;
virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const override;
virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const override;
+ virtual Vector2 region_get_closest_point(RID p_region, const Vector2 &p_point) const override;
virtual Vector2 region_get_random_point(RID p_region, uint32_t p_navigation_layers, bool p_uniformly) const override;
virtual RID link_create() override;
diff --git a/modules/navigation/2d/nav_mesh_generator_2d.cpp b/modules/navigation/2d/nav_mesh_generator_2d.cpp
index 78983187c7..2339936ec4 100644
--- a/modules/navigation/2d/nav_mesh_generator_2d.cpp
+++ b/modules/navigation/2d/nav_mesh_generator_2d.cpp
@@ -755,21 +755,19 @@ void NavMeshGenerator2D::generator_parse_source_geometry_data(Ref<NavigationPoly
for (Node *E : parse_nodes) {
generator_parse_geometry_node(p_navigation_mesh, p_source_geometry_data, E, recurse_children);
}
-};
+}
static void generator_recursive_process_polytree_items(List<TPPLPoly> &p_tppl_in_polygon, const Clipper2Lib::PolyPathD *p_polypath_item) {
using namespace Clipper2Lib;
- Vector<Vector2> polygon_vertices;
+ TPPLPoly tp;
+ int size = p_polypath_item->Polygon().size();
+ tp.Init(size);
+ int j = 0;
for (const PointD &polypath_point : p_polypath_item->Polygon()) {
- polygon_vertices.push_back(Vector2(static_cast<real_t>(polypath_point.x), static_cast<real_t>(polypath_point.y)));
- }
-
- TPPLPoly tp;
- tp.Init(polygon_vertices.size());
- for (int j = 0; j < polygon_vertices.size(); j++) {
- tp[j] = polygon_vertices[j];
+ tp[j] = Vector2(static_cast<real_t>(polypath_point.x), static_cast<real_t>(polypath_point.y));
+ ++j;
}
if (p_polypath_item->IsHole()) {
@@ -842,87 +840,79 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
return;
}
- if (p_navigation_mesh->get_outline_count() == 0 && !p_source_geometry_data->has_data()) {
- return;
- }
-
- int outline_count = p_navigation_mesh->get_outline_count();
-
- Vector<Vector<Vector2>> traversable_outlines;
- Vector<Vector<Vector2>> obstruction_outlines;
- Vector<NavigationMeshSourceGeometryData2D::ProjectedObstruction> projected_obstructions;
-
- p_source_geometry_data->get_data(
- traversable_outlines,
- obstruction_outlines,
- projected_obstructions);
-
- if (outline_count == 0 && traversable_outlines.size() == 0) {
- return;
- }
-
using namespace Clipper2Lib;
-
PathsD traversable_polygon_paths;
PathsD obstruction_polygon_paths;
+ int obstruction_polygon_path_size = 0;
+ {
+ RWLockRead read_lock(p_source_geometry_data->geometry_rwlock);
- traversable_polygon_paths.reserve(outline_count + traversable_outlines.size());
- obstruction_polygon_paths.reserve(obstruction_outlines.size());
+ const Vector<Vector<Vector2>> &traversable_outlines = p_source_geometry_data->traversable_outlines;
+ int outline_count = p_navigation_mesh->get_outline_count();
- for (int i = 0; i < outline_count; i++) {
- const Vector<Vector2> &traversable_outline = p_navigation_mesh->get_outline(i);
- PathD subject_path;
- subject_path.reserve(traversable_outline.size());
- for (const Vector2 &traversable_point : traversable_outline) {
- const PointD &point = PointD(traversable_point.x, traversable_point.y);
- subject_path.push_back(point);
+ if (outline_count == 0 && (!p_source_geometry_data->has_data() || (traversable_outlines.is_empty()))) {
+ return;
}
- traversable_polygon_paths.push_back(subject_path);
- }
- for (const Vector<Vector2> &traversable_outline : traversable_outlines) {
- PathD subject_path;
- subject_path.reserve(traversable_outline.size());
- for (const Vector2 &traversable_point : traversable_outline) {
- const PointD &point = PointD(traversable_point.x, traversable_point.y);
- subject_path.push_back(point);
- }
- traversable_polygon_paths.push_back(subject_path);
- }
+ const Vector<Vector<Vector2>> &obstruction_outlines = p_source_geometry_data->obstruction_outlines;
+ const Vector<NavigationMeshSourceGeometryData2D::ProjectedObstruction> &projected_obstructions = p_source_geometry_data->_projected_obstructions;
- for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) {
- PathD clip_path;
- clip_path.reserve(obstruction_outline.size());
- for (const Vector2 &obstruction_point : obstruction_outline) {
- const PointD &point = PointD(obstruction_point.x, obstruction_point.y);
- clip_path.push_back(point);
+ traversable_polygon_paths.reserve(outline_count + traversable_outlines.size());
+ obstruction_polygon_paths.reserve(obstruction_outlines.size());
+
+ for (int i = 0; i < outline_count; i++) {
+ const Vector<Vector2> &traversable_outline = p_navigation_mesh->get_outline(i);
+ PathD subject_path;
+ subject_path.reserve(traversable_outline.size());
+ for (const Vector2 &traversable_point : traversable_outline) {
+ subject_path.emplace_back(traversable_point.x, traversable_point.y);
+ }
+ traversable_polygon_paths.push_back(std::move(subject_path));
}
- obstruction_polygon_paths.push_back(clip_path);
- }
- if (!projected_obstructions.is_empty()) {
- for (const NavigationMeshSourceGeometryData2D::ProjectedObstruction &projected_obstruction : projected_obstructions) {
- if (projected_obstruction.carve) {
- continue;
+ for (const Vector<Vector2> &traversable_outline : traversable_outlines) {
+ PathD subject_path;
+ subject_path.reserve(traversable_outline.size());
+ for (const Vector2 &traversable_point : traversable_outline) {
+ subject_path.emplace_back(traversable_point.x, traversable_point.y);
}
- if (projected_obstruction.vertices.is_empty() || projected_obstruction.vertices.size() % 2 != 0) {
- continue;
+ traversable_polygon_paths.push_back(std::move(subject_path));
+ }
+
+ if (!projected_obstructions.is_empty()) {
+ for (const NavigationMeshSourceGeometryData2D::ProjectedObstruction &projected_obstruction : projected_obstructions) {
+ if (projected_obstruction.carve) {
+ continue;
+ }
+ if (projected_obstruction.vertices.is_empty() || projected_obstruction.vertices.size() % 2 != 0) {
+ continue;
+ }
+
+ PathD clip_path;
+ clip_path.reserve(projected_obstruction.vertices.size() / 2);
+ for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) {
+ clip_path.emplace_back(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]);
+ }
+ if (!IsPositive(clip_path)) {
+ std::reverse(clip_path.begin(), clip_path.end());
+ }
+ obstruction_polygon_paths.push_back(std::move(clip_path));
}
+ }
+ obstruction_polygon_path_size = obstruction_polygon_paths.size();
+ for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) {
PathD clip_path;
- clip_path.reserve(projected_obstruction.vertices.size() / 2);
- for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) {
- const PointD &point = PointD(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]);
- clip_path.push_back(point);
+ clip_path.reserve(obstruction_outline.size());
+ for (const Vector2 &obstruction_point : obstruction_outline) {
+ clip_path.emplace_back(obstruction_point.x, obstruction_point.y);
}
- if (!IsPositive(clip_path)) {
- std::reverse(clip_path.begin(), clip_path.end());
- }
- obstruction_polygon_paths.push_back(clip_path);
+ obstruction_polygon_paths.push_back(std::move(clip_path));
}
}
Rect2 baking_rect = p_navigation_mesh->get_baking_rect();
+ PathsD area_obstruction_polygon_paths;
if (baking_rect.has_area()) {
Vector2 baking_rect_offset = p_navigation_mesh->get_baking_rect_offset();
@@ -934,48 +924,27 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
RectD clipper_rect = RectD(rect_begin_x, rect_begin_y, rect_end_x, rect_end_y);
traversable_polygon_paths = RectClip(clipper_rect, traversable_polygon_paths);
- obstruction_polygon_paths = RectClip(clipper_rect, obstruction_polygon_paths);
+ area_obstruction_polygon_paths = RectClip(clipper_rect, obstruction_polygon_paths);
+ } else {
+ area_obstruction_polygon_paths = obstruction_polygon_paths;
}
- PathsD path_solution;
-
// first merge all traversable polygons according to user specified fill rule
PathsD dummy_clip_path;
traversable_polygon_paths = Union(traversable_polygon_paths, dummy_clip_path, FillRule::NonZero);
// merge all obstruction polygons, don't allow holes for what is considered "solid" 2D geometry
- obstruction_polygon_paths = Union(obstruction_polygon_paths, dummy_clip_path, FillRule::NonZero);
+ area_obstruction_polygon_paths = Union(area_obstruction_polygon_paths, dummy_clip_path, FillRule::NonZero);
- path_solution = Difference(traversable_polygon_paths, obstruction_polygon_paths, FillRule::NonZero);
+ PathsD path_solution = Difference(traversable_polygon_paths, area_obstruction_polygon_paths, FillRule::NonZero);
real_t agent_radius_offset = p_navigation_mesh->get_agent_radius();
if (agent_radius_offset > 0.0) {
path_solution = InflatePaths(path_solution, -agent_radius_offset, JoinType::Miter, EndType::Polygon);
}
- if (!projected_obstructions.is_empty()) {
- obstruction_polygon_paths.resize(0);
- for (const NavigationMeshSourceGeometryData2D::ProjectedObstruction &projected_obstruction : projected_obstructions) {
- if (!projected_obstruction.carve) {
- continue;
- }
- if (projected_obstruction.vertices.is_empty() || projected_obstruction.vertices.size() % 2 != 0) {
- continue;
- }
-
- PathD clip_path;
- clip_path.reserve(projected_obstruction.vertices.size() / 2);
- for (int i = 0; i < projected_obstruction.vertices.size() / 2; i++) {
- const PointD &point = PointD(projected_obstruction.vertices[i * 2], projected_obstruction.vertices[i * 2 + 1]);
- clip_path.push_back(point);
- }
- if (!IsPositive(clip_path)) {
- std::reverse(clip_path.begin(), clip_path.end());
- }
- obstruction_polygon_paths.push_back(clip_path);
- }
- if (obstruction_polygon_paths.size() > 0) {
- path_solution = Difference(path_solution, obstruction_polygon_paths, FillRule::NonZero);
- }
+ if (obstruction_polygon_path_size > 0) {
+ obstruction_polygon_paths.resize(obstruction_polygon_path_size);
+ path_solution = Difference(path_solution, obstruction_polygon_paths, FillRule::NonZero);
}
//path_solution = RamerDouglasPeucker(path_solution, 0.025); //
@@ -994,33 +963,11 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
path_solution = RectClip(clipper_rect, path_solution);
}
- Vector<Vector<Vector2>> new_baked_outlines;
-
- for (const PathD &scaled_path : path_solution) {
- Vector<Vector2> polypath;
- for (const PointD &scaled_point : scaled_path) {
- polypath.push_back(Vector2(static_cast<real_t>(scaled_point.x), static_cast<real_t>(scaled_point.y)));
- }
- new_baked_outlines.push_back(polypath);
- }
-
- if (new_baked_outlines.size() == 0) {
+ if (path_solution.size() == 0) {
p_navigation_mesh->clear();
return;
}
- PathsD polygon_paths;
- polygon_paths.reserve(new_baked_outlines.size());
-
- for (const Vector<Vector2> &baked_outline : new_baked_outlines) {
- PathD polygon_path;
- for (const Vector2 &baked_outline_point : baked_outline) {
- const PointD &point = PointD(baked_outline_point.x, baked_outline_point.y);
- polygon_path.push_back(point);
- }
- polygon_paths.push_back(polygon_path);
- }
-
ClipType clipper_cliptype = ClipType::Union;
List<TPPLPoly> tppl_in_polygon, tppl_out_polygon;
@@ -1028,7 +975,7 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
PolyTreeD polytree;
ClipperD clipper_D;
- clipper_D.AddSubject(polygon_paths);
+ clipper_D.AddSubject(path_solution);
clipper_D.Execute(clipper_cliptype, FillRule::NonZero, polytree);
for (size_t i = 0; i < polytree.Count(); i++) {