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
path: root/source
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-02-28 18:46:34 +0300
committerHans Goudey <h.goudey@me.com>2022-02-28 18:46:34 +0300
commit9ec12c26f16ea3da1e6de95d5d5daf1057464830 (patch)
tree708e542d5d4de0efdda7b9a54def6b25b6b64039 /source
parent81bb86c7506c0ae5f07780a63f954a8416a0d4e6 (diff)
Geometry Nodes: Begin conversion to new curves
This commit changes `CurveComponent` to store the new curve type by adding conversions to and from `CurveEval` in most nodes. This will temporarily make performance of curves in geometry nodes much worse, but as functionality is implemented for the new type and it is used in more places, performance will become better than before. We still use `CurveEval` for drawing curves, because the new `Curves` data-block has no evaluated points yet. So the `Curve` ID is still generated for rendering in the same way as before. It's also still needed for drawing curve object edit mode overlays. The old curve component isn't removed yet, because it is still used to implement the conversions to and from `CurveEval`. A few more attributes are added to make this possible: - `nurbs_weight`: The weight for each control point on NURBS curves. - `nurbs_order`: The order of the NURBS curve - `knots_mode`: Necessary for conversion, not defined yet. - `handle_type_{left/right}`: An 8 bit integer attribute. Differential Revision: https://developer.blender.org/D14145
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh73
-rw-r--r--source/blender/blenkernel/BKE_spline.hh3
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/curve.cc2
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc189
-rw-r--r--source/blender/blenkernel/intern/displist.cc4
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curve.cc167
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curves.cc521
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc26
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc7
-rw-r--r--source/blender/geometry/intern/realize_instances.cc39
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc5
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc16
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc10
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc12
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc7
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc7
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_length.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc14
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc21
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc13
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc24
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc15
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc15
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_transform.cc9
53 files changed, 1004 insertions, 327 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index d93b3ca95e7..f11bfb7692a 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -24,6 +24,7 @@
#include "FN_field.hh"
+struct Curves;
struct Collection;
struct Curve;
struct CurveEval;
@@ -415,7 +416,7 @@ struct GeometrySet {
* Create a new geometry set that only contains the given curve.
*/
static GeometrySet create_with_curve(
- CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ Curves *curves, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
/* Utility methods for access. */
/**
@@ -462,7 +463,7 @@ struct GeometrySet {
/**
* Returns a read-only curve or null.
*/
- const CurveEval *get_curve_for_read() const;
+ const Curves *get_curve_for_read() const;
/**
* Returns a mutable mesh or null. No ownership is transferred.
@@ -479,7 +480,7 @@ struct GeometrySet {
/**
* Returns a mutable curve or null. No ownership is transferred.
*/
- CurveEval *get_curve_for_write();
+ Curves *get_curve_for_write();
/* Utility methods for replacement. */
/**
@@ -499,7 +500,7 @@ struct GeometrySet {
/**
* Clear the existing curve and replace it with the given one.
*/
- void replace_curve(CurveEval *curve,
+ void replace_curve(Curves *curves,
GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
private:
@@ -632,17 +633,59 @@ class PointCloudComponent : public GeometryComponent {
};
/**
- * A geometry component that stores curve data, in other words, a group of splines.
- * Curves are stored differently than other geometry components, because the data structure used
- * here does not correspond exactly to the #Curve DNA data structure. A #CurveEval is stored here
- * instead, though the component does give access to a #Curve for interfacing with render engines
- * and other areas of Blender that expect to use a data-block with an #ID.
+ * Legacy runtime-only curves type.
+ * These curves are stored differently than other geometry components, because the data structure
+ * used here does not correspond exactly to the #Curve DNA data structure. A #CurveEval is stored
+ * here instead, though the component does give access to a #Curve for interfacing with render
+ * engines and other areas of Blender that expect to use a data-block with an #ID.
*/
-class CurveComponent : public GeometryComponent {
+class CurveComponentLegacy : public GeometryComponent {
private:
CurveEval *curve_ = nullptr;
GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned;
+ public:
+ CurveComponentLegacy();
+ ~CurveComponentLegacy();
+ GeometryComponent *copy() const override;
+
+ void clear();
+ bool has_curve() const;
+ /**
+ * Clear the component and replace it with the new curve.
+ */
+ void replace(CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ CurveEval *release();
+
+ const CurveEval *get_for_read() const;
+ CurveEval *get_for_write();
+
+ int attribute_domain_size(AttributeDomain domain) const final;
+
+ bool is_empty() const final;
+
+ bool owns_direct_data() const override;
+ void ensure_owns_direct_data() override;
+
+ static constexpr inline GeometryComponentType static_type = GEO_COMPONENT_TYPE_CURVE;
+
+ private:
+ const blender::bke::ComponentAttributeProviders *get_attribute_providers() const final;
+
+ blender::fn::GVArray attribute_try_adapt_domain_impl(const blender::fn::GVArray &varray,
+ AttributeDomain from_domain,
+ AttributeDomain to_domain) const final;
+};
+
+/**
+ * A geometry component that stores a group of curves, corresponding the the #Curves and
+ * #CurvesGeometry types.
+ */
+class CurveComponent : public GeometryComponent {
+ private:
+ Curves *curves_ = nullptr;
+ GeometryOwnershipType ownership_ = GeometryOwnershipType::Owned;
+
/**
* Curve data necessary to hold the draw cache for rendering, consistent over multiple redraws.
* This is necessary because Blender assumes that objects evaluate to an object data type, and
@@ -658,15 +701,15 @@ class CurveComponent : public GeometryComponent {
GeometryComponent *copy() const override;
void clear();
- bool has_curve() const;
+ bool has_curves() const;
/**
* Clear the component and replace it with the new curve.
*/
- void replace(CurveEval *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
- CurveEval *release();
+ void replace(Curves *curve, GeometryOwnershipType ownership = GeometryOwnershipType::Owned);
+ Curves *release();
- const CurveEval *get_for_read() const;
- CurveEval *get_for_write();
+ const Curves *get_for_read() const;
+ Curves *get_for_write();
int attribute_domain_size(AttributeDomain domain) const final;
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 439f20ee471..42b4702ee44 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -20,6 +20,7 @@
#include "BKE_attribute_math.hh"
struct Curve;
+struct Curves;
struct ListBase;
class Spline;
@@ -691,3 +692,5 @@ struct CurveEval {
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &curve,
const ListBase &nurbs_list);
std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve);
+std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves);
+Curves *curve_eval_to_curves(const CurveEval &curve_eval);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 2b77b2c5dae..a12a956cbf5 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -131,6 +131,7 @@ set(SRC
intern/fmodifier.c
intern/freestyle.c
intern/geometry_component_curve.cc
+ intern/geometry_component_curves.cc
intern/geometry_component_instances.cc
intern/geometry_component_mesh.cc
intern/geometry_component_pointcloud.cc
diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc
index b0f58dd4ec9..6be04b79761 100644
--- a/source/blender/blenkernel/intern/curve.cc
+++ b/source/blender/blenkernel/intern/curve.cc
@@ -115,6 +115,8 @@ static void curve_free_data(ID *id)
MEM_SAFE_FREE(curve->str);
MEM_SAFE_FREE(curve->strinfo);
MEM_SAFE_FREE(curve->tb);
+
+ delete curve->curve_eval;
}
static void curve_foreach_id(ID *id, LibraryForeachIDData *data)
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index 8529e7ad194..78dafe34b4f 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -13,6 +13,8 @@
#include "BKE_anonymous_attribute.hh"
#include "BKE_curve.h"
+#include "BKE_curves.hh"
+#include "BKE_geometry_set.hh"
#include "BKE_spline.hh"
using blender::Array;
@@ -23,8 +25,15 @@ using blender::Map;
using blender::MutableSpan;
using blender::Span;
using blender::StringRefNull;
+using blender::VArray;
+using blender::VArray_Span;
using blender::Vector;
using blender::bke::AttributeIDRef;
+using blender::bke::OutputAttribute;
+using blender::bke::OutputAttribute_Typed;
+using blender::bke::ReadAttributeLookup;
+using blender::fn::GVArray;
+using blender::fn::GVArray_GSpan;
blender::Span<SplinePtr> CurveEval::splines() const
{
@@ -336,6 +345,186 @@ std::unique_ptr<CurveEval> curve_eval_from_dna_curve(const Curve &dna_curve)
return curve_eval_from_dna_curve(dna_curve, *BKE_curve_nurbs_get_for_read(&dna_curve));
}
+static void copy_attributes_between_components(const GeometryComponent &src_component,
+ GeometryComponent &dst_component,
+ Span<std::string> skip)
+{
+ src_component.attribute_foreach(
+ [&](const AttributeIDRef &id, const AttributeMetaData meta_data) {
+ if (id.is_named() && skip.contains(id.name())) {
+ return true;
+ }
+
+ GVArray src_attribute = src_component.attribute_try_get_for_read(
+ id, meta_data.domain, meta_data.data_type);
+ if (!src_attribute) {
+ return true;
+ }
+ GVArray_GSpan src_attribute_data{src_attribute};
+
+ OutputAttribute dst_attribute = dst_component.attribute_try_get_for_output_only(
+ id, meta_data.domain, meta_data.data_type);
+ if (!dst_attribute) {
+ return true;
+ }
+ dst_attribute.varray().set_all(src_attribute_data.data());
+ dst_attribute.save();
+ return true;
+ });
+}
+
+std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
+{
+ CurveComponent src_component;
+ src_component.replace(&const_cast<Curves &>(curves), GeometryOwnershipType::ReadOnly);
+ const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(
+ curves.geometry);
+
+ VArray_Span<float> nurbs_weights{
+ src_component.attribute_get_for_read<float>("nurbs_weight", ATTR_DOMAIN_POINT, 0.0f)};
+ VArray_Span<int> nurbs_orders{
+ src_component.attribute_get_for_read<int>("nurbs_order", ATTR_DOMAIN_CURVE, 4)};
+ VArray_Span<int8_t> nurbs_knots_modes{
+ src_component.attribute_get_for_read<int8_t>("knots_mode", ATTR_DOMAIN_CURVE, 0)};
+
+ VArray_Span<int8_t> handle_types_right{
+ src_component.attribute_get_for_read<int8_t>("handle_type_right", ATTR_DOMAIN_POINT, 0)};
+ VArray_Span<int8_t> handle_types_left{
+ src_component.attribute_get_for_read<int8_t>("handle_type_left", ATTR_DOMAIN_POINT, 0)};
+
+ /* Create splines with the correct size and type. */
+ VArray<int8_t> curve_types = geometry.curve_types();
+ std::unique_ptr<CurveEval> curve_eval = std::make_unique<CurveEval>();
+ for (const int curve_index : curve_types.index_range()) {
+ const IndexRange point_range = geometry.range_for_curve(curve_index);
+
+ std::unique_ptr<Spline> spline;
+ switch (curve_types[curve_index]) {
+ case CURVE_TYPE_POLY: {
+ spline = std::make_unique<PolySpline>();
+ spline->resize(point_range.size());
+ break;
+ }
+ case CURVE_TYPE_BEZIER: {
+ std::unique_ptr<BezierSpline> bezier_spline = std::make_unique<BezierSpline>();
+ bezier_spline->resize(point_range.size());
+ bezier_spline->handle_types_left().copy_from(handle_types_left.slice(point_range));
+ bezier_spline->handle_types_right().copy_from(handle_types_right.slice(point_range));
+
+ spline = std::move(bezier_spline);
+ break;
+ }
+ case CURVE_TYPE_NURBS: {
+ std::unique_ptr<NURBSpline> nurb_spline = std::make_unique<NURBSpline>();
+ nurb_spline->resize(point_range.size());
+ nurb_spline->weights().copy_from(nurbs_weights.slice(point_range));
+ nurb_spline->set_order(nurbs_orders[curve_index]);
+ nurb_spline->knots_mode = static_cast<NURBSpline::KnotsMode>(
+ nurbs_knots_modes[curve_index]);
+
+ spline = std::move(nurb_spline);
+ break;
+ }
+ case CURVE_TYPE_CATMULL_ROM:
+ /* Not supported yet. */
+ BLI_assert_unreachable();
+ continue;
+ }
+ spline->positions().fill(float3(0));
+ spline->tilts().fill(0.0f);
+ spline->radii().fill(0.0f);
+ curve_eval->add_spline(std::move(spline));
+ }
+
+ CurveComponentLegacy dst_component;
+ dst_component.replace(curve_eval.get(), GeometryOwnershipType::Editable);
+
+ copy_attributes_between_components(src_component,
+ dst_component,
+ {"curve_type",
+ "nurbs_weight",
+ "nurbs_order",
+ "knots_mode",
+ "handle_type_right",
+ "handle_type_left"});
+
+ return curve_eval;
+}
+
+Curves *curve_eval_to_curves(const CurveEval &curve_eval)
+{
+ Curves *curves = blender::bke::curves_new_nomain(curve_eval.total_control_point_size(),
+ curve_eval.splines().size());
+ CurveComponent dst_component;
+ dst_component.replace(curves, GeometryOwnershipType::Editable);
+
+ blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(curves->geometry);
+ geometry.offsets().copy_from(curve_eval.control_point_offsets());
+ MutableSpan<int8_t> curve_types = geometry.curve_types();
+
+ OutputAttribute_Typed<float> nurbs_weight;
+ OutputAttribute_Typed<int> nurbs_order;
+ OutputAttribute_Typed<int8_t> nurbs_knots_mode;
+ if (curve_eval.has_spline_with_type(CURVE_TYPE_NURBS)) {
+ nurbs_weight = dst_component.attribute_try_get_for_output_only<float>("nurbs_weight",
+ ATTR_DOMAIN_POINT);
+ nurbs_order = dst_component.attribute_try_get_for_output_only<int>("nurbs_order",
+ ATTR_DOMAIN_CURVE);
+ nurbs_knots_mode = dst_component.attribute_try_get_for_output_only<int8_t>("knots_mode",
+ ATTR_DOMAIN_CURVE);
+ }
+ OutputAttribute_Typed<int8_t> handle_type_right;
+ OutputAttribute_Typed<int8_t> handle_type_left;
+ if (curve_eval.has_spline_with_type(CURVE_TYPE_BEZIER)) {
+ handle_type_right = dst_component.attribute_try_get_for_output_only<int8_t>(
+ "handle_type_right", ATTR_DOMAIN_POINT);
+ handle_type_left = dst_component.attribute_try_get_for_output_only<int8_t>("handle_type_left",
+ ATTR_DOMAIN_POINT);
+ }
+
+ for (const int curve_index : curve_eval.splines().index_range()) {
+ const Spline &spline = *curve_eval.splines()[curve_index];
+ curve_types[curve_index] = curve_eval.splines()[curve_index]->type();
+
+ const IndexRange point_range = geometry.range_for_curve(curve_index);
+
+ switch (spline.type()) {
+ case CURVE_TYPE_POLY:
+ break;
+ case CURVE_TYPE_BEZIER: {
+ const BezierSpline &src = static_cast<const BezierSpline &>(spline);
+ handle_type_right.as_span().slice(point_range).copy_from(src.handle_types_right());
+ handle_type_left.as_span().slice(point_range).copy_from(src.handle_types_left());
+ break;
+ }
+ case CURVE_TYPE_NURBS: {
+ const NURBSpline &src = static_cast<const NURBSpline &>(spline);
+ nurbs_knots_mode.as_span()[curve_index] = static_cast<int8_t>(src.knots_mode);
+ nurbs_order.as_span()[curve_index] = src.order();
+ nurbs_weight.as_span().slice(point_range).copy_from(src.weights());
+ break;
+ }
+ case CURVE_TYPE_CATMULL_ROM: {
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+ }
+
+ nurbs_weight.save();
+ nurbs_order.save();
+ nurbs_knots_mode.save();
+ handle_type_right.save();
+ handle_type_left.save();
+
+ CurveComponentLegacy src_component;
+ src_component.replace(&const_cast<CurveEval &>(curve_eval), GeometryOwnershipType::ReadOnly);
+
+ copy_attributes_between_components(src_component, dst_component, {});
+
+ return curves;
+}
+
void CurveEval::assert_valid_point_attributes() const
{
#ifdef DEBUG
diff --git a/source/blender/blenkernel/intern/displist.cc b/source/blender/blenkernel/intern/displist.cc
index 5c761e94bb9..97445851ffa 100644
--- a/source/blender/blenkernel/intern/displist.cc
+++ b/source/blender/blenkernel/intern/displist.cc
@@ -865,7 +865,7 @@ static GeometrySet curve_calc_modifiers_post(Depsgraph *depsgraph,
else {
std::unique_ptr<CurveEval> curve_eval = curve_eval_from_dna_curve(
*cu, ob->runtime.curve_cache->deformed_nurbs);
- geometry_set.replace_curve(curve_eval.release());
+ geometry_set.replace_curve(curve_eval_to_curves(*curve_eval));
}
for (; md; md = md->next) {
@@ -1497,7 +1497,7 @@ void BKE_displist_make_curveTypes(Depsgraph *depsgraph,
* the CurveEval data type was introduced, when an evaluated object's curve data was just a
* copy of the original curve and everything else ended up in #CurveCache. */
CurveComponent &curve_component = geometry.get_component_for_write<CurveComponent>();
- cow_curve.curve_eval = curve_component.get_for_write();
+ cow_curve.curve_eval = curves_to_curve_eval(*curve_component.get_for_read()).release();
BKE_object_eval_assign_data(ob, &cow_curve.id, false);
}
diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc
index c22b6ff07ec..0926d65b306 100644
--- a/source/blender/blenkernel/intern/geometry_component_curve.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curve.cc
@@ -23,18 +23,18 @@ using blender::fn::GVArray_GSpan;
/** \name Geometry Component Implementation
* \{ */
-CurveComponent::CurveComponent() : GeometryComponent(GEO_COMPONENT_TYPE_CURVE)
+CurveComponentLegacy::CurveComponentLegacy() : GeometryComponent(GEO_COMPONENT_TYPE_CURVE)
{
}
-CurveComponent::~CurveComponent()
+CurveComponentLegacy::~CurveComponentLegacy()
{
this->clear();
}
-GeometryComponent *CurveComponent::copy() const
+GeometryComponent *CurveComponentLegacy::copy() const
{
- CurveComponent *new_component = new CurveComponent();
+ CurveComponentLegacy *new_component = new CurveComponentLegacy();
if (curve_ != nullptr) {
new_component->curve_ = new CurveEval(*curve_);
new_component->ownership_ = GeometryOwnershipType::Owned;
@@ -42,30 +42,23 @@ GeometryComponent *CurveComponent::copy() const
return new_component;
}
-void CurveComponent::clear()
+void CurveComponentLegacy::clear()
{
BLI_assert(this->is_mutable());
if (curve_ != nullptr) {
if (ownership_ == GeometryOwnershipType::Owned) {
delete curve_;
}
- if (curve_for_render_ != nullptr) {
- /* The curve created by this component should not have any edit mode data. */
- BLI_assert(curve_for_render_->editfont == nullptr && curve_for_render_->editnurb == nullptr);
- BKE_id_free(nullptr, curve_for_render_);
- curve_for_render_ = nullptr;
- }
-
curve_ = nullptr;
}
}
-bool CurveComponent::has_curve() const
+bool CurveComponentLegacy::has_curve() const
{
return curve_ != nullptr;
}
-void CurveComponent::replace(CurveEval *curve, GeometryOwnershipType ownership)
+void CurveComponentLegacy::replace(CurveEval *curve, GeometryOwnershipType ownership)
{
BLI_assert(this->is_mutable());
this->clear();
@@ -73,7 +66,7 @@ void CurveComponent::replace(CurveEval *curve, GeometryOwnershipType ownership)
ownership_ = ownership;
}
-CurveEval *CurveComponent::release()
+CurveEval *CurveComponentLegacy::release()
{
BLI_assert(this->is_mutable());
CurveEval *curve = curve_;
@@ -81,12 +74,12 @@ CurveEval *CurveComponent::release()
return curve;
}
-const CurveEval *CurveComponent::get_for_read() const
+const CurveEval *CurveComponentLegacy::get_for_read() const
{
return curve_;
}
-CurveEval *CurveComponent::get_for_write()
+CurveEval *CurveComponentLegacy::get_for_write()
{
BLI_assert(this->is_mutable());
if (ownership_ == GeometryOwnershipType::ReadOnly) {
@@ -96,17 +89,17 @@ CurveEval *CurveComponent::get_for_write()
return curve_;
}
-bool CurveComponent::is_empty() const
+bool CurveComponentLegacy::is_empty() const
{
return curve_ == nullptr;
}
-bool CurveComponent::owns_direct_data() const
+bool CurveComponentLegacy::owns_direct_data() const
{
return ownership_ == GeometryOwnershipType::Owned;
}
-void CurveComponent::ensure_owns_direct_data()
+void CurveComponentLegacy::ensure_owns_direct_data()
{
BLI_assert(this->is_mutable());
if (ownership_ != GeometryOwnershipType::Owned) {
@@ -115,32 +108,13 @@ void CurveComponent::ensure_owns_direct_data()
}
}
-const Curve *CurveComponent::get_curve_for_render() const
-{
- if (curve_ == nullptr) {
- return nullptr;
- }
- if (curve_for_render_ != nullptr) {
- return curve_for_render_;
- }
- std::lock_guard lock{curve_for_render_mutex_};
- if (curve_for_render_ != nullptr) {
- return curve_for_render_;
- }
-
- curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU_LEGACY, nullptr);
- curve_for_render_->curve_eval = curve_;
-
- return curve_for_render_;
-}
-
/** \} */
/* -------------------------------------------------------------------- */
/** \name Attribute Access Helper Functions
* \{ */
-int CurveComponent::attribute_domain_size(const AttributeDomain domain) const
+int CurveComponentLegacy::attribute_domain_size(const AttributeDomain domain) const
{
if (curve_ == nullptr) {
return 0;
@@ -334,9 +308,10 @@ static GVArray adapt_curve_domain_spline_to_point(const CurveEval &curve, GVArra
} // namespace blender::bke
-GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray,
- const AttributeDomain from_domain,
- const AttributeDomain to_domain) const
+GVArray CurveComponentLegacy::attribute_try_adapt_domain_impl(
+ const GVArray &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const
{
if (!varray) {
return {};
@@ -361,14 +336,15 @@ GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray,
static CurveEval *get_curve_from_component_for_write(GeometryComponent &component)
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE);
- CurveComponent &curve_component = static_cast<CurveComponent &>(component);
+ CurveComponentLegacy &curve_component = static_cast<CurveComponentLegacy &>(component);
return curve_component.get_for_write();
}
static const CurveEval *get_curve_from_component_for_read(const GeometryComponent &component)
{
BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE);
- const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
+ const CurveComponentLegacy &curve_component = static_cast<const CurveComponentLegacy &>(
+ component);
return curve_component.get_for_read();
}
@@ -377,101 +353,6 @@ static const CurveEval *get_curve_from_component_for_read(const GeometryComponen
namespace blender::bke {
/* -------------------------------------------------------------------- */
-/** \name Curve Normals Access
- * \{ */
-
-static void calculate_bezier_normals(const BezierSpline &spline, MutableSpan<float3> normals)
-{
- Span<int> offsets = spline.control_point_offsets();
- Span<float3> evaluated_normals = spline.evaluated_normals();
- for (const int i : IndexRange(spline.size())) {
- normals[i] = evaluated_normals[offsets[i]];
- }
-}
-
-static void calculate_poly_normals(const PolySpline &spline, MutableSpan<float3> normals)
-{
- normals.copy_from(spline.evaluated_normals());
-}
-
-/**
- * Because NURBS control points are not necessarily on the path, the normal at the control points
- * is not well defined, so create a temporary poly spline to find the normals. This requires extra
- * copying currently, but may be more efficient in the future if attributes have some form of CoW.
- */
-static void calculate_nurbs_normals(const NURBSpline &spline, MutableSpan<float3> normals)
-{
- PolySpline poly_spline;
- poly_spline.resize(spline.size());
- poly_spline.positions().copy_from(spline.positions());
- poly_spline.tilts().copy_from(spline.tilts());
- normals.copy_from(poly_spline.evaluated_normals());
-}
-
-static Array<float3> curve_normal_point_domain(const CurveEval &curve)
-{
- Span<SplinePtr> splines = curve.splines();
- Array<int> offsets = curve.control_point_offsets();
- const int total_size = offsets.last();
- Array<float3> normals(total_size);
-
- threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- const Spline &spline = *splines[i];
- MutableSpan spline_normals{normals.as_mutable_span().slice(offsets[i], spline.size())};
- switch (splines[i]->type()) {
- case CURVE_TYPE_BEZIER:
- calculate_bezier_normals(static_cast<const BezierSpline &>(spline), spline_normals);
- break;
- case CURVE_TYPE_POLY:
- calculate_poly_normals(static_cast<const PolySpline &>(spline), spline_normals);
- break;
- case CURVE_TYPE_NURBS:
- calculate_nurbs_normals(static_cast<const NURBSpline &>(spline), spline_normals);
- break;
- case CURVE_TYPE_CATMULL_ROM:
- BLI_assert_unreachable();
- break;
- }
- }
- });
- return normals;
-}
-
-VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain)
-{
- const CurveEval *curve = component.get_for_read();
- if (curve == nullptr) {
- return nullptr;
- }
-
- if (domain == ATTR_DOMAIN_POINT) {
- const Span<SplinePtr> splines = curve->splines();
-
- /* Use a reference to evaluated normals if possible to avoid an allocation and a copy.
- * This is only possible when there is only one poly spline. */
- if (splines.size() == 1 && splines.first()->type() == CURVE_TYPE_POLY) {
- const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
- return VArray<float3>::ForSpan(spline.evaluated_normals());
- }
-
- Array<float3> normals = curve_normal_point_domain(*curve);
- return VArray<float3>::ForContainer(std::move(normals));
- }
-
- if (domain == ATTR_DOMAIN_CURVE) {
- Array<float3> point_normals = curve_normal_point_domain(*curve);
- VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals));
- return component.attribute_try_adapt_domain<float3>(
- std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
- }
-
- return nullptr;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Builtin Spline Attributes
*
* Attributes with a value for every spline, stored contiguously or in every spline separately.
@@ -1306,7 +1187,8 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider {
private:
static constexpr uint64_t supported_types_mask = CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 |
CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 |
- CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL;
+ CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL |
+ CD_MASK_PROP_INT8;
public:
ReadAttributeLookup try_get_for_read(const GeometryComponent &component,
@@ -1551,7 +1433,8 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
} // namespace blender::bke
-const blender::bke::ComponentAttributeProviders *CurveComponent::get_attribute_providers() const
+const blender::bke::ComponentAttributeProviders *CurveComponentLegacy::get_attribute_providers()
+ const
{
static blender::bke::ComponentAttributeProviders providers =
blender::bke::create_attribute_providers_for_curve();
diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc
new file mode 100644
index 00000000000..e32dd852e0e
--- /dev/null
+++ b/source/blender/blenkernel/intern/geometry_component_curves.cc
@@ -0,0 +1,521 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BLI_task.hh"
+
+#include "DNA_ID_enums.h"
+#include "DNA_curve_types.h"
+
+#include "BKE_attribute_access.hh"
+#include "BKE_attribute_math.hh"
+#include "BKE_curve.h"
+#include "BKE_curves.hh"
+#include "BKE_geometry_set.hh"
+#include "BKE_lib_id.h"
+#include "BKE_spline.hh"
+
+#include "attribute_access_intern.hh"
+
+using blender::fn::GVArray;
+
+/* -------------------------------------------------------------------- */
+/** \name Geometry Component Implementation
+ * \{ */
+
+CurveComponent::CurveComponent() : GeometryComponent(GEO_COMPONENT_TYPE_CURVE)
+{
+}
+
+CurveComponent::~CurveComponent()
+{
+ this->clear();
+}
+
+GeometryComponent *CurveComponent::copy() const
+{
+ CurveComponent *new_component = new CurveComponent();
+ if (curves_ != nullptr) {
+ new_component->curves_ = BKE_curves_copy_for_eval(curves_, false);
+ new_component->ownership_ = GeometryOwnershipType::Owned;
+ }
+ return new_component;
+}
+
+void CurveComponent::clear()
+{
+ BLI_assert(this->is_mutable());
+ if (curves_ != nullptr) {
+ if (ownership_ == GeometryOwnershipType::Owned) {
+ BKE_id_free(nullptr, curves_);
+ }
+ if (curve_for_render_ != nullptr) {
+ /* The curve created by this component should not have any edit mode data. */
+ BLI_assert(curve_for_render_->editfont == nullptr && curve_for_render_->editnurb == nullptr);
+ BKE_id_free(nullptr, curve_for_render_);
+ curve_for_render_ = nullptr;
+ }
+
+ curves_ = nullptr;
+ }
+}
+
+bool CurveComponent::has_curves() const
+{
+ return curves_ != nullptr;
+}
+
+void CurveComponent::replace(Curves *curves, GeometryOwnershipType ownership)
+{
+ BLI_assert(this->is_mutable());
+ this->clear();
+ curves_ = curves;
+ ownership_ = ownership;
+}
+
+Curves *CurveComponent::release()
+{
+ BLI_assert(this->is_mutable());
+ Curves *curves = curves_;
+ curves_ = nullptr;
+ return curves;
+}
+
+const Curves *CurveComponent::get_for_read() const
+{
+ return curves_;
+}
+
+Curves *CurveComponent::get_for_write()
+{
+ BLI_assert(this->is_mutable());
+ if (ownership_ == GeometryOwnershipType::ReadOnly) {
+ curves_ = BKE_curves_copy_for_eval(curves_, false);
+ ownership_ = GeometryOwnershipType::Owned;
+ }
+ return curves_;
+}
+
+bool CurveComponent::is_empty() const
+{
+ return curves_ == nullptr;
+}
+
+bool CurveComponent::owns_direct_data() const
+{
+ return ownership_ == GeometryOwnershipType::Owned;
+}
+
+void CurveComponent::ensure_owns_direct_data()
+{
+ BLI_assert(this->is_mutable());
+ if (ownership_ != GeometryOwnershipType::Owned) {
+ curves_ = BKE_curves_copy_for_eval(curves_, false);
+ ownership_ = GeometryOwnershipType::Owned;
+ }
+}
+
+const Curve *CurveComponent::get_curve_for_render() const
+{
+ if (curves_ == nullptr) {
+ return nullptr;
+ }
+ if (curve_for_render_ != nullptr) {
+ return curve_for_render_;
+ }
+ std::lock_guard lock{curve_for_render_mutex_};
+ if (curve_for_render_ != nullptr) {
+ return curve_for_render_;
+ }
+
+ curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU_LEGACY, nullptr);
+ curve_for_render_->curve_eval = curves_to_curve_eval(*curves_).release();
+
+ return curve_for_render_;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Curve Normals Access
+ * \{ */
+
+namespace blender::bke {
+
+static void calculate_bezier_normals(const BezierSpline &spline, MutableSpan<float3> normals)
+{
+ Span<int> offsets = spline.control_point_offsets();
+ Span<float3> evaluated_normals = spline.evaluated_normals();
+ for (const int i : IndexRange(spline.size())) {
+ normals[i] = evaluated_normals[offsets[i]];
+ }
+}
+
+static void calculate_poly_normals(const PolySpline &spline, MutableSpan<float3> normals)
+{
+ normals.copy_from(spline.evaluated_normals());
+}
+
+/**
+ * Because NURBS control points are not necessarily on the path, the normal at the control points
+ * is not well defined, so create a temporary poly spline to find the normals. This requires extra
+ * copying currently, but may be more efficient in the future if attributes have some form of CoW.
+ */
+static void calculate_nurbs_normals(const NURBSpline &spline, MutableSpan<float3> normals)
+{
+ PolySpline poly_spline;
+ poly_spline.resize(spline.size());
+ poly_spline.positions().copy_from(spline.positions());
+ poly_spline.tilts().copy_from(spline.tilts());
+ normals.copy_from(poly_spline.evaluated_normals());
+}
+
+static Array<float3> curve_normal_point_domain(const CurveEval &curve)
+{
+ Span<SplinePtr> splines = curve.splines();
+ Array<int> offsets = curve.control_point_offsets();
+ const int total_size = offsets.last();
+ Array<float3> normals(total_size);
+
+ threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
+ for (const int i : range) {
+ const Spline &spline = *splines[i];
+ MutableSpan spline_normals{normals.as_mutable_span().slice(offsets[i], spline.size())};
+ switch (splines[i]->type()) {
+ case CURVE_TYPE_BEZIER:
+ calculate_bezier_normals(static_cast<const BezierSpline &>(spline), spline_normals);
+ break;
+ case CURVE_TYPE_POLY:
+ calculate_poly_normals(static_cast<const PolySpline &>(spline), spline_normals);
+ break;
+ case CURVE_TYPE_NURBS:
+ calculate_nurbs_normals(static_cast<const NURBSpline &>(spline), spline_normals);
+ break;
+ case CURVE_TYPE_CATMULL_ROM:
+ BLI_assert_unreachable();
+ break;
+ }
+ }
+ });
+ return normals;
+}
+
+VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain)
+{
+ if (component.is_empty()) {
+ return nullptr;
+ }
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
+
+ if (domain == ATTR_DOMAIN_POINT) {
+ Array<float3> normals = curve_normal_point_domain(*curve);
+ return VArray<float3>::ForContainer(std::move(normals));
+ }
+
+ if (domain == ATTR_DOMAIN_CURVE) {
+ Array<float3> point_normals = curve_normal_point_domain(*curve);
+ VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals));
+ return component.attribute_try_adapt_domain<float3>(
+ std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
+ }
+
+ return nullptr;
+}
+
+} // namespace blender::bke
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Attribute Access Helper Functions
+ * \{ */
+
+int CurveComponent::attribute_domain_size(const AttributeDomain domain) const
+{
+ if (curves_ == nullptr) {
+ return 0;
+ }
+ const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(
+ curves_->geometry);
+ if (domain == ATTR_DOMAIN_POINT) {
+ return geometry.points_size();
+ }
+ if (domain == ATTR_DOMAIN_CURVE) {
+ return geometry.curves_size();
+ }
+ return 0;
+}
+
+GVArray CurveComponent::attribute_try_adapt_domain_impl(const GVArray &varray,
+ const AttributeDomain from_domain,
+ const AttributeDomain to_domain) const
+{
+ return blender::bke::CurvesGeometry::wrap(curves_->geometry)
+ .adapt_domain(varray, from_domain, to_domain);
+}
+
+static Curves *get_curves_from_component_for_write(GeometryComponent &component)
+{
+ BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE);
+ CurveComponent &curve_component = static_cast<CurveComponent &>(component);
+ return curve_component.get_for_write();
+}
+
+static const Curves *get_curves_from_component_for_read(const GeometryComponent &component)
+{
+ BLI_assert(component.type() == GEO_COMPONENT_TYPE_CURVE);
+ const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
+ return curve_component.get_for_read();
+}
+
+static void tag_component_topology_changed(GeometryComponent &component)
+{
+ Curves *curves = get_curves_from_component_for_write(component);
+ if (curves) {
+ blender::bke::CurvesGeometry::wrap(curves->geometry).tag_topology_changed();
+ }
+}
+
+static void tag_component_positions_changed(GeometryComponent &component)
+{
+ Curves *curves = get_curves_from_component_for_write(component);
+ if (curves) {
+ blender::bke::CurvesGeometry::wrap(curves->geometry).tag_positions_changed();
+ }
+}
+
+static void tag_component_normals_changed(GeometryComponent &component)
+{
+ Curves *curves = get_curves_from_component_for_write(component);
+ if (curves) {
+ blender::bke::CurvesGeometry::wrap(curves->geometry).tag_normals_changed();
+ }
+}
+
+/** \} */
+
+namespace blender::bke {
+
+/* -------------------------------------------------------------------- */
+/** \name Attribute Provider Declaration
+ * \{ */
+
+/**
+ * In this function all the attribute providers for a curves component are created.
+ * Most data in this function is statically allocated, because it does not change over time.
+ */
+static ComponentAttributeProviders create_attribute_providers_for_curve()
+{
+ static CustomDataAccessInfo curve_access = {
+ [](GeometryComponent &component) -> CustomData * {
+ Curves *curves = get_curves_from_component_for_write(component);
+ return curves ? &curves->geometry.curve_data : nullptr;
+ },
+ [](const GeometryComponent &component) -> const CustomData * {
+ const Curves *curves = get_curves_from_component_for_read(component);
+ return curves ? &curves->geometry.curve_data : nullptr;
+ },
+ [](GeometryComponent &component) {
+ Curves *curves = get_curves_from_component_for_write(component);
+ if (curves) {
+ blender::bke::CurvesGeometry::wrap(curves->geometry).update_customdata_pointers();
+ }
+ }};
+ static CustomDataAccessInfo point_access = {
+ [](GeometryComponent &component) -> CustomData * {
+ Curves *curves = get_curves_from_component_for_write(component);
+ return curves ? &curves->geometry.point_data : nullptr;
+ },
+ [](const GeometryComponent &component) -> const CustomData * {
+ const Curves *curves = get_curves_from_component_for_read(component);
+ return curves ? &curves->geometry.point_data : nullptr;
+ },
+ [](GeometryComponent &component) {
+ Curves *curves = get_curves_from_component_for_write(component);
+ if (curves) {
+ blender::bke::CurvesGeometry::wrap(curves->geometry).update_customdata_pointers();
+ }
+ }};
+
+ static BuiltinCustomDataLayerProvider position("position",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT3,
+ CD_PROP_FLOAT3,
+ BuiltinAttributeProvider::NonCreatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::NonDeletable,
+ point_access,
+ make_array_read_attribute<float3>,
+ make_array_write_attribute<float3>,
+ tag_component_positions_changed);
+
+ static BuiltinCustomDataLayerProvider radius("radius",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT,
+ CD_PROP_FLOAT,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<float>,
+ make_array_write_attribute<float>,
+ tag_component_normals_changed);
+
+ static BuiltinCustomDataLayerProvider id("id",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_INT32,
+ CD_PROP_INT32,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<int>,
+ make_array_write_attribute<int>,
+ nullptr);
+
+ static BuiltinCustomDataLayerProvider tilt("tilt",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT,
+ CD_PROP_FLOAT,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<float>,
+ make_array_write_attribute<float>,
+ tag_component_normals_changed);
+
+ static BuiltinCustomDataLayerProvider handle_right("handle_right",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT3,
+ CD_PROP_FLOAT3,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<float3>,
+ make_array_write_attribute<float3>,
+ tag_component_positions_changed);
+
+ static BuiltinCustomDataLayerProvider handle_left("handle_left",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT3,
+ CD_PROP_FLOAT3,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<float3>,
+ make_array_write_attribute<float3>,
+ tag_component_positions_changed);
+
+ static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_INT8,
+ CD_PROP_INT8,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<int8_t>,
+ make_array_write_attribute<int8_t>,
+ tag_component_topology_changed);
+
+ static BuiltinCustomDataLayerProvider handle_type_left("handle_type_left",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_INT8,
+ CD_PROP_INT8,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<int8_t>,
+ make_array_write_attribute<int8_t>,
+ tag_component_topology_changed);
+
+ static BuiltinCustomDataLayerProvider nurbs_weight("nurbs_weight",
+ ATTR_DOMAIN_POINT,
+ CD_PROP_FLOAT,
+ CD_PROP_FLOAT,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ point_access,
+ make_array_read_attribute<float>,
+ make_array_write_attribute<float>,
+ tag_component_positions_changed);
+
+ static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order",
+ ATTR_DOMAIN_CURVE,
+ CD_PROP_INT32,
+ CD_PROP_INT32,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ curve_access,
+ make_array_read_attribute<int>,
+ make_array_write_attribute<int>,
+ tag_component_topology_changed);
+
+ static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode",
+ ATTR_DOMAIN_CURVE,
+ CD_PROP_INT8,
+ CD_PROP_INT8,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ curve_access,
+ make_array_read_attribute<int8_t>,
+ make_array_write_attribute<int8_t>,
+ tag_component_topology_changed);
+
+ static BuiltinCustomDataLayerProvider resolution("resolution",
+ ATTR_DOMAIN_CURVE,
+ CD_PROP_INT32,
+ CD_PROP_INT32,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ curve_access,
+ make_array_read_attribute<int>,
+ make_array_write_attribute<int>,
+ tag_component_positions_changed);
+
+ static BuiltinCustomDataLayerProvider cyclic("cyclic",
+ ATTR_DOMAIN_CURVE,
+ CD_PROP_BOOL,
+ CD_PROP_BOOL,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ curve_access,
+ make_array_read_attribute<bool>,
+ make_array_write_attribute<bool>,
+ tag_component_topology_changed);
+
+ static CustomDataAttributeProvider curve_custom_data(ATTR_DOMAIN_CURVE, curve_access);
+ static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access);
+
+ return ComponentAttributeProviders({&position,
+ &radius,
+ &id,
+ &tilt,
+ &handle_right,
+ &handle_left,
+ &handle_type_right,
+ &handle_type_left,
+ &nurbs_order,
+ &nurbs_weight,
+ &resolution,
+ &cyclic},
+ {&curve_custom_data, &point_custom_data});
+}
+
+/** \} */
+
+} // namespace blender::bke
+
+const blender::bke::ComponentAttributeProviders *CurveComponent::get_attribute_providers() const
+{
+ static blender::bke::ComponentAttributeProviders providers =
+ blender::bke::create_attribute_providers_for_curve();
+ return &providers;
+}
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 13441b4914a..73572e30d61 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -7,6 +7,7 @@
#include "BKE_attribute.h"
#include "BKE_attribute_access.hh"
+#include "BKE_curves.hh"
#include "BKE_geometry_set.hh"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
@@ -186,8 +187,9 @@ bool GeometrySet::compute_boundbox_without_instances(float3 *r_min, float3 *r_ma
if (volume != nullptr) {
have_minmax |= BKE_volume_min_max(volume, *r_min, *r_max);
}
- const CurveEval *curve = this->get_curve_for_read();
- if (curve != nullptr) {
+ const Curves *curves = this->get_curve_for_read();
+ if (curves != nullptr) {
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves);
/* Using the evaluated positions is somewhat arbitrary, but it is probably expected. */
have_minmax |= curve->bounds_min_max(*r_min, *r_max, true);
}
@@ -258,7 +260,7 @@ const Volume *GeometrySet::get_volume_for_read() const
return (component == nullptr) ? nullptr : component->get_for_read();
}
-const CurveEval *GeometrySet::get_curve_for_read() const
+const Curves *GeometrySet::get_curve_for_read() const
{
const CurveComponent *component = this->get_component_for_read<CurveComponent>();
return (component == nullptr) ? nullptr : component->get_for_read();
@@ -285,7 +287,7 @@ bool GeometrySet::has_volume() const
bool GeometrySet::has_curve() const
{
const CurveComponent *component = this->get_component_for_read<CurveComponent>();
- return component != nullptr && component->has_curve();
+ return component != nullptr && component->has_curves();
}
bool GeometrySet::has_realized_data() const
@@ -327,12 +329,12 @@ GeometrySet GeometrySet::create_with_pointcloud(PointCloud *pointcloud,
return geometry_set;
}
-GeometrySet GeometrySet::create_with_curve(CurveEval *curve, GeometryOwnershipType ownership)
+GeometrySet GeometrySet::create_with_curve(Curves *curves, GeometryOwnershipType ownership)
{
GeometrySet geometry_set;
- if (curve != nullptr) {
+ if (curves != nullptr) {
CurveComponent &component = geometry_set.get_component_for_write<CurveComponent>();
- component.replace(curve, ownership);
+ component.replace(curves, ownership);
}
return geometry_set;
}
@@ -351,18 +353,18 @@ void GeometrySet::replace_mesh(Mesh *mesh, GeometryOwnershipType ownership)
component.replace(mesh, ownership);
}
-void GeometrySet::replace_curve(CurveEval *curve, GeometryOwnershipType ownership)
+void GeometrySet::replace_curve(Curves *curves, GeometryOwnershipType ownership)
{
- if (curve == nullptr) {
+ if (curves == nullptr) {
this->remove<CurveComponent>();
return;
}
- if (curve == this->get_curve_for_read()) {
+ if (curves == this->get_curve_for_read()) {
return;
}
this->remove<CurveComponent>();
CurveComponent &component = this->get_component_for_write<CurveComponent>();
- component.replace(curve, ownership);
+ component.replace(curves, ownership);
}
void GeometrySet::replace_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership)
@@ -411,7 +413,7 @@ Volume *GeometrySet::get_volume_for_write()
return component == nullptr ? nullptr : component->get_for_write();
}
-CurveEval *GeometrySet::get_curve_for_write()
+Curves *GeometrySet::get_curve_for_write()
{
CurveComponent *component = this->get_component_ptr<CurveComponent>();
return component == nullptr ? nullptr : component->get_for_write();
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index 5af599f0302..6b5c04ac25e 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -953,7 +953,7 @@ static const Mesh *get_evaluated_mesh_from_object(const Object *object)
return nullptr;
}
-static const CurveEval *get_evaluated_curve_from_object(const Object *object)
+static const Curves *get_evaluated_curves_from_object(const Object *object)
{
GeometrySet *geometry_set_eval = object->runtime.geometry_set_eval;
if (geometry_set_eval) {
@@ -968,8 +968,9 @@ static Mesh *mesh_new_from_evaluated_curve_type_object(const Object *evaluated_o
if (mesh) {
return BKE_mesh_copy_for_eval(mesh, false);
}
- const CurveEval *curve = get_evaluated_curve_from_object(evaluated_object);
- if (curve) {
+ const Curves *curves = get_evaluated_curves_from_object(evaluated_object);
+ if (curves) {
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves);
return blender::bke::curve_to_wire_mesh(*curve);
}
return nullptr;
diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc
index c98bd9d6b74..149ae70dda1 100644
--- a/source/blender/geometry/intern/realize_instances.cc
+++ b/source/blender/geometry/intern/realize_instances.cc
@@ -13,6 +13,7 @@
#include "BLI_task.hh"
#include "BKE_collection.h"
+#include "BKE_curves.hh"
#include "BKE_geometry_set_instances.hh"
#include "BKE_material.h"
#include "BKE_mesh.h"
@@ -118,7 +119,7 @@ struct RealizeMeshTask {
};
struct RealizeCurveInfo {
- const CurveEval *curve = nullptr;
+ const Curves *curves;
/**
* Matches the order in #AllCurvesInfo.attributes. For point attributes, the `std::optional`
* will be empty.
@@ -163,7 +164,7 @@ struct AllCurvesInfo {
/** Ordering of all attributes that are propagated to the output curve generically. */
OrderedAttributes attributes;
/** Ordering of the original curves that are joined. */
- VectorSet<const CurveEval *> order;
+ VectorSet<const Curves *> order;
/** Preprocessed data about every original curve. This is ordered by #order. */
Array<RealizeCurveInfo> realize_info;
bool create_id_attribute = false;
@@ -443,16 +444,16 @@ static void gather_realize_tasks_recursive(GatherTasksInfo &gather_info,
}
case GEO_COMPONENT_TYPE_CURVE: {
const CurveComponent &curve_component = *static_cast<const CurveComponent *>(component);
- const CurveEval *curve = curve_component.get_for_read();
- if (curve != nullptr && !curve->splines().is_empty()) {
- const int curve_index = gather_info.curves.order.index_of(curve);
+ const Curves *curves = curve_component.get_for_read();
+ if (curves != nullptr && curves->geometry.curve_size > 0) {
+ const int curve_index = gather_info.curves.order.index_of(curves);
const RealizeCurveInfo &curve_info = gather_info.curves.realize_info[curve_index];
gather_info.r_tasks.curve_tasks.append({gather_info.r_offsets.spline_offset,
&curve_info,
base_transform,
base_instance_context.curves,
base_instance_context.id});
- gather_info.r_offsets.spline_offset += curve->splines().size();
+ gather_info.r_offsets.spline_offset += curves->geometry.curve_size;
}
break;
}
@@ -1038,11 +1039,11 @@ static OrderedAttributes gather_generic_curve_attributes_to_propagate(
}
static void gather_curves_to_realize(const GeometrySet &geometry_set,
- VectorSet<const CurveEval *> &r_curves)
+ VectorSet<const Curves *> &r_curves)
{
- if (const CurveEval *curve = geometry_set.get_curve_for_read()) {
- if (!curve->splines().is_empty()) {
- r_curves.add(curve);
+ if (const Curves *curves = geometry_set.get_curve_for_read()) {
+ if (curves->geometry.curve_size != 0) {
+ r_curves.add(curves);
}
}
if (const InstancesComponent *instances =
@@ -1064,12 +1065,12 @@ static AllCurvesInfo preprocess_curves(const GeometrySet &geometry_set,
info.realize_info.reinitialize(info.order.size());
for (const int curve_index : info.realize_info.index_range()) {
RealizeCurveInfo &curve_info = info.realize_info[curve_index];
- const CurveEval *curve = info.order[curve_index];
- curve_info.curve = curve;
+ const Curves *curves = info.order[curve_index];
+ curve_info.curves = curves;
/* Access attributes. */
CurveComponent component;
- component.replace(const_cast<CurveEval *>(curve), GeometryOwnershipType::ReadOnly);
+ component.replace(const_cast<Curves *>(curves), GeometryOwnershipType::ReadOnly);
curve_info.spline_attributes.reinitialize(info.attributes.size());
for (const int attribute_index : info.attributes.index_range()) {
const AttributeDomain domain = info.attributes.kinds[attribute_index].domain;
@@ -1095,9 +1096,9 @@ static void execute_realize_curve_task(const RealizeInstancesOptions &options,
MutableSpan<GMutableSpan> dst_spline_attributes)
{
const RealizeCurveInfo &curve_info = *task.curve_info;
- const CurveEval &curve = *curve_info.curve;
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_info.curves);
- const Span<SplinePtr> src_splines = curve.splines();
+ const Span<SplinePtr> src_splines = curve->splines();
/* Initialize point attributes. */
threading::parallel_for(src_splines.index_range(), 100, [&](const IndexRange src_spline_range) {
@@ -1206,12 +1207,12 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
}
const RealizeCurveTask &last_task = tasks.last();
- const CurveEval &last_curve = *last_task.curve_info->curve;
- const int tot_splines = last_task.start_spline_index + last_curve.splines().size();
+ const Curves &last_curves = *last_task.curve_info->curves;
+ const int tot_splines = last_task.start_spline_index + last_curves.geometry.curve_size;
Array<SplinePtr> dst_splines(tot_splines);
- CurveEval *dst_curve = new CurveEval();
+ std::unique_ptr<CurveEval> dst_curve = std::make_unique<CurveEval>();
dst_curve->attributes.reallocate(tot_splines);
CustomDataAttributes &spline_attributes = dst_curve->attributes;
@@ -1242,7 +1243,7 @@ static void execute_realize_curve_tasks(const RealizeInstancesOptions &options,
dst_curve->add_splines(dst_splines);
CurveComponent &dst_component = r_realized_geometry.get_component_for_write<CurveComponent>();
- dst_component.replace(dst_curve);
+ dst_component.replace(curve_eval_to_curves(*dst_curve));
}
/** \} */
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc
index b83aa8b69a9..e6f3e483f1f 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_endpoints.cc
@@ -143,9 +143,9 @@ static void node_geo_exec(GeoNodeExecParams params)
}
const CurveComponent &curve_component = *geometry_set.get_component_for_read<CurveComponent>();
- const CurveEval &curve = *curve_component.get_for_read();
- const Span<SplinePtr> splines = curve.splines();
- curve.assert_valid_point_attributes();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
+ const Span<SplinePtr> splines = curve->splines();
+ curve->assert_valid_point_attributes();
evaluate_splines(splines);
@@ -167,9 +167,9 @@ static void node_geo_exec(GeoNodeExecParams params)
end_result.get_component_for_write<PointCloudComponent>();
CurveToPointsResults start_attributes = curve_to_points_create_result_attributes(
- start_point_component, curve);
+ start_point_component, *curve);
CurveToPointsResults end_attributes = curve_to_points_create_result_attributes(
- end_point_component, curve);
+ end_point_component, *curve);
copy_endpoint_attributes(splines, offsets.as_span(), start_attributes, end_attributes);
copy_spline_domain_attributes(curve_component, offsets.as_span(), start_point_component);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
index 6deaf5b554a..78e36784be7 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_reverse.cc
@@ -26,8 +26,8 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Retrieve data for write access so we can avoid new allocations for the reversed data. */
CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- CurveEval &curve = *curve_component.get_for_write();
- MutableSpan<SplinePtr> splines = curve.splines();
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
+ MutableSpan<SplinePtr> splines = curve->splines();
const std::string selection_name = params.extract_input<std::string>("Selection");
VArray<bool> selection = curve_component.attribute_get_for_read(
@@ -41,6 +41,8 @@ static void node_geo_exec(GeoNodeExecParams params)
}
});
+ geometry_set.replace_curve(curve_eval_to_curves(*curve));
+
params.set_output("Curve", geometry_set);
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc
index a09a751b550..729ccca5f04 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_select_by_handle_type.cc
@@ -89,9 +89,8 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set = geometry::realize_instances_legacy(geometry_set);
CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- const CurveEval *curve = curve_component.get_for_read();
-
- if (curve != nullptr) {
+ if (curve_component.has_curves()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
const std::string selection_name = params.extract_input<std::string>("Selection");
OutputAttribute_Typed<bool> selection =
curve_component.attribute_try_get_for_output_only<bool>(selection_name, ATTR_DOMAIN_POINT);
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
index e5d4d6c1d0f..8ab43909a20 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_set_handles.cc
@@ -63,8 +63,8 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Retrieve data for write access so we can avoid new allocations for the handles data. */
CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- CurveEval &curve = *curve_component.get_for_write();
- MutableSpan<SplinePtr> splines = curve.splines();
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
+ MutableSpan<SplinePtr> splines = curve->splines();
const std::string selection_name = params.extract_input<std::string>("Selection");
VArray<bool> selection = curve_component.attribute_get_for_read(
@@ -101,6 +101,8 @@ static void node_geo_exec(GeoNodeExecParams params)
bezier_spline.mark_cache_invalid();
}
+ geometry_set.replace_curve(curve_eval_to_curves(*curve));
+
if (!has_bezier_spline) {
params.error_message_add(NodeWarningType::Info, TIP_("No Bezier splines in input curve"));
}
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
index 87b8bbf8786..e15e7339107 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_spline_type.cc
@@ -242,34 +242,34 @@ static void node_geo_exec(GeoNodeExecParams params)
}
const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>();
- const CurveEval &curve = *curve_component->get_for_read();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component->get_for_read());
const std::string selection_name = params.extract_input<std::string>("Selection");
VArray<bool> selection = curve_component->attribute_get_for_read(
selection_name, ATTR_DOMAIN_CURVE, true);
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();
- for (const int i : curve.splines().index_range()) {
+ for (const int i : curve->splines().index_range()) {
if (selection[i]) {
switch (output_type) {
case GEO_NODE_SPLINE_TYPE_POLY:
- new_curve->add_spline(convert_to_poly_spline(*curve.splines()[i]));
+ new_curve->add_spline(convert_to_poly_spline(*curve->splines()[i]));
break;
case GEO_NODE_SPLINE_TYPE_BEZIER:
- new_curve->add_spline(convert_to_bezier(*curve.splines()[i], params));
+ new_curve->add_spline(convert_to_bezier(*curve->splines()[i], params));
break;
case GEO_NODE_SPLINE_TYPE_NURBS:
- new_curve->add_spline(convert_to_nurbs(*curve.splines()[i]));
+ new_curve->add_spline(convert_to_nurbs(*curve->splines()[i]));
break;
}
}
else {
- new_curve->add_spline(curve.splines()[i]->copy());
+ new_curve->add_spline(curve->splines()[i]->copy());
}
}
- new_curve->attributes = curve.attributes;
- params.set_output("Curve", GeometrySet::create_with_curve(new_curve.release()));
+ new_curve->attributes = curve->attributes;
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*new_curve)));
}
} // namespace blender::nodes::node_geo_legacy_curve_spline_type_cc
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc
index bce320496a1..2a8ab2990db 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_subdivide.cc
@@ -354,9 +354,11 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
- std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), cuts);
+ std::unique_ptr<CurveEval> output_curve = subdivide_curve(
+ *curves_to_curve_eval(*component.get_for_read()), cuts);
- params.set_output("Geometry", GeometrySet::create_with_curve(output_curve.release()));
+ params.set_output("Geometry",
+ GeometrySet::create_with_curve(curve_eval_to_curves(*output_curve)));
}
} // namespace blender::nodes::node_geo_legacy_curve_subdivide_cc
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc
index 64627e61910..f68dd6b6b0c 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_curve_to_points.cc
@@ -289,13 +289,13 @@ static void node_geo_exec(GeoNodeExecParams params)
}
const CurveComponent &curve_component = *geometry_set.get_component_for_read<CurveComponent>();
- const CurveEval &curve = *curve_component.get_for_read();
- const Span<SplinePtr> splines = curve.splines();
- curve.assert_valid_point_attributes();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
+ const Span<SplinePtr> splines = curve->splines();
+ curve->assert_valid_point_attributes();
evaluate_splines(splines);
- const Array<int> offsets = calculate_spline_point_offsets(params, mode, curve, splines);
+ const Array<int> offsets = calculate_spline_point_offsets(params, mode, *curve, splines);
const int total_size = offsets.last();
if (total_size == 0) {
params.set_output("Geometry", GeometrySet());
@@ -306,7 +306,7 @@ static void node_geo_exec(GeoNodeExecParams params)
PointCloudComponent &point_component = result.get_component_for_write<PointCloudComponent>();
CurveToPointsResults new_attributes = curve_to_points_create_result_attributes(point_component,
- curve);
+ *curve);
switch (mode) {
case GEO_NODE_CURVE_RESAMPLE_COUNT:
case GEO_NODE_CURVE_RESAMPLE_LENGTH:
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc
index 897a1c1cd2d..ca98d83c137 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_delete_geometry.cc
@@ -235,9 +235,9 @@ static void delete_curve_selection(const CurveComponent &in_component,
const bool invert)
{
std::unique_ptr<CurveEval> r_curve = curve_delete(
- *in_component.get_for_read(), selection_name, invert);
+ *curves_to_curve_eval(*in_component.get_for_read()), selection_name, invert);
if (r_curve) {
- r_component.replace(r_curve.release());
+ r_component.replace(curve_eval_to_curves(*r_curve));
}
else {
r_component.clear();
diff --git a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
index ff86a92f2c7..cb5a757811e 100644
--- a/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/legacy/node_geo_legacy_mesh_to_curve.cc
@@ -48,7 +48,7 @@ static void node_geo_exec(GeoNodeExecParams params)
std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert(
component, IndexMask(selected_edge_indices));
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
}
} // namespace blender::nodes::node_geo_legacy_mesh_to_curve_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
index 59147e9b23f..44b9857e791 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_convex_hull.cc
@@ -162,8 +162,9 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
}
if (geometry_set.has_curve()) {
- const CurveEval &curve = *geometry_set.get_curve_for_read();
- for (const SplinePtr &spline : curve.splines()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ for (const SplinePtr &spline : curve->splines()) {
positions_span = spline->evaluated_positions();
total_size += positions_span.size();
count++;
@@ -202,8 +203,9 @@ static Mesh *compute_hull(const GeometrySet &geometry_set)
}
if (geometry_set.has_curve()) {
- const CurveEval &curve = *geometry_set.get_curve_for_read();
- for (const SplinePtr &spline : curve.splines()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ for (const SplinePtr &spline : curve->splines()) {
Span<float3> array = spline->evaluated_positions();
positions.as_mutable_span().slice(offset, array.size()).copy_from(array);
offset += array.size();
@@ -273,7 +275,7 @@ static Mesh *convex_hull_from_instances(const GeometrySet &geometry_set)
read_positions(*set.get_component_for_read<MeshComponent>(), transforms, &coords);
}
if (set.has_curve()) {
- read_curve_positions(*set.get_curve_for_read(), transforms, &coords);
+ read_curve_positions(*curves_to_curve_eval(*set.get_curve_for_read()), transforms, &coords);
}
}
return hull_from_bullet(nullptr, coords);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc
index 65aad0fcbf1..ce3058c7d42 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_endpoint_selection.cc
@@ -59,10 +59,13 @@ class EndpointFieldInput final : public GeometryFieldInput {
}
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
- const CurveEval *curve = curve_component.get_for_read();
+ if (!curve_component.has_curves()) {
+ return nullptr;
+ }
- Array<int> control_point_offsets = curve->control_point_offsets();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
+ Array<int> control_point_offsets = curve->control_point_offsets();
if (curve == nullptr || control_point_offsets.last() == 0) {
return nullptr;
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
index 9824b2b2ece..c1220746c22 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fill.cc
@@ -117,8 +117,9 @@ static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCu
return;
}
- const CurveEval &curve = *geometry_set.get_curve_for_read();
- if (curve.splines().is_empty()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ if (curve->splines().is_empty()) {
geometry_set.replace_curve(nullptr);
return;
}
@@ -127,7 +128,7 @@ static void curve_fill_calculate(GeometrySet &geometry_set, const GeometryNodeCu
CDT_CONSTRAINTS_VALID_BMESH_WITH_HOLES :
CDT_INSIDE_WITH_HOLES;
- const blender::meshintersect::CDT_result<double> results = do_cdt(curve, output_type);
+ const blender::meshintersect::CDT_result<double> results = do_cdt(*curve, output_type);
Mesh *mesh = cdt_to_mesh(results);
geometry_set.replace_mesh(mesh);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
index b8f317a9679..6742b1103ee 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -603,10 +603,10 @@ static void calculate_curve_fillet(GeometrySet &geometry_set,
fillet_param.limit_radius = limit_radius;
- const CurveEval &input_curve = *geometry_set.get_curve_for_read();
- std::unique_ptr<CurveEval> output_curve = fillet_curve(input_curve, fillet_param);
+ 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_curve(output_curve.release());
+ geometry_set.replace_curve(curve_eval_to_curves(*output_curve));
}
static void node_geo_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
index 8dc74aa3dea..ccd3a587e63 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_handle_type_selection.cc
@@ -92,14 +92,14 @@ class HandleTypeFieldInput final : public GeometryFieldInput {
}
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
- const CurveEval *curve = curve_component.get_for_read();
+ const Curves *curve = curve_component.get_for_read();
if (curve == nullptr) {
return {};
}
if (domain == ATTR_DOMAIN_POINT) {
Array<bool> selection(mask.min_array_size());
- select_by_handle_type(*curve, type_, mode_, selection);
+ select_by_handle_type(*curves_to_curve_eval(*curve), type_, mode_, selection);
return VArray<bool>::ForContainer(std::move(selection));
}
return {};
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
index 82621189964..c7c822db983 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_length.cc
@@ -18,9 +18,9 @@ static void node_geo_exec(GeoNodeExecParams params)
params.set_default_remaining_outputs();
return;
}
- const CurveEval &curve = *curve_set.get_curve_for_read();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_set.get_curve_for_read());
float length = 0.0f;
- for (const SplinePtr &spline : curve.splines()) {
+ for (const SplinePtr &spline : curve->splines()) {
length += spline->length();
}
params.set_output("Length", length);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc
index 9919e24473e..9fbc01935ce 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_arc.cc
@@ -335,7 +335,7 @@ static void node_geo_exec(GeoNodeExecParams params)
r_center,
r_normal,
r_radius);
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
params.set_output("Center", r_center);
params.set_output("Normal", r_normal);
params.set_output("Radius", r_radius);
@@ -350,7 +350,7 @@ static void node_geo_exec(GeoNodeExecParams params)
params.extract_input<bool>("Connect Center"),
params.extract_input<bool>("Invert Arc"));
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
break;
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
index 1d006aea1ef..eabd6aa1aa0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_bezier_segment.cc
@@ -113,7 +113,7 @@ static void node_geo_exec(GeoNodeExecParams params)
params.extract_input<float3>("End Handle"),
std::max(params.extract_input<int>("Resolution"), 1),
mode);
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
}
} // namespace blender::nodes::node_geo_curve_primitive_bezier_segment_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
index 44505b61a27..73929dce1af 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_circle.cc
@@ -203,7 +203,7 @@ static void node_geo_exec(GeoNodeExecParams params)
}
if (curve) {
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
}
else {
params.set_default_remaining_outputs();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
index d11af3b1cc0..066947de496 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_line.cc
@@ -111,7 +111,7 @@ static void node_geo_exec(GeoNodeExecParams params)
params.extract_input<float>("Length"));
}
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
}
} // namespace blender::nodes::node_geo_curve_primitive_line_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
index 456f6e55c1e..1b055a3a3d5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadratic_bezier.cc
@@ -61,7 +61,7 @@ static void node_geo_exec(GeoNodeExecParams params)
params.extract_input<float3>("Middle"),
params.extract_input<float3>("End"),
std::max(params.extract_input<int>("Resolution"), 3));
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
}
} // namespace blender::nodes::node_geo_curve_primitive_quadratic_bezier_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
index b6a847eebf4..7842ad028b7 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_quadrilateral.cc
@@ -264,7 +264,7 @@ static void node_geo_exec(GeoNodeExecParams params)
curve->add_spline(std::move(spline));
curve->attributes.reallocate(curve->splines().size());
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
}
} // namespace blender::nodes::node_geo_curve_primitive_quadrilateral_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc
index f448ddabd2b..d5bc70e37cd 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_spiral.cc
@@ -86,7 +86,7 @@ static void node_geo_exec(GeoNodeExecParams params)
params.extract_input<float>("End Radius"),
params.extract_input<float>("Height"),
params.extract_input<bool>("Reverse"));
- params.set_output("Curve", GeometrySet::create_with_curve(curve.release()));
+ params.set_output("Curve", GeometrySet::create_with_curve(curve_eval_to_curves(*curve)));
}
} // namespace blender::nodes::node_geo_curve_primitive_spiral_cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
index 5969af43bc1..e02bcfb73cc 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_primitive_star.cc
@@ -83,7 +83,7 @@ static void node_geo_exec(GeoNodeExecParams params)
std::max(params.extract_input<float>("Outer Radius"), 0.0f),
params.extract_input<float>("Twist"),
std::max(params.extract_input<int>("Points"), 3));
- GeometrySet output = GeometrySet::create_with_curve(curve.release());
+ GeometrySet output = GeometrySet::create_with_curve(curve_eval_to_curves(*curve));
if (params.output_is_required("Outer Points")) {
StrongAnonymousAttributeID attribute_output("Outer Points");
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
index d2afeaa7094..fffc6188dfd 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_resample.cc
@@ -158,7 +158,7 @@ static SplinePtr resample_spline_evaluated(const Spline &src)
static std::unique_ptr<CurveEval> resample_curve(const CurveComponent *component,
const SampleModeParam &mode_param)
{
- const CurveEval *input_curve = component->get_for_read();
+ const std::unique_ptr<CurveEval> input_curve = curves_to_curve_eval(*component->get_for_read());
GeometryComponentFieldContext field_context{*component, ATTR_DOMAIN_CURVE};
const int domain_size = component->attribute_domain_size(ATTR_DOMAIN_CURVE);
@@ -242,7 +242,7 @@ static void geometry_set_curve_resample(GeometrySet &geometry_set,
std::unique_ptr<CurveEval> output_curve = resample_curve(
geometry_set.get_component_for_read<CurveComponent>(), mode_param);
- geometry_set.replace_curve(output_curve.release());
+ geometry_set.replace_curve(curve_eval_to_curves(*output_curve));
}
static void node_geo_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc
index 0ef3230937b..06ca0483063 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_reverse.cc
@@ -34,13 +34,15 @@ static void node_geo_exec(GeoNodeExecParams params)
selection_evaluator.evaluate();
const IndexMask selection = selection_evaluator.get_evaluated_as_mask(0);
- CurveEval &curve = *component.get_for_write();
- MutableSpan<SplinePtr> splines = curve.splines();
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_write());
+ MutableSpan<SplinePtr> splines = curve->splines();
threading::parallel_for(selection.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
splines[selection[i]]->reverse();
}
});
+
+ component.replace(curve_eval_to_curves(*curve));
});
params.set_output("Curve", std::move(geometry_set));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
index 152828b284c..222c28dd21b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_sample.cc
@@ -127,7 +127,8 @@ class SampleCurveFunction : public fn::MultiFunction {
}
const CurveComponent *curve_component = geometry_set_.get_component_for_read<CurveComponent>();
- const CurveEval *curve = curve_component->get_for_read();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *curve_component->get_for_read());
Span<SplinePtr> splines = curve->splines();
if (splines.is_empty()) {
return return_default();
@@ -234,12 +235,13 @@ static void node_geo_exec(GeoNodeExecParams params)
return;
}
- const CurveEval *curve = component->get_for_read();
- if (curve == nullptr) {
+ if (!component->has_curves()) {
params.set_default_remaining_outputs();
return;
}
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component->get_for_read());
+
if (curve->splines().is_empty()) {
params.set_default_remaining_outputs();
return;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc
index 9f50b29d995..a892ff419e5 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_set_handles.cc
@@ -66,8 +66,8 @@ static void node_geo_exec(GeoNodeExecParams params)
/* Retrieve data for write access so we can avoid new allocations for the handles data. */
CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- CurveEval &curve = *curve_component.get_for_write();
- MutableSpan<SplinePtr> splines = curve.splines();
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
+ MutableSpan<SplinePtr> splines = curve->splines();
GeometryComponentFieldContext field_context{curve_component, ATTR_DOMAIN_POINT};
const int domain_size = curve_component.attribute_domain_size(ATTR_DOMAIN_POINT);
@@ -108,6 +108,8 @@ static void node_geo_exec(GeoNodeExecParams params)
}
bezier_spline.mark_cache_invalid();
}
+
+ curve_component.replace(curve_eval_to_curves(*curve));
});
if (!has_bezier_spline) {
params.error_message_add(NodeWarningType::Info, TIP_("No Bezier splines in input curve"));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
index 3fcbd1b88c3..3edaccba506 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
@@ -205,8 +205,9 @@ class CurveParameterFieldInput final : public GeometryFieldInput {
{
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
- const CurveEval *curve = curve_component.get_for_read();
- if (curve) {
+ if (curve_component.has_curves()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *curve_component.get_for_read());
return construct_curve_parameter_varray(*curve, mask, domain);
}
}
@@ -238,8 +239,8 @@ class CurveLengthFieldInput final : public GeometryFieldInput {
{
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
- const CurveEval *curve = curve_component.get_for_read();
- if (curve) {
+ if (curve_component.has_curves()) {
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curve_component.get_for_read());
return construct_curve_length_varray(*curve, mask, domain);
}
}
@@ -271,8 +272,9 @@ class IndexOnSplineFieldInput final : public GeometryFieldInput {
{
if (component.type() == GEO_COMPONENT_TYPE_CURVE) {
const CurveComponent &curve_component = static_cast<const CurveComponent &>(component);
- const CurveEval *curve = curve_component.get_for_read();
- if (curve) {
+ if (curve_component.has_curves()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *curve_component.get_for_read());
return construct_index_on_spline_varray(*curve, mask, domain);
}
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
index 053df030f15..d691726da27 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc
@@ -367,40 +367,43 @@ static void node_geo_exec(GeoNodeExecParams params)
}
const CurveComponent *curve_component = geometry_set.get_component_for_read<CurveComponent>();
- const CurveEval &curve = *curve_component->get_for_read();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *curve_component->get_for_read());
GeometryComponentFieldContext field_context{*curve_component, ATTR_DOMAIN_CURVE};
const int domain_size = curve_component->attribute_domain_size(ATTR_DOMAIN_CURVE);
+ Span<SplinePtr> src_splines = curve->splines();
+
fn::FieldEvaluator selection_evaluator{field_context, domain_size};
selection_evaluator.add(selection_field);
selection_evaluator.evaluate();
const VArray<bool> &selection = selection_evaluator.get_evaluated<bool>(0);
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();
- new_curve->resize(curve.splines().size());
+ new_curve->resize(src_splines.size());
- threading::parallel_for(curve.splines().index_range(), 512, [&](IndexRange range) {
+ threading::parallel_for(src_splines.index_range(), 512, [&](IndexRange range) {
for (const int i : range) {
if (selection[i]) {
switch (output_type) {
case GEO_NODE_SPLINE_TYPE_POLY:
- new_curve->splines()[i] = convert_to_poly_spline(*curve.splines()[i]);
+ new_curve->splines()[i] = convert_to_poly_spline(*src_splines[i]);
break;
case GEO_NODE_SPLINE_TYPE_BEZIER:
- new_curve->splines()[i] = convert_to_bezier(*curve.splines()[i], params);
+ new_curve->splines()[i] = convert_to_bezier(*src_splines[i], params);
break;
case GEO_NODE_SPLINE_TYPE_NURBS:
- new_curve->splines()[i] = convert_to_nurbs(*curve.splines()[i]);
+ new_curve->splines()[i] = convert_to_nurbs(*src_splines[i]);
break;
}
}
else {
- new_curve->splines()[i] = curve.splines()[i]->copy();
+ new_curve->splines()[i] = src_splines[i]->copy();
}
}
});
- new_curve->attributes = curve.attributes;
- geometry_set.replace_curve(new_curve.release());
+ new_curve->attributes = curve->attributes;
+ geometry_set.replace_curve(curve_eval_to_curves(*new_curve));
});
params.set_output("Curve", std::move(geometry_set));
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
index 81c3f14d8b1..3297ddcae85 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_subdivide.cc
@@ -340,9 +340,9 @@ static void node_geo_exec(GeoNodeExecParams params)
if (cuts.is_single() && cuts.get_internal_single() < 1) {
return;
}
-
- std::unique_ptr<CurveEval> output_curve = subdivide_curve(*component.get_for_read(), cuts);
- geometry_set.replace_curve(output_curve.release());
+ std::unique_ptr<CurveEval> output_curve = subdivide_curve(
+ *curves_to_curve_eval(*component.get_for_read()), cuts);
+ geometry_set.replace_curve(curve_eval_to_curves(*output_curve));
});
params.set_output("Curve", geometry_set);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index ed497b6fbe0..753a6fe7278 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -27,14 +27,16 @@ static void geometry_set_curve_to_mesh(GeometrySet &geometry_set,
const GeometrySet &profile_set,
const bool fill_caps)
{
- const CurveEval *curve = geometry_set.get_curve_for_read();
- const CurveEval *profile_curve = profile_set.get_curve_for_read();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ const Curves *profile_curves = profile_set.get_curve_for_read();
- if (profile_curve == nullptr) {
+ if (profile_curves == nullptr) {
Mesh *mesh = bke::curve_to_wire_mesh(*curve);
geometry_set.replace_mesh(mesh);
}
else {
+ const std::unique_ptr<CurveEval> profile_curve = curves_to_curve_eval(*profile_curves);
Mesh *mesh = bke::curve_to_mesh_sweep(*curve, *profile_curve, fill_caps);
geometry_set.replace_mesh(mesh);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
index 7481f7248a1..33e7a818c87 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_points.cc
@@ -325,11 +325,12 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
return;
}
- const CurveEval &curve = *geometry_set.get_curve_for_read();
- const Span<SplinePtr> splines = curve.splines();
- curve.assert_valid_point_attributes();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ const Span<SplinePtr> splines = curve->splines();
+ curve->assert_valid_point_attributes();
- const Array<int> offsets = calculate_spline_point_offsets(params, mode, curve, splines);
+ const Array<int> offsets = calculate_spline_point_offsets(params, mode, *curve, splines);
const int total_size = offsets.last();
if (total_size == 0) {
geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
@@ -339,7 +340,7 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.replace_pointcloud(BKE_pointcloud_new_nomain(total_size));
PointCloudComponent &points = geometry_set.get_component_for_write<PointCloudComponent>();
ResultAttributes point_attributes = create_attributes_for_transfer(
- points, curve, attribute_outputs);
+ points, *curve, attribute_outputs);
switch (mode) {
case GEO_NODE_CURVE_RESAMPLE_COUNT:
@@ -351,7 +352,7 @@ static void node_geo_exec(GeoNodeExecParams params)
break;
}
- copy_spline_domain_attributes(curve, offsets, points);
+ copy_spline_domain_attributes(*curve, offsets, points);
if (!point_attributes.rotations.is_empty()) {
curve_create_default_rotation_attribute(
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
index 6f2eb9f23c4..649391a2346 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
@@ -515,8 +515,8 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set,
const blender::VArray<float> &starts = evaluator.get_evaluated<float>(0);
const blender::VArray<float> &ends = evaluator.get_evaluated<float>(1);
- CurveEval &curve = *geometry_set.get_curve_for_write();
- MutableSpan<SplinePtr> splines = curve.splines();
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*geometry_set.get_curve_for_read());
+ MutableSpan<SplinePtr> splines = curve->splines();
threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
for (const int i : range) {
@@ -565,6 +565,8 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set,
}
}
});
+
+ geometry_set.replace_curve(curve_eval_to_curves(*curve));
}
static void node_geo_exec(GeoNodeExecParams params)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
index c11b82a7d99..9fc71ebe8d1 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_delete_geometry.cc
@@ -475,9 +475,9 @@ static void separate_curve_selection(GeometrySet &geometry_set,
selection_evaluator.evaluate();
const VArray_Span<bool> &selection = selection_evaluator.get_evaluated<bool>(0);
std::unique_ptr<CurveEval> r_curve = curve_separate(
- *src_component.get_for_read(), selection, selection_domain, invert);
+ *curves_to_curve_eval(*src_component.get_for_read()), selection, selection_domain, invert);
if (r_curve) {
- geometry_set.replace_curve(r_curve.release());
+ geometry_set.replace_curve(curve_eval_to_curves(*r_curve));
}
else {
geometry_set.replace_curve(nullptr);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
index c247a255e5b..41f1e6663d3 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc
@@ -529,7 +529,8 @@ static void duplicate_splines(GeometrySet &geometry_set,
const GeometryComponent &src_component = *geometry_set.get_component_for_read(
GEO_COMPONENT_TYPE_CURVE);
- const CurveEval &curve = *geometry_set.get_curve_for_read();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
const int domain_size = src_component.attribute_domain_size(ATTR_DOMAIN_CURVE);
GeometryComponentFieldContext field_context{src_component, ATTR_DOMAIN_CURVE};
FieldEvaluator evaluator{field_context, domain_size};
@@ -547,11 +548,11 @@ static void duplicate_splines(GeometrySet &geometry_set,
int count = std::max(counts[selection[i_spline]], 0);
curve_offsets[i_spline] = dst_splines_size;
dst_splines_size += count;
- dst_points_size += count * curve.splines()[selection[i_spline]]->size();
+ dst_points_size += count * curve->splines()[selection[i_spline]]->size();
}
curve_offsets.last() = dst_splines_size;
- Array<int> control_point_offsets = curve.control_point_offsets();
+ Array<int> control_point_offsets = curve->control_point_offsets();
Array<int> point_mapping(dst_points_size);
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();
@@ -559,8 +560,8 @@ static void duplicate_splines(GeometrySet &geometry_set,
for (const int i_spline : selection.index_range()) {
const IndexRange spline_range = range_for_offsets_index(curve_offsets, i_spline);
for ([[maybe_unused]] const int i_duplicate : IndexRange(spline_range.size())) {
- SplinePtr spline = curve.splines()[selection[i_spline]]->copy();
- for (const int i_point : IndexRange(curve.splines()[selection[i_spline]]->size())) {
+ SplinePtr spline = curve->splines()[selection[i_spline]]->copy();
+ for (const int i_point : IndexRange(curve->splines()[selection[i_spline]]->size())) {
point_mapping[point_index++] = control_point_offsets[selection[i_spline]] + i_point;
}
new_curve->add_spline(std::move(spline));
@@ -569,7 +570,7 @@ static void duplicate_splines(GeometrySet &geometry_set,
new_curve->attributes.reallocate(new_curve->splines().size());
CurveComponent dst_component;
- dst_component.replace(new_curve.release(), GeometryOwnershipType::Editable);
+ dst_component.replace(curve_eval_to_curves(*new_curve), GeometryOwnershipType::Editable);
Vector<std::string> skip(
{"position", "radius", "resolution", "cyclic", "tilt", "handle_left", "handle_right"});
@@ -577,7 +578,7 @@ static void duplicate_splines(GeometrySet &geometry_set,
copy_spline_attributes_without_id(
geometry_set, point_mapping, curve_offsets, skip, src_component, dst_component);
- copy_stable_id_splines(curve, selection, curve_offsets, src_component, dst_component);
+ copy_stable_id_splines(*curve, selection, curve_offsets, src_component, dst_component);
if (attributes.duplicate_index) {
create_duplicate_index_attribute(
@@ -786,8 +787,9 @@ static void duplicate_points_curve(const GeometryComponentType component_type,
Array<int> offsets = accumulate_counts_to_offsets(selection, counts);
CurveComponent &curve_component = geometry_set.get_component_for_write<CurveComponent>();
- const CurveEval &curve = *geometry_set.get_curve_for_read();
- Array<int> control_point_offsets = curve.control_point_offsets();
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ Array<int> control_point_offsets = curve->control_point_offsets();
std::unique_ptr<CurveEval> new_curve = std::make_unique<CurveEval>();
Array<int> parent(domain_size);
@@ -802,7 +804,7 @@ static void duplicate_points_curve(const GeometryComponentType component_type,
for (const int i_point : selection) {
const IndexRange point_range = range_for_offsets_index(offsets, i_point);
for ([[maybe_unused]] const int i_duplicate : IndexRange(point_range.size())) {
- const SplinePtr &parent_spline = curve.splines()[parent[i_point]];
+ const SplinePtr &parent_spline = curve->splines()[parent[i_point]];
switch (parent_spline->type()) {
case CurveType::CURVE_TYPE_BEZIER: {
std::unique_ptr<BezierSpline> spline = std::make_unique<BezierSpline>();
@@ -833,7 +835,7 @@ static void duplicate_points_curve(const GeometryComponentType component_type,
}
new_curve->attributes.reallocate(new_curve->splines().size());
CurveComponent dst_component;
- dst_component.replace(new_curve.release(), GeometryOwnershipType::Editable);
+ dst_component.replace(curve_eval_to_curves(*new_curve), GeometryOwnershipType::Editable);
copy_point_attributes_without_id(
geometry_set, GEO_COMPONENT_TYPE_CURVE, false, offsets, src_component, dst_component);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
index 4537721d173..f952e15fbbe 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_spline_length.cc
@@ -19,10 +19,10 @@ static void node_declare(NodeDeclarationBuilder &b)
static VArray<float> construct_spline_length_gvarray(const CurveComponent &component,
const AttributeDomain domain)
{
- const CurveEval *curve = component.get_for_read();
- if (curve == nullptr) {
+ if (!component.has_curves()) {
return {};
}
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
Span<SplinePtr> splines = curve->splines();
auto length_fn = [splines](int i) { return splines[i]->length(); };
@@ -76,10 +76,10 @@ class SplineLengthFieldInput final : public GeometryFieldInput {
static VArray<int> construct_spline_count_gvarray(const CurveComponent &component,
const AttributeDomain domain)
{
- const CurveEval *curve = component.get_for_read();
- if (curve == nullptr) {
+ if (!component.has_curves()) {
return {};
}
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
Span<SplinePtr> splines = curve->splines();
auto count_fn = [splines](int i) { return splines[i]->size(); };
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
index 4ee7c52a872..435dd969c03 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
@@ -77,21 +77,12 @@ static Array<float3> curve_tangent_point_domain(const CurveEval &curve)
static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component,
const AttributeDomain domain)
{
- const CurveEval *curve = component.get_for_read();
- if (curve == nullptr) {
- return nullptr;
+ if (!component.has_curves()) {
+ return {};
}
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
if (domain == ATTR_DOMAIN_POINT) {
- const Span<SplinePtr> splines = curve->splines();
-
- /* Use a reference to evaluated tangents if possible to avoid an allocation and a copy.
- * This is only possible when there is only one poly spline. */
- if (splines.size() == 1 && splines.first()->type() == CURVE_TYPE_POLY) {
- const PolySpline &spline = static_cast<PolySpline &>(*splines.first());
- return VArray<float3>::ForSpan(spline.evaluated_tangents());
- }
-
Array<float3> tangents = curve_tangent_point_domain(*curve);
return VArray<float3>::ForContainer(std::move(tangents));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
index 3284378a2cb..91cde52f9eb 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_mesh_to_curve.cc
@@ -35,7 +35,7 @@ static void node_geo_exec(GeoNodeExecParams params)
}
std::unique_ptr<CurveEval> curve = geometry::mesh_to_curve_convert(component, selection);
- geometry_set.replace_curve(curve.release());
+ geometry_set.replace_curve(curve_eval_to_curves(*curve));
geometry_set.keep_only({GEO_COMPONENT_TYPE_CURVE, GEO_COMPONENT_TYPE_INSTANCES});
});
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
index 808d679fb73..85b042ddb9b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_curve_handles.cc
@@ -35,7 +35,7 @@ static void node_init(bNodeTree *UNUSED(tree), bNode *node)
}
static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
- GeometryComponent &component,
+ CurveComponent &component,
const Field<bool> &selection_field,
const Field<float3> &position_field,
const Field<float3> &offset_field)
@@ -53,8 +53,7 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
evaluator.evaluate();
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
- CurveComponent &curve_component = *static_cast<CurveComponent *>(&component);
- CurveEval *curve = curve_component.get_for_write();
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
int current_point = 0;
int current_mask = 0;
@@ -126,6 +125,8 @@ static void set_position_in_component(const GeometryNodeCurveHandleMode mode,
}
}
}
+
+ component.replace(curve_eval_to_curves(*curve), GeometryOwnershipType::Owned);
}
static void node_geo_exec(GeoNodeExecParams params)
@@ -140,9 +141,11 @@ static void node_geo_exec(GeoNodeExecParams params)
bool has_bezier = false;
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
- if (geometry_set.has_curve() &&
- geometry_set.get_curve_for_read()->has_spline_with_type(CURVE_TYPE_BEZIER)) {
- has_bezier = true;
+ if (geometry_set.has_curve()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ has_bezier = curve->has_spline_with_type(CURVE_TYPE_BEZIER);
+
set_position_in_component(mode,
geometry_set.get_component_for_write<CurveComponent>(),
selection_field,
diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
index f1353bda9ce..e1c252d0081 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_set_spline_resolution.cc
@@ -45,7 +45,9 @@ static void node_geo_exec(GeoNodeExecParams params)
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (geometry_set.has_curve()) {
if (only_poly) {
- for (const SplinePtr &spline : geometry_set.get_curve_for_read()->splines()) {
+ const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(
+ *geometry_set.get_curve_for_read());
+ for (const SplinePtr &spline : curve->splines()) {
if (ELEM(spline->type(), CURVE_TYPE_BEZIER, CURVE_TYPE_NURBS)) {
only_poly = false;
break;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
index ddc0bb2bc11..45156e0cbf8 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
@@ -298,7 +298,8 @@ static Map<int, int> create_curve_instances(GeoNodeExecParams &params,
layout.pivot_points.add_new(layout.char_codes[i], pivot_point);
}
- GeometrySet geometry_set_curve = GeometrySet::create_with_curve(curve_eval.release());
+ GeometrySet geometry_set_curve = GeometrySet::create_with_curve(
+ curve_eval_to_curves(*curve_eval));
handles.add_new(layout.char_codes[i],
instance_component.add_reference(std::move(geometry_set_curve)));
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
index 5950a2a16d2..045dea77f38 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_transform.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_transform.cc
@@ -10,6 +10,7 @@
#include "DNA_pointcloud_types.h"
#include "DNA_volume_types.h"
+#include "BKE_curves.hh"
#include "BKE_mesh.h"
#include "BKE_pointcloud.h"
#include "BKE_spline.hh"
@@ -125,8 +126,10 @@ static void translate_geometry_set(GeometrySet &geometry,
const float3 translation,
const Depsgraph &depsgraph)
{
- if (CurveEval *curve = geometry.get_curve_for_write()) {
+ if (Curves *curves = geometry.get_curve_for_write()) {
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves);
curve->translate(translation);
+ geometry.replace_curve(curve_eval_to_curves(*curve));
}
if (Mesh *mesh = geometry.get_mesh_for_write()) {
translate_mesh(*mesh, translation);
@@ -146,8 +149,10 @@ void transform_geometry_set(GeometrySet &geometry,
const float4x4 &transform,
const Depsgraph &depsgraph)
{
- if (CurveEval *curve = geometry.get_curve_for_write()) {
+ if (Curves *curves = geometry.get_curve_for_write()) {
+ std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*curves);
curve->transform(transform);
+ geometry.replace_curve(curve_eval_to_curves(*curve));
}
if (Mesh *mesh = geometry.get_mesh_for_write()) {
transform_mesh(*mesh, transform);