diff --git a/doc/classes/NavigationMesh.xml b/doc/classes/NavigationMesh.xml index a76e739c23b6..8b2265baad52 100644 --- a/doc/classes/NavigationMesh.xml +++ b/doc/classes/NavigationMesh.xml @@ -96,6 +96,11 @@ The distance to erode/shrink the walkable area of the heightfield away from obstructions. [b]Note:[/b] While baking, this value will be rounded up to the nearest multiple of [member cell_size]. + + The size of the non-navigable border around the bake bounding area. + In conjunction with the [member filter_baking_aabb] and a [member edge_max_error] value at [code]1.0[/code] or below the border size can be used to bake tile aligned navigation meshes without the tile edges being shrunk by [member agent_radius]. + [b]Note:[/b] While baking and not zero, this value will be rounded up to the nearest multiple of [member cell_size]. + The cell height used to rasterize the navigation mesh vertices on the Y axis. Must match with the cell height on the navigation map. diff --git a/modules/navigation/nav_mesh_generator_3d.cpp b/modules/navigation/nav_mesh_generator_3d.cpp index 8719801c72d4..df93edaaeab8 100644 --- a/modules/navigation/nav_mesh_generator_3d.cpp +++ b/modules/navigation/nav_mesh_generator_3d.cpp @@ -625,6 +625,9 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Refget_cell_size(); cfg.ch = p_navigation_mesh->get_cell_height(); + if (p_navigation_mesh->get_border_size() > 0.0) { + cfg.borderSize = (int)Math::ceil(p_navigation_mesh->get_border_size() / cfg.cs); + } 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); @@ -637,6 +640,9 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Refget_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 (p_navigation_mesh->get_border_size() > 0.0 && !Math::is_equal_approx(p_navigation_mesh->get_cell_size(), p_navigation_mesh->get_border_size())) { + WARN_PRINT("Property border_size is ceiled to cell_size voxel units and loses precision."); + } 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."); } @@ -738,11 +744,11 @@ void NavMeshGenerator3D::generator_bake_from_source_geometry_data(Refget_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_WATERSHED) { ERR_FAIL_COND(!rcBuildDistanceField(&ctx, *chf)); - ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea)); + ERR_FAIL_COND(!rcBuildRegions(&ctx, *chf, cfg.borderSize, cfg.minRegionArea, cfg.mergeRegionArea)); } else if (p_navigation_mesh->get_sample_partition_type() == NavigationMesh::SAMPLE_PARTITION_MONOTONE) { - ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, 0, cfg.minRegionArea, cfg.mergeRegionArea)); + ERR_FAIL_COND(!rcBuildRegionsMonotone(&ctx, *chf, cfg.borderSize, cfg.minRegionArea, cfg.mergeRegionArea)); } else { - ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, 0, cfg.minRegionArea)); + ERR_FAIL_COND(!rcBuildLayerRegions(&ctx, *chf, cfg.borderSize, cfg.minRegionArea)); } bake_state = "Creating contours..."; // step #8 diff --git a/scene/resources/navigation_mesh.cpp b/scene/resources/navigation_mesh.cpp index dd2e7ef26813..a7ce15c5ad18 100644 --- a/scene/resources/navigation_mesh.cpp +++ b/scene/resources/navigation_mesh.cpp @@ -153,6 +153,15 @@ float NavigationMesh::get_cell_height() const { return cell_height; } +void NavigationMesh::set_border_size(float p_value) { + ERR_FAIL_COND(p_value < 0); + border_size = p_value; +} + +float NavigationMesh::get_border_size() const { + return border_size; +} + void NavigationMesh::set_agent_height(float p_value) { ERR_FAIL_COND(p_value < 0); agent_height = p_value; @@ -464,6 +473,9 @@ void NavigationMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_cell_height", "cell_height"), &NavigationMesh::set_cell_height); ClassDB::bind_method(D_METHOD("get_cell_height"), &NavigationMesh::get_cell_height); + ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &NavigationMesh::set_border_size); + ClassDB::bind_method(D_METHOD("get_border_size"), &NavigationMesh::get_border_size); + ClassDB::bind_method(D_METHOD("set_agent_height", "agent_height"), &NavigationMesh::set_agent_height); ClassDB::bind_method(D_METHOD("get_agent_height"), &NavigationMesh::get_agent_height); @@ -537,9 +549,10 @@ void NavigationMesh::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "geometry_source_geometry_mode", PROPERTY_HINT_ENUM, "Root Node Children,Group With Children,Group Explicit"), "set_source_geometry_mode", "get_source_geometry_mode"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "geometry_source_group_name"), "set_source_group_name", "get_source_group_name"); ADD_PROPERTY_DEFAULT("geometry_source_group_name", StringName("navigation_mesh_source_group")); - ADD_GROUP("Cells", "cell_"); + ADD_GROUP("Cells", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_size", "get_cell_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_height", PROPERTY_HINT_RANGE, "0.01,500.0,0.01,or_greater,suffix:m"), "set_cell_height", "get_cell_height"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_size", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:m"), "set_border_size", "get_border_size"); ADD_GROUP("Agents", "agent_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_height", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:m"), "set_agent_height", "get_agent_height"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_radius", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:m"), "set_agent_radius", "get_agent_radius"); diff --git a/scene/resources/navigation_mesh.h b/scene/resources/navigation_mesh.h index cb8880eb94ff..1daebdda7f41 100644 --- a/scene/resources/navigation_mesh.h +++ b/scene/resources/navigation_mesh.h @@ -80,6 +80,7 @@ class NavigationMesh : public Resource { protected: float cell_size = 0.25f; // Must match ProjectSettings default 3D cell_size and NavigationServer NavMap cell_size. float cell_height = 0.25f; // Must match ProjectSettings default 3D cell_height and NavigationServer NavMap cell_height. + float border_size = 0.0f; float agent_height = 1.5f; float agent_radius = 0.5f; float agent_max_climb = 0.25f; @@ -131,6 +132,9 @@ class NavigationMesh : public Resource { void set_cell_height(float p_value); float get_cell_height() const; + void set_border_size(float p_value); + float get_border_size() const; + void set_agent_height(float p_value); float get_agent_height() const;