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