Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/geometry/intern/mesh_to_curve_convert.cc')
-rw-r--r--source/blender/geometry/intern/mesh_to_curve_convert.cc108
1 files changed, 67 insertions, 41 deletions
diff --git a/source/blender/geometry/intern/mesh_to_curve_convert.cc b/source/blender/geometry/intern/mesh_to_curve_convert.cc
index 0cbec35ec7a..965c09984fa 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<T> &source_data,
}
}
-static void copy_attributes_to_points(CurveEval &curve,
- const MeshComponent &mesh_component,
- Span<Vector<int>> point_to_vert_maps)
+static std::unique_ptr<CurveEval> create_curve_from_vert_indices(
+ const MeshComponent &mesh_component, Span<Vector<int>> vert_indices, IndexRange cyclic_splines)
{
- MutableSpan<SplinePtr> splines = curve.splines();
+ std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
+ curve->resize(vert_indices.size());
+
+ MutableSpan<SplinePtr> splines = curve->splines();
+
+ for (const int i : vert_indices.index_range()) {
+ splines[i] = std::make_unique<PolySpline>();
+ splines[i]->resize(vert_indices[i].size());
+ }
+ for (const int i : cyclic_splines) {
+ splines[i]->set_cyclic(true);
+ }
+
Set<bke::AttributeIDRef> source_attribute_ids = mesh_component.attribute_ids();
/* Copy builtin control point attributes. */
@@ -54,27 +66,44 @@ 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<float>(
- tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
+ copy_attribute_to_points<float>(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<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
"radius", ATTR_DOMAIN_POINT, 1.0f);
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
for (const int i : range) {
- copy_attribute_to_points<float>(
- radius_attribute, point_to_vert_maps[i], splines[i]->radii());
+ copy_attribute_to_points<float>(radius_attribute, vert_indices[i], splines[i]->radii());
}
});
source_attribute_ids.remove_contained("radius");
}
+ else {
+ for (SplinePtr &spline : splines) {
+ spline->radii().fill(1.0f);
+ }
+ }
+
+ VArray<float3> mesh_positions = mesh_component.attribute_get_for_read(
+ "position", ATTR_DOMAIN_POINT, float3(0));
+ threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
+ for (const int i : range) {
+ copy_attribute_to_points(mesh_positions, vert_indices[i], splines[i]->positions());
+ }
+ });
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)) {
+ /* Don't copy attributes that are built-in on meshes but not on curves. */
continue;
}
@@ -104,24 +133,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<T>(
- mesh_attribute.typed<T>(), point_to_vert_maps[i], spline_attribute->typed<T>());
+ mesh_attribute.typed<T>(), vert_indices[i], spline_attribute->typed<T>());
});
}
});
}
- curve.assert_valid_point_attributes();
+ curve->assert_valid_point_attributes();
+ return curve;
}
struct CurveFromEdgesOutput {
- std::unique_ptr<CurveEval> curve;
- Vector<Vector<int>> point_to_vert_maps;
+ /** The indices in the mesh for each control point of each result splines. */
+ Vector<Vector<int>> vert_indices;
+ /** A subset of splines that should be set cyclic. */
+ IndexRange cyclic_splines;
};
-static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int, int>> edges)
+static CurveFromEdgesOutput edges_to_curve_point_indices(Span<MVert> verts,
+ Span<std::pair<int, int>> edges)
{
- std::unique_ptr<CurveEval> curve = std::make_unique<CurveEval>();
- Vector<Vector<int>> point_to_vert_maps;
+ Vector<Vector<int>> vert_indices;
/* Compute the number of edges connecting to each vertex. */
Array<int> neighbor_count(verts.size(), 0);
@@ -173,19 +205,15 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
continue;
}
- std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
- Vector<int> point_to_vert_map;
-
- spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
- point_to_vert_map.append(current_vert);
+ Vector<int> 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 +227,13 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
next_vert = (last_vert == next_a) ? next_b : next_a;
}
- spline->attributes.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 +243,16 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
int current_vert = start_vert;
int next_vert = neighbors[neighbor_offsets[current_vert]];
- std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
- Vector<int> point_to_vert_map;
- spline->set_cyclic(true);
+ Vector<int> 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 +262,12 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
next_vert = (last_vert == next_a) ? next_b : next_a;
}
- spline->attributes.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 +290,11 @@ std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_compo
const Mesh &mesh = *mesh_component.get_for_read();
Vector<std::pair<int, int>> 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