diff options
Diffstat (limited to 'modules/navigation/2d')
-rw-r--r-- | modules/navigation/2d/godot_navigation_server_2d.cpp | 5 | ||||
-rw-r--r-- | modules/navigation/2d/godot_navigation_server_2d.h | 1 | ||||
-rw-r--r-- | modules/navigation/2d/nav_mesh_generator_2d.cpp | 195 |
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++) { |