Geometry Nodes: Copy parameters when copying a curves data-block

Previously, things like materials, symmetry, and selection options
stored on `Curves` weren't copied to the result in nodes like the
subdivide and resample nodes. Now they are, which fixes some
unexpected behavior and allows visualization of the sculpt mode
selection.

In the realize instances and join nodes the behavior is the same as
for meshes, the parameters are taken from the first (top) input.

I also refactored some functions to return a `CurvesGeometry` by-value,
which makes it the responsibility of the node to copy the parameters.
That should make the algorithms more reusable in other situations.

Differential Revision: https://developer.blender.org/D15408
This commit is contained in:
Hans Goudey 2022-07-19 10:14:46 -05:00
parent 9246ff373a
commit 6a1ab4747b
18 changed files with 148 additions and 143 deletions

View File

@ -735,6 +735,12 @@ Curves *curves_new_nomain(CurvesGeometry curves);
*/
Curves *curves_new_nomain_single(int points_num, CurveType type);
/**
* Copy data from #src to #dst, except the geometry data in #CurvesGeometry. Typically used to
* copy high-level parameters when a geometry-altering operation creates a new curves data-block.
*/
void curves_copy_parameters(const Curves &src, Curves &dst);
std::array<int, CURVE_TYPES_NUM> calculate_type_counts(const VArray<int8_t> &types);
/* -------------------------------------------------------------------- */

View File

@ -55,6 +55,13 @@ void fill_points(const CurvesGeometry &curves,
fill_points(curves, curve_selection, &value, dst);
}
/**
* Copy only the information on the point domain, but not the offsets or any point attributes,
* meant for operations that change the number of points but not the number of curves.
* \warning The returned curves have invalid offsets!
*/
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves);
/**
* Copy the size of every curve in #curve_ranges to the corresponding index in #counts.
*/

View File

@ -388,6 +388,23 @@ Curves *curves_new_nomain(CurvesGeometry curves)
return curves_id;
}
void curves_copy_parameters(const Curves &src, Curves &dst)
{
dst.flag = src.flag;
dst.attributes_active_index = src.attributes_active_index;
MEM_SAFE_FREE(dst.mat);
dst.mat = static_cast<Material **>(MEM_malloc_arrayN(src.totcol, sizeof(Material *), __func__));
dst.totcol = src.totcol;
MutableSpan(dst.mat, dst.totcol).copy_from(Span(src.mat, src.totcol));
dst.symmetry = src.symmetry;
dst.selection_domain = src.selection_domain;
dst.surface = src.surface;
MEM_SAFE_FREE(dst.surface_uv_map);
if (src.surface_uv_map != nullptr) {
dst.surface_uv_map = BLI_strdup(src.surface_uv_map);
}
}
CurvesSurfaceTransforms::CurvesSurfaceTransforms(const Object &curves_ob, const Object *surface_ob)
{
this->curves_to_world = curves_ob.obmat;

View File

@ -84,6 +84,18 @@ void fill_points(const CurvesGeometry &curves,
});
}
bke::CurvesGeometry copy_only_curve_domain(const bke::CurvesGeometry &src_curves)
{
bke::CurvesGeometry dst_curves(0, src_curves.curves_num());
CustomData_copy(&src_curves.curve_data,
&dst_curves.curve_data,
CD_MASK_ALL,
CD_DUPLICATE,
src_curves.curves_num());
dst_curves.runtime->type_counts = src_curves.runtime->type_counts;
return dst_curves;
}
IndexMask indices_for_type(const VArray<int8_t> &types,
const std::array<int, CURVE_TYPES_NUM> &type_counts,
const CurveType type,

View File

@ -1,12 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_index_mask.hh"
#pragma once
#include "BLI_index_mask.hh"
#include "BKE_curves.hh"
struct Mesh;
struct Curves;
class MeshComponent;
/** \file
* \ingroup geo
@ -15,10 +15,10 @@ class MeshComponent;
namespace blender::geometry {
/**
* Convert the mesh into one or many poly splines. Since splines cannot have branches,
* intersections of more than three edges will become breaks in splines. Attributes that
* Convert the mesh into one or many poly curves. Since curves cannot have branches,
* intersections of more than three edges will become breaks in curves. Attributes that
* are not built-in on meshes and not curves are transferred to the result curve.
*/
Curves *mesh_to_curve_convert(const MeshComponent &mesh_component, const IndexMask selection);
bke::CurvesGeometry mesh_to_curve_convert(const Mesh &mesh, const IndexMask selection);
} // namespace blender::geometry

