Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve NavigationRegion2D debug performance #92372

Merged
merged 1 commit into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading