Skip to content

Commit 23ea3ab

Browse files
committed
Improve NavigationObstacle2D debug visuals
Improves NavigationObstacle2D debug visuals by aligning them closer to their aleady improved 3D counterpart.
1 parent 89001f9 commit 23ea3ab

5 files changed

+85
-50
lines changed

editor/plugins/navigation_obstacle_3d_editor_plugin.cpp

+3-11
Original file line numberDiff line numberDiff line change
@@ -103,20 +103,12 @@ void NavigationObstacle3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
103103
lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(Vector3(point.x, height, point.z));
104104
}
105105

106-
Vector<Vector2> polygon_2d_vertices;
107-
polygon_2d_vertices.resize(vertex_count);
108-
for (int i = 0; i < vertex_count; i++) {
109-
const Vector3 &vert = vertices[i];
110-
polygon_2d_vertices.write[i] = Vector2(vert.x, vert.z);
111-
}
112-
Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(polygon_2d_vertices);
113-
114106
NavigationServer3D *ns3d = NavigationServer3D::get_singleton();
115107

116-
if (triangulated_polygon_2d_indices.is_empty()) {
117-
p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material());
118-
} else {
108+
if (obstacle->are_vertices_valid()) {
119109
p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushout_edge_material());
110+
} else {
111+
p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material());
120112
}
121113
p_gizmo->add_collision_segments(lines_mesh_vertices);
122114

scene/2d/navigation_obstacle_2d.cpp

+54-27
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ NavigationObstacle2D::NavigationObstacle2D() {
187187

188188
#ifdef DEBUG_ENABLED
189189
debug_canvas_item = RenderingServer::get_singleton()->canvas_item_create();
190+
debug_mesh_rid = RenderingServer::get_singleton()->mesh_create();
190191
#endif // DEBUG_ENABLED
191192
}
192193

