diff --git a/doc/classes/NavigationPolygon.xml b/doc/classes/NavigationPolygon.xml index eebdc817a74..68fbc059315 100644 --- a/doc/classes/NavigationPolygon.xml +++ b/doc/classes/NavigationPolygon.xml @@ -193,6 +193,9 @@ Determines which type of nodes will be parsed as geometry. See [enum ParsedGeometryType] for possible values. + + Partitioning algorithm for creating the navigation mesh polys. See [enum SamplePartitionType] for possible values. + The group name of nodes that should be parsed for baking source geometry. Only used when [member source_geometry_mode] is [constant SOURCE_GEOMETRY_GROUPS_WITH_CHILDREN] or [constant SOURCE_GEOMETRY_GROUPS_EXPLICIT]. @@ -202,6 +205,15 @@ + + Convex partitioning that yields navigation mesh with convex polygons. + + + Triangulation partitioning that yields navigation mesh with triangle polygons. + + + Represents the size of the [enum SamplePartitionType] enum. + Parses mesh instances as obstruction geometry. This includes [Polygon2D], [MeshInstance2D], [MultiMeshInstance2D], and [TileMap] nodes. Meshes are only parsed when they use a 2D vertices surface format. diff --git a/modules/navigation/2d/nav_mesh_generator_2d.cpp b/modules/navigation/2d/nav_mesh_generator_2d.cpp index 8c2fb424635..33b92f6266a 100644 --- a/modules/navigation/2d/nav_mesh_generator_2d.cpp +++ b/modules/navigation/2d/nav_mesh_generator_2d.cpp @@ -1042,10 +1042,32 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Refclear(); - return; + + NavigationPolygon::SamplePartitionType sample_partition_type = p_navigation_mesh->get_sample_partition_type(); + + switch (sample_partition_type) { + case NavigationPolygon::SamplePartitionType::SAMPLE_PARTITION_CONVEX_PARTITION: + if (tpart.ConvexPartition_HM(&tppl_in_polygon, &tppl_out_polygon) == 0) { + ERR_PRINT("NavigationPolygon polygon convex partition failed. Unable to create a valid navigation mesh polygon layout from provided source geometry."); + p_navigation_mesh->set_vertices(Vector()); + p_navigation_mesh->clear_polygons(); + return; + } + break; + case NavigationPolygon::SamplePartitionType::SAMPLE_PARTITION_TRIANGULATE: + if (tpart.Triangulate_EC(&tppl_in_polygon, &tppl_out_polygon) == 0) { + ERR_PRINT("NavigationPolygon polygon triangulation failed. Unable to create a valid navigation mesh polygon layout from provided source geometry."); + p_navigation_mesh->set_vertices(Vector()); + p_navigation_mesh->clear_polygons(); + return; + } + break; + default: { + ERR_PRINT("NavigationPolygon polygon partitioning failed. Unrecognized partition type."); + p_navigation_mesh->set_vertices(Vector()); + p_navigation_mesh->clear_polygons(); + return; + } } Vector new_vertices; diff --git a/scene/resources/2d/navigation_polygon.cpp b/scene/resources/2d/navigation_polygon.cpp index 4a290db86b5..4c0f824472c 100644 --- a/scene/resources/2d/navigation_polygon.cpp +++ b/scene/resources/2d/navigation_polygon.cpp @@ -400,6 +400,15 @@ real_t NavigationPolygon::get_border_size() const { return border_size; } +void NavigationPolygon::set_sample_partition_type(SamplePartitionType p_value) { + ERR_FAIL_INDEX(p_value, SAMPLE_PARTITION_MAX); + partition_type = p_value; +} + +NavigationPolygon::SamplePartitionType NavigationPolygon::get_sample_partition_type() const { + return partition_type; +} + void NavigationPolygon::set_parsed_geometry_type(ParsedGeometryType p_geometry_type) { ERR_FAIL_INDEX(p_geometry_type, PARSED_GEOMETRY_MAX); parsed_geometry_type = p_geometry_type; @@ -514,6 +523,9 @@ void NavigationPolygon::_bind_methods() { ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &NavigationPolygon::set_border_size); ClassDB::bind_method(D_METHOD("get_border_size"), &NavigationPolygon::get_border_size); + ClassDB::bind_method(D_METHOD("set_sample_partition_type", "sample_partition_type"), &NavigationPolygon::set_sample_partition_type); + ClassDB::bind_method(D_METHOD("get_sample_partition_type"), &NavigationPolygon::get_sample_partition_type); + ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationPolygon::set_parsed_geometry_type); ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationPolygon::get_parsed_geometry_type); @@ -543,6 +555,8 @@ void NavigationPolygon::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "polygons", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_polygons", "_get_polygons"); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "outlines", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_outlines", "_get_outlines"); + ADD_GROUP("Sampling", "sample_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "sample_partition_type", PROPERTY_HINT_ENUM, "Convex Partition,Triangulate"), "set_sample_partition_type", "get_sample_partition_type"); ADD_GROUP("Geometry", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_geometry_type", PROPERTY_HINT_ENUM, "Mesh Instances,Static Colliders,Meshes and Static Colliders"), "set_parsed_geometry_type", "get_parsed_geometry_type"); ADD_PROPERTY(PropertyInfo(Variant::INT, "parsed_collision_mask", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_parsed_collision_mask", "get_parsed_collision_mask"); @@ -559,6 +573,10 @@ void NavigationPolygon::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::RECT2, "baking_rect"), "set_baking_rect", "get_baking_rect"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "baking_rect_offset"), "set_baking_rect_offset", "get_baking_rect_offset"); + BIND_ENUM_CONSTANT(SAMPLE_PARTITION_CONVEX_PARTITION); + BIND_ENUM_CONSTANT(SAMPLE_PARTITION_TRIANGULATE); + BIND_ENUM_CONSTANT(SAMPLE_PARTITION_MAX); + BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES); BIND_ENUM_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS); BIND_ENUM_CONSTANT(PARSED_GEOMETRY_BOTH); diff --git a/scene/resources/2d/navigation_polygon.h b/scene/resources/2d/navigation_polygon.h index 4e99660b0ee..9125eb41982 100644 --- a/scene/resources/2d/navigation_polygon.h +++ b/scene/resources/2d/navigation_polygon.h @@ -74,6 +74,11 @@ public: Rect2 _edit_get_rect() const; bool _edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const; #endif + enum SamplePartitionType { + SAMPLE_PARTITION_CONVEX_PARTITION = 0, + SAMPLE_PARTITION_TRIANGULATE, + SAMPLE_PARTITION_MAX + }; enum ParsedGeometryType { PARSED_GEOMETRY_MESH_INSTANCES = 0, @@ -91,6 +96,7 @@ public: real_t agent_radius = 10.0f; + SamplePartitionType partition_type = SAMPLE_PARTITION_CONVEX_PARTITION; ParsedGeometryType parsed_geometry_type = PARSED_GEOMETRY_BOTH; uint32_t parsed_collision_mask = 0xFFFFFFFF; @@ -120,6 +126,9 @@ public: Vector get_polygon(int p_idx); void clear_polygons(); + void set_sample_partition_type(SamplePartitionType p_value); + SamplePartitionType get_sample_partition_type() const; + void set_parsed_geometry_type(ParsedGeometryType p_geometry_type); ParsedGeometryType get_parsed_geometry_type() const; @@ -161,6 +170,7 @@ public: ~NavigationPolygon() {} }; +VARIANT_ENUM_CAST(NavigationPolygon::SamplePartitionType); VARIANT_ENUM_CAST(NavigationPolygon::ParsedGeometryType); VARIANT_ENUM_CAST(NavigationPolygon::SourceGeometryMode);