Skip to content

Commit

Permalink
Improve NavigationRegion2D debug performance
Browse files Browse the repository at this point in the history
Improves NavigationRegion2D debug performance by replacing the canvas polygon and line commands with a static mesh.
  • Loading branch information
smix8 committed May 28, 2024
1 parent 1e6b11d commit 5f5fe73
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 24 deletions.
178 changes: 154 additions & 24 deletions scene/2d/navigation_region_2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,19 @@ void NavigationRegion2D::_notification(int p_what) {
set_physics_process_internal(true);
} break;

case NOTIFICATION_VISIBILITY_CHANGED: {
#ifdef DEBUG_ENABLED
if (debug_instance_rid.is_valid()) {
RS::get_singleton()->canvas_item_set_visible(debug_instance_rid, is_visible_in_tree());
}
#endif // DEBUG_ENABLED
} break;

case NOTIFICATION_EXIT_TREE: {
_region_exit_navigation_map();
#ifdef DEBUG_ENABLED
_free_debug();
#endif // DEBUG_ENABLED
} break;

case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
Expand All @@ -189,6 +200,9 @@ void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_
}

navigation_polygon = p_navigation_polygon;
#ifdef DEBUG_ENABLED
debug_mesh_dirty = true;
#endif // DEBUG_ENABLED
NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, p_navigation_polygon);