@@ -197,6 +198,10 @@ NavigationObstacle2D::~NavigationObstacle2D() {
197198
obstacle = RID();
198199

199200
#ifdef DEBUG_ENABLED
201+
if (debug_mesh_rid.is_valid()) {
202+
RenderingServer::get_singleton()->free(debug_mesh_rid);
203+
debug_mesh_rid = RID();
204+
}
200205
if (debug_canvas_item.is_valid()) {
201206
RenderingServer::get_singleton()->free(debug_canvas_item);
202207
debug_canvas_item = RID();
@@ -206,6 +211,10 @@ NavigationObstacle2D::~NavigationObstacle2D() {
206211

207212
void NavigationObstacle2D::set_vertices(const Vector<Vector2> &p_vertices) {
208213
vertices = p_vertices;
214+
215+
vertices_are_clockwise = !Geometry2D::is_polygon_clockwise(vertices); // Geometry2D is inverted.
216+
vertices_are_valid = !Geometry2D::triangulate_polygon(vertices).is_empty();
217+
209218
const Transform2D node_transform = is_inside_tree() ? get_global_transform() : Transform2D();
210219
NavigationServer2D::get_singleton()->obstacle_set_vertices(obstacle, node_transform.xform(vertices));
211220
#ifdef DEBUG_ENABLED
@@ -370,43 +379,61 @@ void NavigationObstacle2D::_update_fake_agent_radius_debug() {
370379

371380
#ifdef DEBUG_ENABLED
372381
void NavigationObstacle2D::_update_static_obstacle_debug() {
373-
if (get_vertices().size() > 2 && NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_static()) {
374-
bool obstacle_pushes_inward = Geometry2D::is_polygon_clockwise(get_vertices());
382+
if (get_vertices().size() < 3) {
383+
return;
384+
}
375385

376-
Color debug_static_obstacle_face_color;
386+
if (!NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_enable_obstacles_static()) {
387+
return;
388+
}
377389

378-
if (obstacle_pushes_inward) {
379-
debug_static_obstacle_face_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushin_face_color();
380-
} else {
381-
debug_static_obstacle_face_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushout_face_color();
382-
}
390+
RenderingServer *rs = RenderingServer::get_singleton();
383391

384-
Vector<Vector2> debug_obstacle_polygon_vertices = get_vertices();
392+
rs->mesh_clear(debug_mesh_rid);
385393

386-
Vector<Color> debug_obstacle_polygon_colors;
387-
debug_obstacle_polygon_colors.resize(debug_obstacle_polygon_vertices.size());
388-
debug_obstacle_polygon_colors.fill(debug_static_obstacle_face_color);
394+
const int vertex_count = vertices.size();
389395

390-
RS::get_singleton()->canvas_item_add_polygon(debug_canvas_item, get_global_transform().xform(debug_obstacle_polygon_vertices), debug_obstacle_polygon_colors);
396+
Vector<Vector2> edge_vertex_array;
397+
edge_vertex_array.resize(vertex_count * 4);
391398

392-
Color debug_static_obstacle_edge_color;
399+
Vector2 *edge_vertex_array_ptrw = edge_vertex_array.ptrw();
393400

394-
if (obstacle_pushes_inward) {
395-
debug_static_obstacle_edge_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushin_edge_color();
396-
} else {
397-
debug_static_obstacle_edge_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushout_edge_color();
398-
}
401+
int vertex_index = 0;
399402

400-
Vector<Vector2> debug_obstacle_line_vertices = get_vertices();
401-
debug_obstacle_line_vertices.push_back(debug_obstacle_line_vertices[0]);
402-
debug_obstacle_line_vertices.resize(debug_obstacle_line_vertices.size());
403+
for (int i = 0; i < vertex_count; i++) {
404+
Vector2 point = vertices[i];
405+
Vector2 next_point = vertices[(i + 1) % vertex_count];
403406

404-
Vector<Color> debug_obstacle_line_colors;
405-
debug_obstacle_line_colors.resize(debug_obstacle_line_vertices.size());
406-
debug_obstacle_line_colors.fill(debug_static_obstacle_edge_color);
407+
Vector2 direction = next_point.direction_to(point);
408+
Vector2 arrow_dir = -direction.orthogonal();
409+
Vector2 edge_middle = point + ((next_point - point) * 0.5);
407410

408-
// Transforming the vertices directly instead of the canvas item in order to not affect the circle shape by non-uniform scales.
409-
RS::get_singleton()->canvas_item_add_polyline(debug_canvas_item, get_global_transform().xform(debug_obstacle_line_vertices), debug_obstacle_line_colors, 4.0);
411+
edge_vertex_array_ptrw[vertex_index++] = edge_middle;
412+
edge_vertex_array_ptrw[vertex_index++] = edge_middle + (arrow_dir * 10.0);
413+
414+
edge_vertex_array_ptrw[vertex_index++] = point;
415+
edge_vertex_array_ptrw[vertex_index++] = next_point;
416+
}
417+
418+
Color debug_static_obstacle_edge_color;
419+
420+
if (are_vertices_valid()) {
421+
debug_static_obstacle_edge_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushout_edge_color();
422+
} else {
423+
debug_static_obstacle_edge_color = NavigationServer2D::get_singleton()->get_debug_navigation_avoidance_static_obstacle_pushin_edge_color();
410424
}
425+
426+
Vector<Color> line_color_array;
427+
line_color_array.resize(edge_vertex_array.size());
428+
line_color_array.fill(debug_static_obstacle_edge_color);
429+
430+
Array edge_mesh_array;
431+
edge_mesh_array.resize(Mesh::ARRAY_MAX);
432+
edge_mesh_array[Mesh::ARRAY_VERTEX] = edge_vertex_array;
433+
edge_mesh_array[Mesh::ARRAY_COLOR] = line_color_array;
434+
435+
rs->mesh_add_surface_from_arrays(debug_mesh_rid, RS::PRIMITIVE_LINES, edge_mesh_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
436+
437+
rs->canvas_item_add_mesh(debug_canvas_item, debug_mesh_rid, get_global_transform());
411438
}
412439
#endif // DEBUG_ENABLED

scene/2d/navigation_obstacle_2d.h

+7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class NavigationObstacle2D : public Node2D {
4444
real_t radius = 0.0;
4545

4646
Vector<Vector2> vertices;
47+
bool vertices_are_clockwise = true;
48+
bool vertices_are_valid = true;
4749

4850
bool avoidance_enabled = true;
4951
uint32_t avoidance_layers = 1;
@@ -60,6 +62,8 @@ class NavigationObstacle2D : public Node2D {
6062
#ifdef DEBUG_ENABLED
6163
private:
6264
RID debug_canvas_item;
65+
RID debug_mesh_rid;
66+
6367
void _update_fake_agent_radius_debug();
6468
void _update_static_obstacle_debug();
6569
#endif // DEBUG_ENABLED
@@ -86,6 +90,9 @@ class NavigationObstacle2D : public Node2D {
8690
void set_vertices(const Vector<Vector2> &p_vertices);
8791
const Vector<Vector2> &get_vertices() const { return vertices; }
8892

93+
bool are_vertices_clockwise() const { return vertices_are_clockwise; }
94+
bool are_vertices_valid() const { return vertices_are_valid; }
95+
8996
void set_avoidance_layers(uint32_t p_layers);
9097
uint32_t get_avoidance_layers() const;
9198

scene/3d/navigation_obstacle_3d.cpp

+16-12
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,19 @@ NavigationObstacle3D::~NavigationObstacle3D() {
258258
void NavigationObstacle3D::set_vertices(const Vector<Vector3> &p_vertices) {
259259
vertices = p_vertices;
260260

261+
Vector<Vector2> vertices_2d;
262+
vertices_2d.resize(vertices.size());
263+
264+
const Vector3 *vertices_ptr = vertices.ptr();
265+
Vector2 *vertices_2d_ptrw = vertices_2d.ptrw();
266+
267+
for (int i = 0; i < vertices.size(); i++) {
268+
vertices_2d_ptrw[i] = Vector2(vertices_ptr[i].x, vertices_ptr[i].z);
269+
}
270+
271+
vertices_are_clockwise = !Geometry2D::is_polygon_clockwise(vertices_2d); // Geometry2D is inverted.
272+
vertices_are_valid = !Geometry2D::triangulate_polygon(vertices_2d).is_empty();
273+
261274
const Basis basis = is_inside_tree() ? get_global_basis() : get_basis();
262275
const float rotation_y = is_inside_tree() ? get_global_rotation().y : get_rotation().y;
263276
const Vector3 safe_scale = basis.get_scale().abs().maxf(0.001);
@@ -604,21 +617,12 @@ void NavigationObstacle3D::_update_static_obstacle_debug() {
604617

605618
rs->mesh_add_surface_from_arrays(static_obstacle_debug_mesh_rid, RS::PRIMITIVE_LINES, edge_mesh_array);
606619

607-
Vector<Vector2> polygon_2d_vertices;
608-
polygon_2d_vertices.resize(vertex_count);
609-
for (int i = 0; i < vertex_count; i++) {
610-
const Vector3 &vert = vertices[i];
611-
polygon_2d_vertices.write[i] = Vector2(vert.x, vert.z);
612-
}
613-
614-
Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(polygon_2d_vertices);
615-
616620
Ref<StandardMaterial3D> edge_material;
617621

618-
if (triangulated_polygon_2d_indices.is_empty()) {
619-
edge_material = ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material();
620-
} else {
622+
if (are_vertices_valid()) {
621623
edge_material = ns3d->get_debug_navigation_avoidance_static_obstacle_pushout_edge_material();
624+
} else {
625+
edge_material = ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material();
622626
}
623627

624628
rs->instance_set_surface_override_material(static_obstacle_debug_instance_rid, 0, edge_material->get_rid());

scene/3d/navigation_obstacle_3d.h

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class NavigationObstacle3D : public Node3D {
4545
real_t radius = 0.0;
4646

4747
Vector<Vector3> vertices;
48+
bool vertices_are_clockwise = true;
49+
bool vertices_are_valid = true;
4850

4951
bool avoidance_enabled = true;
5052
uint32_t avoidance_layers = 1;
@@ -96,6 +98,9 @@ class NavigationObstacle3D : public Node3D {
9698
void set_vertices(const Vector<Vector3> &p_vertices);
9799
const Vector<Vector3> &get_vertices() const { return vertices; }
98100

101+
bool are_vertices_clockwise() const { return vertices_are_clockwise; }
102+
bool are_vertices_valid() const { return vertices_are_valid; }
103+
99104
void set_avoidance_layers(uint32_t p_layers);
100105
uint32_t get_avoidance_layers() const;
101106

0 commit comments

Comments
 (0)