From 60c59d7d611dfd72652d9f7ffef519f983703349 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 22 Dec 2021 17:39:35 -0600 Subject: [PATCH] Cleanup: Remove spline add_point method, refactor mesh to curve node It's better to calculate the size of a spline before creating it, and this should simplify refactoring to a data structure that stores all point attribute contiguously (see T94193). The mesh to curve conversion is simplified slightly now, it creates the curve output after gathering all of the result vertex indices. This should be more efficient too, since it only grows an index vector for each spline, not a whole spline. --- source/blender/blenkernel/BKE_spline.hh | 24 ---- .../intern/curve_to_mesh_convert.cc | 5 +- .../blenkernel/intern/spline_bezier.cc | 18 --- .../blender/blenkernel/intern/spline_nurbs.cc | 13 --- .../blender/blenkernel/intern/spline_poly.cc | 8 -- .../geometry/intern/mesh_to_curve_convert.cc | 105 +++++++++++------- 6 files changed, 67 insertions(+), 106 deletions(-) diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh index ebdc4a0ca0b..d66af092475 100644 --- a/source/blender/blenkernel/BKE_spline.hh +++ b/source/blender/blenkernel/BKE_spline.hh @@ -330,17 +330,6 @@ class BezierSpline final : public Spline { int resolution() const; void set_resolution(const int value); - /** - * \warning Call #reallocate on the spline's attributes after adding all points. - */ - void add_point(const blender::float3 position, - const HandleType handle_type_left, - const blender::float3 handle_position_left, - const HandleType handle_type_right, - const blender::float3 handle_position_right, - const float radius, - const float tilt); - void resize(const int size) final; blender::MutableSpan positions() final; blender::Span positions() const final; @@ -567,14 +556,6 @@ class NURBSpline final : public Spline { uint8_t order() const; void set_order(const uint8_t value); - /** - * \warning Call #reallocate on the spline's attributes after adding all points. - */ - void add_point(const blender::float3 position, - const float radius, - const float tilt, - const float weight); - bool check_valid_size_and_order() const; int knots_size() const; @@ -634,11 +615,6 @@ class PolySpline final : public Spline { int size() const final; - /** - * \warning Call #reallocate on the spline's attributes after adding all points. - */ - void add_point(const blender::float3 position, const float radius, const float tilt); - void resize(const int size) final; blender::MutableSpan positions() final; blender::Span positions() const final; diff --git a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index 8c256da44cd..073d9d18a04 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -762,7 +762,10 @@ static CurveEval get_curve_single_vert() { CurveEval curve; std::unique_ptr spline = std::make_unique(); - spline->add_point(float3(0), 0, 0.0f); + spline->resize(1.0f); + spline->positions().fill(float3(0)); + spline->radii().fill(1.0f); + spline->tilts().fill(0.0f); curve.add_spline(std::move(spline)); return curve; diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index 9ce285cebb8..b24c8960857 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -70,24 +70,6 @@ void BezierSpline::set_resolution(const int value) this->mark_cache_invalid(); } -void BezierSpline::add_point(const float3 position, - const HandleType handle_type_left, - const float3 handle_position_left, - const HandleType handle_type_right, - const float3 handle_position_right, - const float radius, - const float tilt) -{ - handle_types_left_.append(handle_type_left); - handle_positions_left_.append(handle_position_left); - positions_.append(position); - handle_types_right_.append(handle_type_right); - handle_positions_right_.append(handle_position_right); - radii_.append(radius); - tilts_.append(tilt); - this->mark_cache_invalid(); -} - void BezierSpline::resize(const int size) { handle_types_left_.resize(size); diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc index e9d4ba7c7ef..719ba4b7ecd 100644 --- a/source/blender/blenkernel/intern/spline_nurbs.cc +++ b/source/blender/blenkernel/intern/spline_nurbs.cc @@ -81,19 +81,6 @@ void NURBSpline::set_order(const uint8_t value) this->mark_cache_invalid(); } -void NURBSpline::add_point(const float3 position, - const float radius, - const float tilt, - const float weight) -{ - positions_.append(position); - radii_.append(radius); - tilts_.append(tilt); - weights_.append(weight); - knots_dirty_ = true; - this->mark_cache_invalid(); -} - void NURBSpline::resize(const int size) { positions_.resize(size); diff --git a/source/blender/blenkernel/intern/spline_poly.cc b/source/blender/blenkernel/intern/spline_poly.cc index 4af68b5f270..480bbd1dfe8 100644 --- a/source/blender/blenkernel/intern/spline_poly.cc +++ b/source/blender/blenkernel/intern/spline_poly.cc @@ -45,14 +45,6 @@ int PolySpline::size() const return size; } -void PolySpline::add_point(const float3 position, const float radius, const float tilt) -{ - positions_.append(position); - radii_.append(radius); - tilts_.append(tilt); - this->mark_cache_invalid(); -} - void PolySpline::resize(const int size) { positions_.resize(size); diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc index 0cbec35ec7a..398ce609d55 100644 --- a/source/blender/geometry/intern/mesh_to_curve_convert.cc +++ b/source/blender/geometry/intern/mesh_to_curve_convert.cc @@ -16,6 +16,7 @@ #include "BLI_array.hh" #include "BLI_set.hh" +#include "BLI_string_ref.hh" #include "BLI_task.hh" #include "DNA_mesh_types.h" @@ -41,11 +42,22 @@ static void copy_attribute_to_points(const VArray &source_data, } } -static void copy_attributes_to_points(CurveEval &curve, - const MeshComponent &mesh_component, - Span> point_to_vert_maps) +static std::unique_ptr create_curve_from_vert_indices( + const MeshComponent &mesh_component, Span> vert_indices, IndexRange cyclic_splines) { - MutableSpan splines = curve.splines(); + std::unique_ptr curve = std::make_unique(); + curve->resize(vert_indices.size()); + + MutableSpan splines = curve->splines(); + + for (const int i : vert_indices.index_range()) { + splines[i] = std::make_unique(); + splines[i]->resize(vert_indices[i].size()); + } + for (const int i : cyclic_splines) { + splines[i]->set_cyclic(true); + } + Set source_attribute_ids = mesh_component.attribute_ids(); /* Copy builtin control point attributes. */ @@ -54,28 +66,40 @@ static void copy_attributes_to_points(CurveEval &curve, "tilt", ATTR_DOMAIN_POINT, 0.0f); threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { for (const int i : range) { - copy_attribute_to_points( - tilt_attribute, point_to_vert_maps[i], splines[i]->tilts()); + copy_attribute_to_points(tilt_attribute, vert_indices[i], splines[i]->tilts()); } }); source_attribute_ids.remove_contained("tilt"); } + else { + for (SplinePtr &spline : splines) { + spline->tilts().fill(0.0f); + } + } + if (source_attribute_ids.contains("radius")) { const VArray radius_attribute = mesh_component.attribute_get_for_read( "radius", ATTR_DOMAIN_POINT, 1.0f); threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) { for (const int i : range) { - copy_attribute_to_points( - radius_attribute, point_to_vert_maps[i], splines[i]->radii()); + copy_attribute_to_points(radius_attribute, vert_indices[i], splines[i]->radii()); } }); source_attribute_ids.remove_contained("radius"); } + else { + for (SplinePtr &spline : splines) { + spline->radii().fill(1.0f); + } + } for (const bke::AttributeIDRef &attribute_id : source_attribute_ids) { - /* Don't copy attributes that are built-in on meshes but not on curves. */ if (mesh_component.attribute_is_builtin(attribute_id)) { - continue; + /* Don't copy attributes that are built-in on meshes but not on curves, + * except for the position attribute. */ + if (!(attribute_id == "position")) { + continue; + } } if (!attribute_id.should_be_kept()) { @@ -104,24 +128,27 @@ static void copy_attributes_to_points(CurveEval &curve, attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) { using T = decltype(dummy); copy_attribute_to_points( - mesh_attribute.typed(), point_to_vert_maps[i], spline_attribute->typed()); + mesh_attribute.typed(), vert_indices[i], spline_attribute->typed()); }); } }); } - curve.assert_valid_point_attributes(); + curve->assert_valid_point_attributes(); + return curve; } struct CurveFromEdgesOutput { - std::unique_ptr curve; - Vector> point_to_vert_maps; + /** The indices in the mesh for each control point of each result splines. */ + Vector> vert_indices; + /** A subset of splines that should be set cyclic. */ + IndexRange cyclic_splines; }; -static CurveFromEdgesOutput edges_to_curve(Span verts, Span> edges) +static CurveFromEdgesOutput edges_to_curve_point_indices(Span verts, + Span> edges) { - std::unique_ptr curve = std::make_unique(); - Vector> point_to_vert_maps; + Vector> vert_indices; /* Compute the number of edges connecting to each vertex. */ Array neighbor_count(verts.size(), 0); @@ -173,19 +200,15 @@ static CurveFromEdgesOutput edges_to_curve(Span verts, Span spline = std::make_unique(); - Vector point_to_vert_map; - - spline->add_point(verts[current_vert].co, 1.0f, 0.0f); - point_to_vert_map.append(current_vert); + Vector spline_indices; + spline_indices.append(current_vert); /* Follow connected edges until we read a vertex with more than two connected edges. */ while (true) { int last_vert = current_vert; current_vert = next_vert; - spline->add_point(verts[current_vert].co, 1.0f, 0.0f); - point_to_vert_map.append(current_vert); + spline_indices.append(current_vert); unused_edges[current_vert]--; unused_edges[last_vert]--; @@ -199,12 +222,13 @@ static CurveFromEdgesOutput edges_to_curve(Span verts, Spanattributes.reallocate(spline->size()); - curve->add_spline(std::move(spline)); - point_to_vert_maps.append(std::move(point_to_vert_map)); + vert_indices.append(std::move(spline_indices)); } } + /* All splines added after this are cyclic. */ + const int cyclic_start = vert_indices.size(); + /* All remaining edges are part of cyclic splines (we skipped vertices with two edges before). */ for (const int start_vert : verts.index_range()) { if (unused_edges[start_vert] != 2) { @@ -214,20 +238,16 @@ static CurveFromEdgesOutput edges_to_curve(Span verts, Span spline = std::make_unique(); - Vector point_to_vert_map; - spline->set_cyclic(true); + Vector spline_indices; - spline->add_point(verts[current_vert].co, 1.0f, 0.0f); - point_to_vert_map.append(current_vert); + spline_indices.append(current_vert); /* Follow connected edges until we loop back to the start vertex. */ while (next_vert != start_vert) { const int last_vert = current_vert; current_vert = next_vert; - spline->add_point(verts[current_vert].co, 1.0f, 0.0f); - point_to_vert_map.append(current_vert); + spline_indices.append(current_vert); unused_edges[current_vert]--; unused_edges[last_vert]--; @@ -237,13 +257,12 @@ static CurveFromEdgesOutput edges_to_curve(Span verts, Spanattributes.reallocate(spline->size()); - curve->add_spline(std::move(spline)); - point_to_vert_maps.append(std::move(point_to_vert_map)); + vert_indices.append(std::move(spline_indices)); } - curve->attributes.reallocate(curve->splines().size()); - return {std::move(curve), std::move(point_to_vert_maps)}; + const int final_size = vert_indices.size(); + + return {std::move(vert_indices), IndexRange(cyclic_start, final_size - cyclic_start)}; } /** @@ -266,9 +285,11 @@ std::unique_ptr mesh_to_curve_convert(const MeshComponent &mesh_compo const Mesh &mesh = *mesh_component.get_for_read(); Vector> selected_edges = get_selected_edges(*mesh_component.get_for_read(), selection); - CurveFromEdgesOutput output = edges_to_curve({mesh.mvert, mesh.totvert}, selected_edges); - copy_attributes_to_points(*output.curve, mesh_component, output.point_to_vert_maps); - return std::move(output.curve); + CurveFromEdgesOutput output = edges_to_curve_point_indices({mesh.mvert, mesh.totvert}, + selected_edges); + + return create_curve_from_vert_indices( + mesh_component, output.vert_indices, output.cyclic_splines); } } // namespace blender::geometry