if (navigation_polygon.is_valid()) {
Expand Down Expand Up @@ -420,12 +434,42 @@ void NavigationRegion2D::_region_update_transform() {

#ifdef DEBUG_ENABLED
void NavigationRegion2D::_update_debug_mesh() {
Vector<Vector2> navigation_polygon_vertices = navigation_polygon->get_vertices();
if (navigation_polygon_vertices.size() < 3) {
if (!is_inside_tree()) {
_free_debug();
return;
}

const NavigationServer2D *ns2d = NavigationServer2D::get_singleton();
RenderingServer *rs = RenderingServer::get_singleton();

if (!debug_instance_rid.is_valid()) {
debug_instance_rid = rs->canvas_item_create();
}
if (!debug_mesh_rid.is_valid()) {
debug_mesh_rid = rs->mesh_create();
}

const Transform2D region_gt = get_global_transform();

rs->canvas_item_set_parent(debug_instance_rid, get_world_2d()->get_canvas());
rs->canvas_item_set_transform(debug_instance_rid, region_gt);

if (!debug_mesh_dirty) {
return;
}

rs->mesh_clear(debug_mesh_rid);
debug_mesh_dirty = false;

const Vector<Vector2> &vertices = navigation_polygon->get_vertices();
if (vertices.size() < 3) {
return;
}

int polygon_count = navigation_polygon->get_polygon_count();
if (polygon_count == 0) {
return;
}

bool enabled_geometry_face_random_color = ns2d->get_debug_navigation_enable_geometry_face_random_color();
bool enabled_edge_lines = ns2d->get_debug_navigation_enable_edge_lines();
Expand All @@ -438,39 +482,109 @@ void NavigationRegion2D::_update_debug_mesh() {
debug_edge_color = ns2d->get_debug_navigation_geometry_edge_disabled_color();
}

int vertex_count = 0;
int line_count = 0;

for (int i = 0; i < polygon_count; i++) {
const Vector<int> &polygon = navigation_polygon->get_polygon(i);
int polygon_size = polygon.size();
if (polygon_size < 3) {
continue;
}
line_count += polygon_size * 2;
vertex_count += (polygon_size - 2) * 3;
}

Vector<Vector2> face_vertex_array;
face_vertex_array.resize(vertex_count);

Vector<Color> face_color_array;
if (enabled_geometry_face_random_color) {
face_color_array.resize(vertex_count);
}

Vector<Vector2> line_vertex_array;
if (enabled_edge_lines) {
line_vertex_array.resize(line_count);
}

RandomPCG rand;
Color polygon_color = debug_face_color;

for (int i = 0; i < navigation_polygon->get_polygon_count(); i++) {
// An array of vertices for this polygon.
Vector<int> polygon = navigation_polygon->get_polygon(i);
Vector<Vector2> debug_polygon_vertices;
debug_polygon_vertices.resize(polygon.size());
for (int j = 0; j < polygon.size(); j++) {
ERR_FAIL_INDEX(polygon[j], navigation_polygon_vertices.size());
debug_polygon_vertices.write[j] = navigation_polygon_vertices[polygon[j]];
int face_vertex_index = 0;
int line_vertex_index = 0;

Vector2 *face_vertex_array_ptrw = face_vertex_array.ptrw();
Color *face_color_array_ptrw = face_color_array.ptrw();
Vector2 *line_vertex_array_ptrw = line_vertex_array.ptrw();

for (int polygon_index = 0; polygon_index < polygon_count; polygon_index++) {
const Vector<int> &polygon_indices = navigation_polygon->get_polygon(polygon_index);
int polygon_indices_size = polygon_indices.size();
if (polygon_indices_size < 3) {
continue;
}

// Generate the polygon color, slightly randomly modified from the settings one.
Color random_variation_color = debug_face_color;
if (enabled_geometry_face_random_color) {
random_variation_color.set_hsv(
debug_face_color.get_h() + rand.random(-1.0, 1.0) * 0.1,
debug_face_color.get_s(),
debug_face_color.get_v() + rand.random(-1.0, 1.0) * 0.2);
// Generate the polygon color, slightly randomly modified from the settings one.
polygon_color.set_hsv(debug_face_color.get_h() + rand.random(-1.0, 1.0) * 0.1, debug_face_color.get_s(), debug_face_color.get_v() + rand.random(-1.0, 1.0) * 0.2);
polygon_color.a = debug_face_color.a;
}
random_variation_color.a = debug_face_color.a;

Vector<Color> debug_face_colors;
debug_face_colors.push_back(random_variation_color);
RS::get_singleton()->canvas_item_add_polygon(get_canvas_item(), debug_polygon_vertices, debug_face_colors);
for (int polygon_indices_index = 0; polygon_indices_index < polygon_indices_size - 2; polygon_indices_index++) {
face_vertex_array_ptrw[face_vertex_index] = vertices[polygon_indices[0]];
face_vertex_array_ptrw[face_vertex_index + 1] = vertices[polygon_indices[polygon_indices_index + 1]];
face_vertex_array_ptrw[face_vertex_index + 2] = vertices[polygon_indices[polygon_indices_index + 2]];
if (enabled_geometry_face_random_color) {
face_color_array_ptrw[face_vertex_index] = polygon_color;
face_color_array_ptrw[face_vertex_index + 1] = polygon_color;
face_color_array_ptrw[face_vertex_index + 2] = polygon_color;
}
face_vertex_index += 3;
}

if (enabled_edge_lines) {
Vector<Color> debug_edge_colors;
debug_edge_colors.push_back(debug_edge_color);
debug_polygon_vertices.push_back(debug_polygon_vertices[0]); // Add first again for closing polyline.
RS::get_singleton()->canvas_item_add_polyline(get_canvas_item(), debug_polygon_vertices, debug_edge_colors);
for (int polygon_indices_index = 0; polygon_indices_index < polygon_indices_size; polygon_indices_index++) {
line_vertex_array_ptrw[line_vertex_index] = vertices[polygon_indices[polygon_indices_index]];
line_vertex_index += 1;
if (polygon_indices_index + 1 == polygon_indices_size) {
line_vertex_array_ptrw[line_vertex_index] = vertices[polygon_indices[0]];
line_vertex_index += 1;
} else {
line_vertex_array_ptrw[line_vertex_index] = vertices[polygon_indices[polygon_indices_index + 1]];
line_vertex_index += 1;
}
}
}
}

if (!enabled_geometry_face_random_color) {
face_color_array.resize(face_vertex_array.size());
face_color_array.fill(debug_face_color);
}

Array face_mesh_array;
face_mesh_array.resize(Mesh::ARRAY_MAX);
face_mesh_array[Mesh::ARRAY_VERTEX] = face_vertex_array;
face_mesh_array[Mesh::ARRAY_COLOR] = face_color_array;

rs->mesh_add_surface_from_arrays(debug_mesh_rid, RS::PRIMITIVE_TRIANGLES, face_mesh_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);

if (enabled_edge_lines) {
Vector<Color> line_color_array;
line_color_array.resize(line_vertex_array.size());
line_color_array.fill(debug_edge_color);

Array line_mesh_array;
line_mesh_array.resize(Mesh::ARRAY_MAX);
line_mesh_array[Mesh::ARRAY_VERTEX] = line_vertex_array;
line_mesh_array[Mesh::ARRAY_COLOR] = line_color_array;

rs->mesh_add_surface_from_arrays(debug_mesh_rid, RS::PRIMITIVE_LINES, line_mesh_array, Array(), Dictionary(), RS::ARRAY_FLAG_USE_2D_VERTICES);
}

rs->canvas_item_add_mesh(debug_instance_rid, debug_mesh_rid, Transform2D());
rs->canvas_item_set_visible(debug_instance_rid, is_visible_in_tree());
}
#endif // DEBUG_ENABLED

Expand Down Expand Up @@ -512,3 +626,19 @@ void NavigationRegion2D::_update_debug_baking_rect() {
}
}
#endif // DEBUG_ENABLED

#ifdef DEBUG_ENABLED
void NavigationRegion2D::_free_debug() {
RenderingServer *rs = RenderingServer::get_singleton();
ERR_FAIL_NULL(rs);
if (debug_instance_rid.is_valid()) {
rs->canvas_item_clear(debug_instance_rid);
rs->free(debug_instance_rid);
debug_instance_rid = RID();
}
if (debug_mesh_rid.is_valid()) {
rs->free(debug_mesh_rid);
debug_mesh_rid = RID();
}
}
#endif // DEBUG_ENABLED
6 changes: 6 additions & 0 deletions scene/2d/navigation_region_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ class NavigationRegion2D : public Node2D {

#ifdef DEBUG_ENABLED
private:
RID debug_mesh_rid;
RID debug_instance_rid;

bool debug_mesh_dirty = true;

void _free_debug();
void _update_debug_mesh();
void _update_debug_edge_connections_mesh();
void _update_debug_baking_rect();
Expand Down

0 comments on commit 5f5fe73

Please sign in to comment.