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.
This commit is contained in:
@@ -330,17 +330,6 @@ class BezierSpline final : public Spline {
|
|||||||
int resolution() const;
|
int resolution() const;
|
||||||
void set_resolution(const int value);
|
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;
|
void resize(const int size) final;
|
||||||
blender::MutableSpan<blender::float3> positions() final;
|
blender::MutableSpan<blender::float3> positions() final;
|
||||||
blender::Span<blender::float3> positions() const final;
|
blender::Span<blender::float3> positions() const final;
|
||||||
@@ -567,14 +556,6 @@ class NURBSpline final : public Spline {
|
|||||||
uint8_t order() const;
|
uint8_t order() const;
|
||||||
void set_order(const uint8_t value);
|
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;
|
bool check_valid_size_and_order() const;
|
||||||
int knots_size() const;
|
int knots_size() const;
|
||||||
|
|
||||||
@@ -634,11 +615,6 @@ class PolySpline final : public Spline {
|
|||||||
|
|
||||||
int size() const final;
|
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;
|
void resize(const int size) final;
|
||||||
blender::MutableSpan<blender::float3> positions() final;
|
blender::MutableSpan<blender::float3> positions() final;
|
||||||
blender::Span<blender::float3> positions() const final;
|
blender::Span<blender::float3> positions() const final;
|
||||||
|
|||||||
@@ -762,7 +762,10 @@ static CurveEval get_curve_single_vert()
|
|||||||
{
|
{
|
||||||
CurveEval curve;
|
CurveEval curve;
|
||||||
std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
|
std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
|
||||||
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));
|
curve.add_spline(std::move(spline));
|
||||||
|
|
||||||
return curve;
|
return curve;
|
||||||
|
|||||||
@@ -70,24 +70,6 @@ void BezierSpline::set_resolution(const int value)
|
|||||||
this->mark_cache_invalid();
|
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)
|
void BezierSpline::resize(const int size)
|
||||||
{
|
{
|
||||||
handle_types_left_.resize(size);
|
handle_types_left_.resize(size);
|
||||||
|
|||||||
@@ -81,19 +81,6 @@ void NURBSpline::set_order(const uint8_t value)
|
|||||||
this->mark_cache_invalid();
|
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)
|
void NURBSpline::resize(const int size)
|
||||||
{
|
{
|
||||||
positions_.resize(size);
|
positions_.resize(size);
|
||||||
|
|||||||
@@ -45,14 +45,6 @@ int PolySpline::size() const
|
|||||||
return size;
|
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)
|
void PolySpline::resize(const int size)
|
||||||
{
|
{
|
||||||
positions_.resize(size);
|
positions_.resize(size);
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "BLI_array.hh"
|
#include "BLI_array.hh"
|
||||||
#include "BLI_set.hh"
|
#include "BLI_set.hh"
|
||||||
|
#include "BLI_string_ref.hh"
|
||||||
#include "BLI_task.hh"
|
#include "BLI_task.hh"
|
||||||
|
|
||||||
#include "DNA_mesh_types.h"
|
#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,
|
static std::unique_ptr<CurveEval> create_curve_from_vert_indices(
|
||||||
const MeshComponent &mesh_component,
|
const MeshComponent &mesh_component, Span<Vector<int>> vert_indices, IndexRange cyclic_splines)
|
||||||
Span<Vector<int>> point_to_vert_maps)
|
|
||||||
{
|
{
|
||||||
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();
|
Set<bke::AttributeIDRef> source_attribute_ids = mesh_component.attribute_ids();
|
||||||
|
|
||||||
/* Copy builtin control point attributes. */
|
/* Copy builtin control point attributes. */
|
||||||
@@ -54,28 +66,40 @@ static void copy_attributes_to_points(CurveEval &curve,
|
|||||||
"tilt", ATTR_DOMAIN_POINT, 0.0f);
|
"tilt", ATTR_DOMAIN_POINT, 0.0f);
|
||||||
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
||||||
for (const int i : range) {
|
for (const int i : range) {
|
||||||
copy_attribute_to_points<float>(
|
copy_attribute_to_points<float>(tilt_attribute, vert_indices[i], splines[i]->tilts());
|
||||||
tilt_attribute, point_to_vert_maps[i], splines[i]->tilts());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
source_attribute_ids.remove_contained("tilt");
|
source_attribute_ids.remove_contained("tilt");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
for (SplinePtr &spline : splines) {
|
||||||
|
spline->tilts().fill(0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (source_attribute_ids.contains("radius")) {
|
if (source_attribute_ids.contains("radius")) {
|
||||||
const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
|
const VArray<float> radius_attribute = mesh_component.attribute_get_for_read<float>(
|
||||||
"radius", ATTR_DOMAIN_POINT, 1.0f);
|
"radius", ATTR_DOMAIN_POINT, 1.0f);
|
||||||
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
threading::parallel_for(splines.index_range(), 256, [&](IndexRange range) {
|
||||||
for (const int i : range) {
|
for (const int i : range) {
|
||||||
copy_attribute_to_points<float>(
|
copy_attribute_to_points<float>(radius_attribute, vert_indices[i], splines[i]->radii());
|
||||||
radius_attribute, point_to_vert_maps[i], splines[i]->radii());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
source_attribute_ids.remove_contained("radius");
|
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) {
|
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)) {
|
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()) {
|
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) {
|
attribute_math::convert_to_static_type(mesh_attribute.type(), [&](auto dummy) {
|
||||||
using T = decltype(dummy);
|
using T = decltype(dummy);
|
||||||
copy_attribute_to_points<T>(
|
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 {
|
struct CurveFromEdgesOutput {
|
||||||
std::unique_ptr<CurveEval> curve;
|
/** The indices in the mesh for each control point of each result splines. */
|
||||||
Vector<Vector<int>> point_to_vert_maps;
|
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>> vert_indices;
|
||||||
Vector<Vector<int>> point_to_vert_maps;
|
|
||||||
|
|
||||||
/* Compute the number of edges connecting to each vertex. */
|
/* Compute the number of edges connecting to each vertex. */
|
||||||
Array<int> neighbor_count(verts.size(), 0);
|
Array<int> neighbor_count(verts.size(), 0);
|
||||||
@@ -173,19 +200,15 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
|
Vector<int> spline_indices;
|
||||||
Vector<int> point_to_vert_map;
|
spline_indices.append(current_vert);
|
||||||
|
|
||||||
spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
|
|
||||||
point_to_vert_map.append(current_vert);
|
|
||||||
|
|
||||||
/* Follow connected edges until we read a vertex with more than two connected edges. */
|
/* Follow connected edges until we read a vertex with more than two connected edges. */
|
||||||
while (true) {
|
while (true) {
|
||||||
int last_vert = current_vert;
|
int last_vert = current_vert;
|
||||||
current_vert = next_vert;
|
current_vert = next_vert;
|
||||||
|
|
||||||
spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
|
spline_indices.append(current_vert);
|
||||||
point_to_vert_map.append(current_vert);
|
|
||||||
unused_edges[current_vert]--;
|
unused_edges[current_vert]--;
|
||||||
unused_edges[last_vert]--;
|
unused_edges[last_vert]--;
|
||||||
|
|
||||||
@@ -199,12 +222,13 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
|
|||||||
next_vert = (last_vert == next_a) ? next_b : next_a;
|
next_vert = (last_vert == next_a) ? next_b : next_a;
|
||||||
}
|
}
|
||||||
|
|
||||||
spline->attributes.reallocate(spline->size());
|
vert_indices.append(std::move(spline_indices));
|
||||||
curve->add_spline(std::move(spline));
|
|
||||||
point_to_vert_maps.append(std::move(point_to_vert_map));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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). */
|
/* All remaining edges are part of cyclic splines (we skipped vertices with two edges before). */
|
||||||
for (const int start_vert : verts.index_range()) {
|
for (const int start_vert : verts.index_range()) {
|
||||||
if (unused_edges[start_vert] != 2) {
|
if (unused_edges[start_vert] != 2) {
|
||||||
@@ -214,20 +238,16 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
|
|||||||
int current_vert = start_vert;
|
int current_vert = start_vert;
|
||||||
int next_vert = neighbors[neighbor_offsets[current_vert]];
|
int next_vert = neighbors[neighbor_offsets[current_vert]];
|
||||||
|
|
||||||
std::unique_ptr<PolySpline> spline = std::make_unique<PolySpline>();
|
Vector<int> spline_indices;
|
||||||
Vector<int> point_to_vert_map;
|
|
||||||
spline->set_cyclic(true);
|
|
||||||
|
|
||||||
spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
|
spline_indices.append(current_vert);
|
||||||
point_to_vert_map.append(current_vert);
|
|
||||||
|
|
||||||
/* Follow connected edges until we loop back to the start vertex. */
|
/* Follow connected edges until we loop back to the start vertex. */
|
||||||
while (next_vert != start_vert) {
|
while (next_vert != start_vert) {
|
||||||
const int last_vert = current_vert;
|
const int last_vert = current_vert;
|
||||||
current_vert = next_vert;
|
current_vert = next_vert;
|
||||||
|
|
||||||
spline->add_point(verts[current_vert].co, 1.0f, 0.0f);
|
spline_indices.append(current_vert);
|
||||||
point_to_vert_map.append(current_vert);
|
|
||||||
unused_edges[current_vert]--;
|
unused_edges[current_vert]--;
|
||||||
unused_edges[last_vert]--;
|
unused_edges[last_vert]--;
|
||||||
|
|
||||||
@@ -237,13 +257,12 @@ static CurveFromEdgesOutput edges_to_curve(Span<MVert> verts, Span<std::pair<int
|
|||||||
next_vert = (last_vert == next_a) ? next_b : next_a;
|
next_vert = (last_vert == next_a) ? next_b : next_a;
|
||||||
}
|
}
|
||||||
|
|
||||||
spline->attributes.reallocate(spline->size());
|
vert_indices.append(std::move(spline_indices));
|
||||||
curve->add_spline(std::move(spline));
|
|
||||||
point_to_vert_maps.append(std::move(point_to_vert_map));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
curve->attributes.reallocate(curve->splines().size());
|
const int final_size = vert_indices.size();
|
||||||
return {std::move(curve), std::move(point_to_vert_maps)};
|
|
||||||
|
return {std::move(vert_indices), IndexRange(cyclic_start, final_size - cyclic_start)};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -266,9 +285,11 @@ std::unique_ptr<CurveEval> mesh_to_curve_convert(const MeshComponent &mesh_compo
|
|||||||
const Mesh &mesh = *mesh_component.get_for_read();
|
const Mesh &mesh = *mesh_component.get_for_read();
|
||||||
Vector<std::pair<int, int>> selected_edges = get_selected_edges(*mesh_component.get_for_read(),
|
Vector<std::pair<int, int>> selected_edges = get_selected_edges(*mesh_component.get_for_read(),
|
||||||
selection);
|
selection);
|
||||||
CurveFromEdgesOutput output = edges_to_curve({mesh.mvert, mesh.totvert}, selected_edges);
|
CurveFromEdgesOutput output = edges_to_curve_point_indices({mesh.mvert, mesh.totvert},
|
||||||
copy_attributes_to_points(*output.curve, mesh_component, output.point_to_vert_maps);
|
selected_edges);
|
||||||
return std::move(output.curve);
|
|
||||||
|
return create_curve_from_vert_indices(
|
||||||
|
mesh_component, output.vert_indices, output.cyclic_splines);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::geometry
|
} // namespace blender::geometry
|
||||||
|
|||||||
Reference in New Issue
Block a user