View File

@ -2,17 +2,10 @@
#pragma once
#include "DNA_curves_types.h"
#include "BLI_function_ref.hh"
#include "BLI_index_mask.hh"
struct Curves;
class CurveComponent;
namespace blender::bke {
class CurvesGeometry;
}
#include "BKE_curves.hh"
namespace blender::geometry {
@ -27,14 +20,13 @@ namespace blender::geometry {
*/
bool try_curves_conversion_in_place(IndexMask selection,
CurveType dst_type,
FunctionRef<Curves &()> get_writable_curves_fn);
FunctionRef<bke::CurvesGeometry &()> get_writable_curves_fn);
/**
* Change the types of the selected curves, potentially changing the total point count.
*/
Curves *convert_curves(const CurveComponent &src_component,
const bke::CurvesGeometry &src_curves,
IndexMask selection,
CurveType dst_type);
bke::CurvesGeometry convert_curves(const bke::CurvesGeometry &src_curves,
IndexMask selection,
CurveType dst_type);
} // namespace blender::geometry

View File

@ -4,11 +4,10 @@
#include "BLI_function_ref.hh"
#include "BLI_index_mask.hh"
#include "BLI_virtual_array.hh"
#include "BKE_curves.hh"
class CurveComponent;
namespace blender::geometry {
/**
@ -18,9 +17,8 @@ namespace blender::geometry {
*
* \param selection: A selection of curves to consider when subdividing.
*/
Curves *subdivide_curves(const CurveComponent &src_component,
const bke::CurvesGeometry &src_curves,
IndexMask selection,
const VArray<int> &cuts);
bke::CurvesGeometry subdivide_curves(const bke::CurvesGeometry &src_curves,
IndexMask selection,
const VArray<int> &cuts);
} // namespace blender::geometry

View File

@ -30,13 +30,12 @@ static void copy_with_map(const VArray<T> &src, Span<int> map, MutableSpan<T> ds
});
}
static Curves *create_curve_from_vert_indices(const MeshComponent &mesh_component,
const Span<int> vert_indices,
const Span<int> curve_offsets,
const IndexRange cyclic_curves)
static bke::CurvesGeometry create_curve_from_vert_indices(const Mesh &mesh,
const Span<int> vert_indices,
const Span<int> curve_offsets,
const IndexRange cyclic_curves)
{
Curves *curves_id = bke::curves_new_nomain(vert_indices.size(), curve_offsets.size());
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id->geometry);
bke::CurvesGeometry curves(vert_indices.size(), curve_offsets.size());
curves.offsets_for_write().drop_back(1).copy_from(curve_offsets);
curves.offsets_for_write().last() = vert_indices.size();
curves.fill_curve_types(CURVE_TYPE_POLY);
@ -44,8 +43,8 @@ static Curves *create_curve_from_vert_indices(const MeshComponent &mesh_componen
curves.cyclic_for_write().fill(false);
curves.cyclic_for_write().slice(cyclic_curves).fill(true);
const bke::AttributeAccessor mesh_attributes = bke::mesh_attributes(mesh);
bke::MutableAttributeAccessor curves_attributes = curves.attributes_for_write();
const bke::AttributeAccessor mesh_attributes = *mesh_component.attributes();
Set<bke::AttributeIDRef> source_attribute_ids = mesh_attributes.all_ids();
@ -76,7 +75,7 @@ static Curves *create_curve_from_vert_indices(const MeshComponent &mesh_componen
});
}
return curves_id;
return curves;
}
struct CurveFromEdgesOutput {
@ -220,16 +219,14 @@ static Vector<std::pair<int, int>> get_selected_edges(const Mesh &mesh, const In
return selected_edges;
}
Curves *mesh_to_curve_convert(const MeshComponent &mesh_component, const IndexMask selection)
bke::CurvesGeometry mesh_to_curve_convert(const Mesh &mesh, const IndexMask selection)
{
const Mesh &mesh = *mesh_component.get_for_read();
Vector<std::pair<int, int>> selected_edges = get_selected_edges(*mesh_component.get_for_read(),
selection);
Vector<std::pair<int, int>> selected_edges = get_selected_edges(mesh, selection);
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.curve_offsets, output.cyclic_curves);
mesh, output.vert_indices, output.curve_offsets, output.cyclic_curves);
}
} // namespace blender::geometry

