Skip to content

Commit 085bc95

Browse files
committed
Add NavigationPolygon border_size property for tile baking
Adds NavigationPolygon border_size property for tile baking. Also adds baking Rect2 bounds.
1 parent b4e2a24 commit 085bc95

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

doc/classes/NavigationPolygon.xml

+10
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,16 @@
174174
<member name="agent_radius" type="float" setter="set_agent_radius" getter="get_agent_radius" default="10.0">
175175
The distance to erode/shrink the walkable surface when baking the navigation mesh.
176176
</member>
177+
<member name="baking_rect" type="Rect2" setter="set_baking_rect" getter="get_baking_rect" default="Rect2(0, 0, 0, 0)">
178+
If the baking [Rect2] has an area the navigation mesh baking will be restricted to its enclosing area.
179+
</member>
180+
<member name="baking_rect_offset" type="Vector2" setter="set_baking_rect_offset" getter="get_baking_rect_offset" default="Vector2(0, 0)">
181+
The position offset applied to the [member baking_rect] [Rect2].
182+
</member>
183+
<member name="border_size" type="float" setter="set_border_size" getter="get_border_size" default="0.0">
184+
The size of the non-navigable border around the bake bounding area defined by the [member baking_rect] [Rect2].
185+
In conjunction with the [member baking_rect] the border size can be used to bake tile aligned navigation meshes without the tile edges being shrunk by [member agent_radius].
186+
</member>
177187
<member name="cell_size" type="float" setter="set_cell_size" getter="get_cell_size" default="1.0">
178188
The cell size used to rasterize the navigation mesh vertices. Must match with the cell size on the navigation map.
179189
</member>

modules/navigation/nav_mesh_generator_2d.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -738,9 +738,13 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
738738
Paths64 traversable_polygon_paths;
739739
Paths64 obstruction_polygon_paths;
740740

