Repository: godotengine/godot
File: editor/plugins/navigation_obstacle_3d_editor_plugin.cpp (C++)

Code before:
	if (vertices.is_empty()) {
		return;
	}

	float height = obstacle->get_height();
	Basis gbi = obstacle->get_global_basis().inverse();

	const int vertex_count = vertices.size();

	Vector<Vector3> lines_mesh_vertices;
	lines_mesh_vertices.resize(vertex_count * 8);
	Vector3 *lines_mesh_vertices_ptrw = lines_mesh_vertices.ptrw();

	int vertex_index = 0;

	for (int i = 0; i < vertex_count; i++) {
		Vector3 point = vertices[i];
		Vector3 next_point = vertices[(i + 1) % vertex_count];

		Vector3 direction = next_point.direction_to(point);
		Vector3 arrow_dir = direction.cross(Vector3(0.0, 1.0, 0.0));
		Vector3 edge_middle = point + ((next_point - point) * 0.5);

		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(edge_middle);
		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(edge_middle + (arrow_dir * 0.5));

		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(point);
		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(next_point);

		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(Vector3(point.x, height, point.z));
		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(Vector3(next_point.x, height, next_point.z));

		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(point);
		lines_mesh_vertices_ptrw[vertex_index++] = gbi.xform(Vector3(point.x, height, point.z));
	}

	Vector<Vector2> polygon_2d_vertices;
	polygon_2d_vertices.resize(vertex_count);
	for (int i = 0; i < vertex_count; i++) {
		const Vector3 &vert = vertices[i];
		polygon_2d_vertices.write[i] = Vector2(vert.x, vert.z);
	}
	Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(polygon_2d_vertices);

	NavigationServer3D *ns3d = NavigationServer3D::get_singleton();

	if (triangulated_polygon_2d_indices.is_empty()) {
		p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material());
	} else {
		p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushout_edge_material());
	}

Review comment (suggestion):
```suggestion
		// Ensure vector stays perpendicular even when scaled non-uniformly.
```
Per the [comment style](https://docs.godotengine.org/en/latest/contributing/development/code_style_guidelines.html#comment-style-guide). 

Code after:
	if (vertices.is_empty()) {
		return;
	}

	float height = obstacle->get_height();

	const Basis safe_basis = Basis(Vector3(0.0, 1.0, 0.0), obstacle->get_global_rotation().y, obstacle->get_global_basis().get_scale().abs().maxf(0.001));
	const Basis gbi = obstacle->get_global_basis().inverse();
	const Basis safe_global_basis = gbi * safe_basis;
	const int vertex_count = vertices.size();

	Vector<Vector3> lines_mesh_vertices;
	lines_mesh_vertices.resize(vertex_count * 8);
	Vector3 *lines_mesh_vertices_ptrw = lines_mesh_vertices.ptrw();

	int vertex_index = 0;

	for (int i = 0; i < vertex_count; i++) {
		Vector3 point = vertices[i];
		Vector3 next_point = vertices[(i + 1) % vertex_count];

		Vector3 direction = safe_basis.xform(next_point.direction_to(point));
		Vector3 arrow_dir = direction.cross(Vector3(0.0, 1.0, 0.0));
		Vector3 edge_middle = point + ((next_point - point) * 0.5);

		// Ensure vector stays perpendicular even when scaled non-uniformly.
		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(edge_middle);
		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(edge_middle) + gbi.xform(arrow_dir) * 0.5;

		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(point);
		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(next_point);

		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(Vector3(point.x, height, point.z));
		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(Vector3(next_point.x, height, next_point.z));

		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(point);
		lines_mesh_vertices_ptrw[vertex_index++] = safe_global_basis.xform(Vector3(point.x, height, point.z));
	}

	Vector<Vector2> polygon_2d_vertices;
	polygon_2d_vertices.resize(vertex_count);
	for (int i = 0; i < vertex_count; i++) {
		const Vector3 &vert = vertices[i];
		polygon_2d_vertices.write[i] = Vector2(vert.x, vert.z);
	}
	Vector<int> triangulated_polygon_2d_indices = Geometry2D::triangulate_polygon(polygon_2d_vertices);

	NavigationServer3D *ns3d = NavigationServer3D::get_singleton();

	if (triangulated_polygon_2d_indices.is_empty()) {
		p_gizmo->add_lines(lines_mesh_vertices, ns3d->get_debug_navigation_avoidance_static_obstacle_pushin_edge_material());