View File

@ -1238,6 +1238,11 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
dst_component.replace(dst_curves_id);
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
/* Copy settings from the first input geometry set with curves. */
const RealizeCurveTask &first_task = tasks.first();
const Curves &first_curves_id = *first_task.curve_info->curves;
bke::curves_copy_parameters(first_curves_id, *dst_curves_id);
/* Prepare id attribute. */
SpanAttributeWriter<int> point_ids;
if (all_curves_info.create_id_attribute) {

View File

@ -1,9 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_attribute.hh"
#include "BKE_attribute_math.hh"
#include "BKE_curves.hh"
#include "BKE_curves_utils.hh"
#include "BKE_geometry_set.hh"
#include "BLI_task.hh"
@ -322,39 +322,16 @@ static void retrieve_generic_point_attributes(const bke::AttributeAccessor &src_
});
}
static Curves *create_result_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const CurveType dst_type)
{
Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num());
bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
CurveComponent dst_component;
dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable);
/* Directly copy curve attributes, since they stay the same (except for curve types). */
CustomData_copy(&src_curves.curve_data,
&dst_curves.curve_data,
CD_MASK_ALL,
CD_DUPLICATE,
src_curves.curves_num());
dst_curves.fill_curve_types(selection, dst_type);
return dst_curves_id;
}
static Curves *convert_curves_to_bezier(const CurveComponent &src_component,
const bke::CurvesGeometry &src_curves,
const IndexMask selection)
static bke::CurvesGeometry convert_curves_to_bezier(const bke::CurvesGeometry &src_curves,
const IndexMask selection)
{
const VArray<int8_t> src_knot_modes = src_curves.nurbs_knots_modes();
const VArray<int8_t> src_types = src_curves.curve_types();
const VArray<bool> src_cyclic = src_curves.cyclic();
const Span<float3> src_positions = src_curves.positions();
Curves *dst_curves_id = create_result_curves(src_curves, selection, CURVE_TYPE_BEZIER);
bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
CurveComponent dst_component;
dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable);
bke::CurvesGeometry dst_curves = bke::curves::copy_only_curve_domain(src_curves);
dst_curves.fill_curve_types(selection, CURVE_TYPE_BEZIER);
MutableSpan<int> dst_offsets = dst_curves.offsets_for_write();
retrieve_curve_sizes(src_curves, dst_curves.offsets_for_write());
@ -367,8 +344,8 @@ static Curves *convert_curves_to_bezier(const CurveComponent &src_component,
bke::curves::accumulate_counts_to_offsets(dst_offsets);
dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
const bke::AttributeAccessor src_attributes = *src_component.attributes();
bke::MutableAttributeAccessor dst_attributes = *dst_component.attributes_for_write();
const bke::AttributeAccessor src_attributes = src_curves.attributes();
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
GenericAttributes attributes;
retrieve_generic_point_attributes(src_attributes, dst_attributes, attributes);
@ -501,21 +478,18 @@ static Curves *convert_curves_to_bezier(const CurveComponent &src_component,
attribute.finish();
}
return dst_curves_id;
return dst_curves;
}
static Curves *convert_curves_to_nurbs(const CurveComponent &src_component,
const bke::CurvesGeometry &src_curves,
const IndexMask selection)
static bke::CurvesGeometry convert_curves_to_nurbs(const bke::CurvesGeometry &src_curves,
const IndexMask selection)
{
const VArray<int8_t> src_types = src_curves.curve_types();
const VArray<bool> src_cyclic = src_curves.cyclic();
const Span<float3> src_positions = src_curves.positions();
Curves *dst_curves_id = create_result_curves(src_curves, selection, CURVE_TYPE_NURBS);
bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
CurveComponent dst_component;
dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable);
bke::CurvesGeometry dst_curves = bke::curves::copy_only_curve_domain(src_curves);
dst_curves.fill_curve_types(selection, CURVE_TYPE_NURBS);
MutableSpan<int> dst_offsets = dst_curves.offsets_for_write();
retrieve_curve_sizes(src_curves, dst_curves.offsets_for_write());
@ -527,8 +501,8 @@ static Curves *convert_curves_to_nurbs(const CurveComponent &src_component,
bke::curves::accumulate_counts_to_offsets(dst_offsets);
dst_curves.resize(dst_offsets.last(), dst_curves.curves_num());
const bke::AttributeAccessor src_attributes = *src_component.attributes();
bke::MutableAttributeAccessor dst_attributes = *dst_component.attributes_for_write();
const bke::AttributeAccessor src_attributes = src_curves.attributes();
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
GenericAttributes attributes;
retrieve_generic_point_attributes(src_attributes, dst_attributes, attributes);
@ -669,7 +643,7 @@ static Curves *convert_curves_to_nurbs(const CurveComponent &src_component,
attribute.finish();
}
return dst_curves_id;
return dst_curves;
}
static bke::CurvesGeometry convert_curves_trivial(const bke::CurvesGeometry &src_curves,
@ -682,33 +656,31 @@ static bke::CurvesGeometry convert_curves_trivial(const bke::CurvesGeometry &src
return dst_curves;
}
Curves *convert_curves(const CurveComponent &src_component,
const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const CurveType dst_type)
bke::CurvesGeometry convert_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const CurveType dst_type)
{
switch (dst_type) {
case CURVE_TYPE_CATMULL_ROM:
case CURVE_TYPE_POLY:
return bke::curves_new_nomain(convert_curves_trivial(src_curves, selection, dst_type));
return convert_curves_trivial(src_curves, selection, dst_type);
case CURVE_TYPE_BEZIER:
return convert_curves_to_bezier(src_component, src_curves, selection);
return convert_curves_to_bezier(src_curves, selection);
case CURVE_TYPE_NURBS:
return convert_curves_to_nurbs(src_component, src_curves, selection);
return convert_curves_to_nurbs(src_curves, selection);
}
BLI_assert_unreachable();
return nullptr;
return {};
}
bool try_curves_conversion_in_place(const IndexMask selection,
const CurveType dst_type,
FunctionRef<Curves &()> get_writable_curves_fn)
FunctionRef<bke::CurvesGeometry &()> get_writable_curves_fn)
{
if (conversion_can_change_point_num(dst_type)) {
return false;
}
Curves &curves_id = get_writable_curves_fn();
bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
bke::CurvesGeometry &curves = get_writable_curves_fn();
curves.fill_curve_types(selection, dst_type);
curves.remove_attributes_based_on_types();
return true;

View File

@ -11,26 +11,6 @@
namespace blender::geometry {
/**
* \warning Only the curve domain of the input is copied, so the result is invalid!
*/
static Curves *create_result_curves(const bke::CurvesGeometry &src_curves)
{
Curves *dst_curves_id = bke::curves_new_nomain(0, src_curves.curves_num());
bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
CurveComponent dst_component;
dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable);
/* Directly copy curve attributes, since they stay the same. */
CustomData_copy(&src_curves.curve_data,
&dst_curves.curve_data,
CD_MASK_ALL,
CD_DUPLICATE,
src_curves.curves_num());
dst_curves.runtime->type_counts = src_curves.runtime->type_counts;
return dst_curves_id;
}
/**
* Return a range used to retrieve values from an array of values stored per point, but with an
* extra element at the end of each curve. This is useful for offsets within curves, where it is
@ -342,10 +322,9 @@ static void subdivide_bezier_positions(const Span<float3> src_positions,
cyclic, dst_types_l, dst_types_r, dst_positions, dst_handles_l, dst_handles_r);
}
Curves *subdivide_curves(const CurveComponent &src_component,
const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const VArray<int> &cuts)
bke::CurvesGeometry subdivide_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const VArray<int> &cuts)
{
const Vector<IndexRange> unselected_ranges = selection.extract_ranges_invert(
src_curves.curves_range());
@ -353,10 +332,7 @@ Curves *subdivide_curves(const CurveComponent &src_component,
/* Cyclic is accessed a lot, it's probably worth it to make sure it's a span. */
const VArraySpan<bool> cyclic{src_curves.cyclic()};
Curves *dst_curves_id = create_result_curves(src_curves);
bke::CurvesGeometry &dst_curves = bke::CurvesGeometry::wrap(dst_curves_id->geometry);
CurveComponent dst_component;
dst_component.replace(dst_curves_id, GeometryOwnershipType::Editable);
bke::CurvesGeometry dst_curves = bke::curves::copy_only_curve_domain(src_curves);
/* For each point, this contains the point offset in the corresponding result curve,
* starting at zero. For example for two curves with four points each, the values might
@ -385,8 +361,8 @@ Curves *subdivide_curves(const CurveComponent &src_component,
dst_curves.resize(dst_curves.offsets().last(), dst_curves.curves_num());
const bke::AttributeAccessor src_attributes = *src_component.attributes();
bke::MutableAttributeAccessor dst_attributes = *dst_component.attributes_for_write();
const bke::AttributeAccessor src_attributes = src_curves.attributes();
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
auto subdivide_catmull_rom = [&](IndexMask selection) {
for (auto &attribute : retrieve_point_attributes(src_attributes, dst_attributes)) {
@ -476,7 +452,7 @@ Curves *subdivide_curves(const CurveComponent &src_component,
}
}
return dst_curves_id;
return dst_curves;
}
} // namespace blender::geometry

View File

@ -603,10 +603,13 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
fillet_param.limit_radius = limit_radius;
const Curves &src_curves_id = *geometry_set.get_curves_for_read();
const std::unique_ptr<CurveEval> input_curve = curves_to_curve_eval(*component.get_for_read());
std::unique_ptr<CurveEval> output_curve = fillet_curve(*input_curve, fillet_param);
geometry_set.replace_curves(curve_eval_to_curves(*output_curve));
Curves *dst_curves_id = curve_eval_to_curves(*output_curve);
bke::curves_copy_parameters(src_curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
}
static void node_geo_exec(GeoNodeExecParams params)

View File

@ -65,8 +65,10 @@ static void node_geo_exec(GeoNodeExecParams params)
Field<int> count = params.extract_input<Field<int>>("Count");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const CurveComponent *component = geometry.get_component_for_read<CurveComponent>()) {
if (!component->is_empty()) {
geometry.replace_curves(geometry::resample_to_count(*component, selection, count));
if (const Curves *src_curves = component->get_for_read()) {
Curves *dst_curves = geometry::resample_to_count(*component, selection, count);
bke::curves_copy_parameters(*src_curves, *dst_curves);
geometry.replace_curves(dst_curves);
}
}
});
@ -76,8 +78,10 @@ static void node_geo_exec(GeoNodeExecParams params)
Field<float> length = params.extract_input<Field<float>>("Length");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const CurveComponent *component = geometry.get_component_for_read<CurveComponent>()) {
if (!component->is_empty()) {
geometry.replace_curves(geometry::resample_to_length(*component, selection, length));
if (const Curves *src_curves = component->get_for_read()) {
Curves *dst_curves = geometry::resample_to_length(*component, selection, length);
bke::curves_copy_parameters(*src_curves, *dst_curves);
geometry.replace_curves(dst_curves);
}
}
});
@ -86,8 +90,10 @@ static void node_geo_exec(GeoNodeExecParams params)
case GEO_NODE_CURVE_RESAMPLE_EVALUATED:
geometry_set.modify_geometry_sets([&](GeometrySet &geometry) {
if (const CurveComponent *component = geometry.get_component_for_read<CurveComponent>()) {
if (!component->is_empty()) {
geometry.replace_curves(geometry::resample_to_evaluated(*component, selection));
if (const Curves *src_curves = component->get_for_read()) {
Curves *dst_curves = geometry::resample_to_evaluated(*component, selection);
bke::curves_copy_parameters(*src_curves, *dst_curves);
geometry.replace_curves(dst_curves);
}
}
});

View File

@ -61,15 +61,18 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
if (geometry::try_curves_conversion_in_place(selection, dst_type, [&]() -> Curves & {
return *geometry_set.get_curves_for_write();
})) {
if (geometry::try_curves_conversion_in_place(
selection, dst_type, [&]() -> bke::CurvesGeometry & {
return bke::CurvesGeometry::wrap(geometry_set.get_curves_for_write()->geometry);
})) {
return;
}
Curves *dst_curves = geometry::convert_curves(src_component, src_curves, selection, dst_type);
bke::CurvesGeometry dst_curves = geometry::convert_curves(src_curves, selection, dst_type);
geometry_set.replace_curves(dst_curves);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(src_curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
});
params.set_output("Curve", std::move(geometry_set));

View File

@ -35,11 +35,11 @@ static void node_geo_exec(GeoNodeExecParams params)
}
const CurveComponent &component = *geometry_set.get_component_for_read<CurveComponent>();
const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(
component.get_for_read()->geometry);
const Curves &src_curves_id = *component.get_for_read();
const bke::CurvesGeometry &src_curves = bke::CurvesGeometry::wrap(src_curves_id.geometry);
GeometryComponentFieldContext field_context{component, ATTR_DOMAIN_POINT};
fn::FieldEvaluator evaluator{field_context, curves.points_num()};
fn::FieldEvaluator evaluator{field_context, src_curves.points_num()};
evaluator.add(cuts_field);
evaluator.evaluate();
const VArray<int> cuts = evaluator.get_evaluated<int>(0);
@ -47,9 +47,12 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
Curves *result = geometry::subdivide_curves(component, curves, curves.curves_range(), cuts);
bke::CurvesGeometry dst_curves = geometry::subdivide_curves(
src_curves, src_curves.curves_range(), cuts);
geometry_set.replace_curves(result);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(src_curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
});
params.set_output("Curve", geometry_set);
}

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_curves.hh"
#include "BKE_spline.hh"
#include "BLI_task.hh"
@ -515,7 +516,8 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set,
const VArray<float> starts = evaluator.get_evaluated<float>(0);
const VArray<float> ends = evaluator.get_evaluated<float>(1);
std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*geometry_set.get_curves_for_read());
const Curves &src_curves_id = *geometry_set.get_curves_for_read();
std::unique_ptr<CurveEval> curve = curves_to_curve_eval(src_curves_id);
MutableSpan<SplinePtr> splines = curve->splines();
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
@ -566,7 +568,9 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set,
}
});
geometry_set.replace_curves(curve_eval_to_curves(*curve));
Curves *dst_curves_id = curve_eval_to_curves(*curve);
bke::curves_copy_parameters(src_curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
}
static void node_geo_exec(GeoNodeExecParams params)

View File

@ -369,6 +369,7 @@ static void duplicate_curves(GeometrySet &geometry_set,
point_offsets.last() = dst_points_num;
Curves *new_curves_id = bke::curves_new_nomain(dst_points_num, dst_curves_num);
bke::curves_copy_parameters(curves_id, *new_curves_id);
bke::CurvesGeometry &new_curves = bke::CurvesGeometry::wrap(new_curves_id->geometry);
MutableSpan<int> all_dst_offsets = new_curves.offsets_for_write();
@ -830,6 +831,7 @@ static void duplicate_points_curve(GeometrySet &geometry_set,
});
Curves *new_curves_id = bke::curves_new_nomain(dst_num, dst_num);
bke::curves_copy_parameters(src_curves_id, *new_curves_id);
bke::CurvesGeometry &new_curves = bke::CurvesGeometry::wrap(new_curves_id->geometry);
MutableSpan<int> new_curve_offsets = new_curves.offsets_for_write();
for (const int i : new_curves.curves_range()) {

View File

@ -18,7 +18,8 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (!geometry_set.has_mesh()) {
const Mesh *mesh = geometry_set.get_mesh_for_read();
if (mesh == nullptr) {
geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
return;
}
@ -34,7 +35,8 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
geometry_set.replace_curves(geometry::mesh_to_curve_convert(component, selection));
bke::CurvesGeometry curves = geometry::mesh_to_curve_convert(*mesh, selection);
geometry_set.replace_curves(bke::curves_new_nomain(std::move(curves)));
geometry_set.keep_only({GEO_COMPONENT_TYPE_CURVE, GEO_COMPONENT_TYPE_INSTANCES});
});