741+
traversable_polygon_paths.reserve(outline_count + traversable_outlines.size());
742+
obstruction_polygon_paths.reserve(obstruction_outlines.size());
743+
741744
for (int i = 0; i < outline_count; i++) {
742745
const Vector<Vector2> &traversable_outline = p_navigation_mesh->get_outline(i);
743746
Path64 subject_path;
747+
subject_path.reserve(traversable_outline.size());
744748
for (const Vector2 &traversable_point : traversable_outline) {
745749
const Point64 &point = Point64(traversable_point.x, traversable_point.y);
746750
subject_path.push_back(point);
@@ -750,6 +754,7 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
750754

751755
for (const Vector<Vector2> &traversable_outline : traversable_outlines) {
752756
Path64 subject_path;
757+
subject_path.reserve(traversable_outline.size());
753758
for (const Vector2 &traversable_point : traversable_outline) {
754759
const Point64 &point = Point64(traversable_point.x, traversable_point.y);
755760
subject_path.push_back(point);
@@ -759,13 +764,30 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
759764

760765
for (const Vector<Vector2> &obstruction_outline : obstruction_outlines) {
761766
Path64 clip_path;
767+
clip_path.reserve(obstruction_outline.size());
762768
for (const Vector2 &obstruction_point : obstruction_outline) {
763769
const Point64 &point = Point64(obstruction_point.x, obstruction_point.y);
764770
clip_path.push_back(point);
765771
}
766772
obstruction_polygon_paths.push_back(clip_path);
767773
}
768774

775+
Rect2 baking_rect = p_navigation_mesh->get_baking_rect();
776+
if (baking_rect.has_area()) {
777+
Vector2 baking_rect_offset = p_navigation_mesh->get_baking_rect_offset();
778+
779+
const int rect_begin_x = baking_rect.position[0] + baking_rect_offset.x;
780+
const int rect_begin_y = baking_rect.position[1] + baking_rect_offset.y;
781+
const int rect_end_x = baking_rect.position[0] + baking_rect.size[0] + baking_rect_offset.x;
782+
const int rect_end_y = baking_rect.position[1] + baking_rect.size[1] + baking_rect_offset.y;
783+
784+
Rect64 clipper_rect = Rect64(rect_begin_x, rect_begin_y, rect_end_x, rect_end_y);
785+
RectClip rect_clip = RectClip(clipper_rect);
786+
787+
traversable_polygon_paths = rect_clip.Execute(traversable_polygon_paths);
788+
obstruction_polygon_paths = rect_clip.Execute(obstruction_polygon_paths);
789+
}
790+
769791
Paths64 path_solution;
770792

771793
// first merge all traversable polygons according to user specified fill rule
@@ -782,6 +804,21 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
782804
}
783805
//path_solution = RamerDouglasPeucker(path_solution, 0.025); //
784806

807+
real_t border_size = p_navigation_mesh->get_border_size();
808+
if (baking_rect.has_area() && border_size > 0.0) {
809+
Vector2 baking_rect_offset = p_navigation_mesh->get_baking_rect_offset();
810+
811+
const int rect_begin_x = baking_rect.position[0] + baking_rect_offset.x + border_size;
812+
const int rect_begin_y = baking_rect.position[1] + baking_rect_offset.y + border_size;
813+
const int rect_end_x = baking_rect.position[0] + baking_rect.size[0] + baking_rect_offset.x - border_size;
814+
const int rect_end_y = baking_rect.position[1] + baking_rect.size[1] + baking_rect_offset.y - border_size;
815+
816+
Rect64 clipper_rect = Rect64(rect_begin_x, rect_begin_y, rect_end_x, rect_end_y);
817+
RectClip rect_clip = RectClip(clipper_rect);
818+
819+
path_solution = rect_clip.Execute(path_solution);
820+
}
821+
785822
Vector<Vector<Vector2>> new_baked_outlines;
786823

787824
for (const Path64 &scaled_path : path_solution) {
@@ -799,6 +836,7 @@ void NavMeshGenerator2D::generator_bake_from_source_geometry_data(Ref<Navigation
799836
}
800837

801838
Paths64 polygon_paths;
839+
polygon_paths.reserve(new_baked_outlines.size());
802840

803841
for (const Vector<Vector2> &baked_outline : new_baked_outlines) {
804842
Path64 polygon_path;

scene/resources/navigation_polygon.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ real_t NavigationPolygon::get_cell_size() const {
347347
return cell_size;
348348
}
349349

350+
void NavigationPolygon::set_border_size(real_t p_value) {
351+
ERR_FAIL_COND(p_value < 0.0);
352+
border_size = p_value;
353+
}
354+
355+
real_t NavigationPolygon::get_border_size() const {
356+
return border_size;
357+
}
358+
350359
void NavigationPolygon::set_parsed_geometry_type(ParsedGeometryType p_geometry_type) {
351360
ERR_FAIL_INDEX(p_geometry_type, PARSED_GEOMETRY_MAX);
352361
parsed_geometry_type = p_geometry_type;
@@ -410,6 +419,24 @@ real_t NavigationPolygon::get_agent_radius() const {
410419
return agent_radius;
411420
}
412421

422+
void NavigationPolygon::set_baking_rect(const Rect2 &p_rect) {
423+
baking_rect = p_rect;
424+
emit_changed();
425+
}
426+
427+
Rect2 NavigationPolygon::get_baking_rect() const {
428+
return baking_rect;
429+
}
430+
431+
void NavigationPolygon::set_baking_rect_offset(const Vector2 &p_rect_offset) {
432+
baking_rect_offset = p_rect_offset;
433+
emit_changed();
434+
}
435+
436+
Vector2 NavigationPolygon::get_baking_rect_offset() const {
437+
return baking_rect_offset;
438+
}
439+
413440
void NavigationPolygon::_bind_methods() {
414441
ClassDB::bind_method(D_METHOD("set_vertices", "vertices"), &NavigationPolygon::set_vertices);
415442
ClassDB::bind_method(D_METHOD("get_vertices"), &NavigationPolygon::get_vertices);
@@ -440,6 +467,9 @@ void NavigationPolygon::_bind_methods() {
440467
ClassDB::bind_method(D_METHOD("set_cell_size", "cell_size"), &NavigationPolygon::set_cell_size);
441468
ClassDB::bind_method(D_METHOD("get_cell_size"), &NavigationPolygon::get_cell_size);
442469

470+
ClassDB::bind_method(D_METHOD("set_border_size", "border_size"), &NavigationPolygon::set_border_size);
471+
ClassDB::bind_method(D_METHOD("get_border_size"), &NavigationPolygon::get_border_size);
472+
443473
ClassDB::bind_method(D_METHOD("set_parsed_geometry_type", "geometry_type"), &NavigationPolygon::set_parsed_geometry_type);
444474
ClassDB::bind_method(D_METHOD("get_parsed_geometry_type"), &NavigationPolygon::get_parsed_geometry_type);
445475

@@ -458,6 +488,11 @@ void NavigationPolygon::_bind_methods() {
458488
ClassDB::bind_method(D_METHOD("set_agent_radius", "agent_radius"), &NavigationPolygon::set_agent_radius);
459489
ClassDB::bind_method(D_METHOD("get_agent_radius"), &NavigationPolygon::get_agent_radius);
460490

491+
ClassDB::bind_method(D_METHOD("set_baking_rect", "rect"), &NavigationPolygon::set_baking_rect);
492+
ClassDB::bind_method(D_METHOD("get_baking_rect"), &NavigationPolygon::get_baking_rect);
493+
ClassDB::bind_method(D_METHOD("set_baking_rect_offset", "rect_offset"), &NavigationPolygon::set_baking_rect_offset);
494+
ClassDB::bind_method(D_METHOD("get_baking_rect_offset"), &NavigationPolygon::get_baking_rect_offset);
495+
461496
ClassDB::bind_method(D_METHOD("clear"), &NavigationPolygon::clear);
462497

463498
ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "vertices", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_vertices", "get_vertices");
@@ -473,8 +508,12 @@ void NavigationPolygon::_bind_methods() {
473508
ADD_PROPERTY_DEFAULT("source_geometry_group_name", StringName("navigation_polygon_source_geometry_group"));
474509
ADD_GROUP("Cells", "");
475510
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cell_size", PROPERTY_HINT_RANGE, "1.0,50.0,1.0,or_greater,suffix:px"), "set_cell_size", "get_cell_size");
511+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "border_size", PROPERTY_HINT_RANGE, "0.0,500.0,1.0,or_greater,suffix:px"), "set_border_size", "get_border_size");
476512
ADD_GROUP("Agents", "agent_");
477513
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "agent_radius", PROPERTY_HINT_RANGE, "0.0,500.0,0.01,or_greater,suffix:px"), "set_agent_radius", "get_agent_radius");
514+
ADD_GROUP("Filters", "");
515+
ADD_PROPERTY(PropertyInfo(Variant::RECT2, "baking_rect"), "set_baking_rect", "get_baking_rect");
516+
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "baking_rect_offset"), "set_baking_rect_offset", "get_baking_rect_offset");
478517

479518
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_MESH_INSTANCES);
480519
BIND_ENUM_CONSTANT(PARSED_GEOMETRY_STATIC_COLLIDERS);

scene/resources/navigation_polygon.h

+13
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ class NavigationPolygon : public Resource {
5353
Ref<NavigationMesh> navigation_mesh;
5454

5555
real_t cell_size = 1.0f; // Must match ProjectSettings default 2D cell_size.
56+
real_t border_size = 0.0f;
57+
58+
Rect2 baking_rect;
59+
Vector2 baking_rect_offset;
5660

5761
protected:
5862
static void _bind_methods();
@@ -138,6 +142,15 @@ class NavigationPolygon : public Resource {
138142
void set_cell_size(real_t p_cell_size);
139143
real_t get_cell_size() const;
140144

145+
void set_border_size(real_t p_value);
146+
real_t get_border_size() const;
147+
148+
void set_baking_rect(const Rect2 &p_rect);
149+
Rect2 get_baking_rect() const;
150+
151+
void set_baking_rect_offset(const Vector2 &p_rect_offset);
152+
Vector2 get_baking_rect_offset() const;
153+
141154
void clear();
142155

143156
NavigationPolygon();

0 commit comments

Comments
 (0)