Răsfoiți Sursa

Merge pull request #92372 from smix8/navregion2d_debug

Improve NavigationRegion2D debug performance
Rémi Verschelde 1 an în urmă
părinte
comite
183c634428
2 a modificat fișierele cu 160 adăugiri și 24 ștergeri
  1. 154 24
      scene/2d/navigation_region_2d.cpp
  2. 6 0
      scene/2d/navigation_region_2d.h

+ 154 - 24
scene/2d/navigation_region_2d.cpp

@@ -162,8 +162,19 @@ void NavigationRegion2D::_notification(int p_what) {
 			set_physics_process_internal(true);
 			set_physics_process_internal(true);
 		} break;
 		} 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: {
 		case NOTIFICATION_EXIT_TREE: {
 			_region_exit_navigation_map();
 			_region_exit_navigation_map();
+#ifdef DEBUG_ENABLED
+			_free_debug();
+#endif // DEBUG_ENABLED
 		} break;
 		} break;
 
 
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
@@ -189,6 +200,9 @@ void NavigationRegion2D::set_navigation_polygon(const Ref<NavigationPolygon> &p_
 	}
 	}
 
 
 	navigation_polygon = p_navigation_polygon;
 	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);
 	NavigationServer2D::get_singleton()->region_set_navigation_polygon(region, p_navigation_polygon);
 
 
 	if (navigation_polygon.is_valid()) {
 	if (navigation_polygon.is_valid()) {
@@ -420,12 +434,42 @@ void NavigationRegion2D::_region_update_transform() {
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 void NavigationRegion2D::_update_debug_mesh() {
 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;
 		return;
 	}
 	}
 
 
 	const NavigationServer2D *ns2d = NavigationServer2D::get_singleton();
 	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_geometry_face_random_color = ns2d->get_debug_navigation_enable_geometry_face_random_color();
 	bool enabled_edge_lines = ns2d->get_debug_navigation_enable_edge_lines();
 	bool enabled_edge_lines = ns2d->get_debug_navigation_enable_edge_lines();
@@ -438,39 +482,109 @@ void NavigationRegion2D::_update_debug_mesh() {
 		debug_edge_color = ns2d->get_debug_navigation_geometry_edge_disabled_color();
 		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;
 	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) {
 		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) {
 		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
 #endif // DEBUG_ENABLED
 
 
@@ -512,3 +626,19 @@ void NavigationRegion2D::_update_debug_baking_rect() {
 	}
 	}
 }
 }
 #endif // DEBUG_ENABLED
 #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 - 0
scene/2d/navigation_region_2d.h

@@ -52,6 +52,12 @@ class NavigationRegion2D : public Node2D {
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
 private:
 private:
+	RID debug_mesh_rid;
+	RID debug_instance_rid;
+
+	bool debug_mesh_dirty = true;
+
+	void _free_debug();
 	void _update_debug_mesh();
 	void _update_debug_mesh();
 	void _update_debug_edge_connections_mesh();
 	void _update_debug_edge_connections_mesh();
 	void _update_debug_baking_rect();
 	void _update_debug_baking_rect();