From 627f3571271e5f1a416314fb73f8e3c613271db3 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Wed, 19 May 2021 13:22:09 -0400 Subject: Geometry Nodes: Support for dynamic attributes on curve splines With this patch you will be able to add and remove attributes from curve data inside of geometry nodes. The following is currently implemented: * Adding attributes with any data type to splines or spline points. * Support for working with multiple splines at the same time. * Interaction with the three builtin point attributes. * Resampling attributes in the resample node. The following is not implemented in this patch: * Joining attributes when joining splines with the join geometry node. * Domain interpolation between spline and point domains. * More efficient ways to call attribute operations once per spline. Differential Revision: https://developer.blender.org/D11251 --- source/blender/blenkernel/intern/curve_eval.cc | 52 ++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) (limited to 'source/blender/blenkernel/intern/curve_eval.cc') diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc index 1679f21516a..9cafe1124b1 100644 --- a/source/blender/blenkernel/intern/curve_eval.cc +++ b/source/blender/blenkernel/intern/curve_eval.cc @@ -16,7 +16,9 @@ #include "BLI_array.hh" #include "BLI_listbase.h" +#include "BLI_map.hh" #include "BLI_span.hh" +#include "BLI_string_ref.hh" #include "DNA_curve_types.h" @@ -26,7 +28,9 @@ using blender::Array; using blender::float3; using blender::float4x4; +using blender::Map; using blender::Span; +using blender::StringRefNull; blender::Span CurveEval::splines() const { @@ -38,6 +42,9 @@ blender::MutableSpan CurveEval::splines() return splines_; } +/** + * \warning Call #reallocate on the spline's attributes after adding all splines. + */ void CurveEval::add_spline(SplinePtr spline) { splines_.append(std::move(spline)); @@ -178,7 +185,7 @@ std::unique_ptr curve_eval_from_dna_curve(const Curve &dna_curve) bezt.radius, bezt.tilt); } - + spline->attributes.reallocate(spline->size()); curve->add_spline(std::move(spline)); break; } @@ -192,7 +199,7 @@ std::unique_ptr curve_eval_from_dna_curve(const Curve &dna_curve) for (const BPoint &bp : Span(nurb->bp, nurb->pntsu)) { spline->add_point(bp.vec, bp.radius, bp.tilt, bp.vec[3]); } - + spline->attributes.reallocate(spline->size()); curve->add_spline(std::move(spline)); break; } @@ -203,7 +210,7 @@ std::unique_ptr curve_eval_from_dna_curve(const Curve &dna_curve) for (const BPoint &bp : Span(nurb->bp, nurb->pntsu)) { spline->add_point(bp.vec, bp.radius, bp.tilt); } - + spline->attributes.reallocate(spline->size()); curve->add_spline(std::move(spline)); break; } @@ -214,6 +221,9 @@ std::unique_ptr curve_eval_from_dna_curve(const Curve &dna_curve) } } + /* Though the curve has no attributes, this is necessary to properly set the custom data size. */ + curve->attributes.reallocate(curve->splines().size()); + /* Note: Normal mode is stored separately in each spline to facilitate combining splines * from multiple curve objects, where the value may be different. */ const Spline::NormalCalculationMode normal_mode = normal_mode_from_dna_curve( @@ -224,3 +234,39 @@ std::unique_ptr curve_eval_from_dna_curve(const Curve &dna_curve) return curve; } + +/** + * Check the invariants that curve control point attributes should always uphold, necessary + * because attributes are stored on splines rather than in a flat array on the curve: + * - The same set of attributes exists on every spline. + * - Attributes with the same name have the same type on every spline. + */ +void CurveEval::assert_valid_point_attributes() const +{ +#ifdef DEBUG + if (splines_.size() == 0) { + return; + } + const int layer_len = splines_.first()->attributes.data.totlayer; + Map map; + for (const SplinePtr &spline : splines_) { + BLI_assert(spline->attributes.data.totlayer == layer_len); + spline->attributes.foreach_attribute( + [&](StringRefNull name, const AttributeMetaData &meta_data) { + map.add_or_modify( + name, + [&](AttributeMetaData *map_data) { + /* All unique attribute names should be added on the first spline. */ + BLI_assert(spline == splines_.first()); + *map_data = meta_data; + }, + [&](AttributeMetaData *map_data) { + /* Attributes on different splines should all have the same type. */ + BLI_assert(meta_data == *map_data); + }); + return true; + }, + ATTR_DOMAIN_POINT); + } +#endif +} \ No newline at end of file -- cgit v1.2.3