From f86331a0338dc2351e914b45ccbd743b6cccbb19 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 26 Nov 2021 14:47:02 +0100 Subject: Geometry Nodes: deduplicate virtual array implementations For some underlying data (e.g. spans) we had two virtual array implementations. One for the mutable and one for the immutable case. Now that most code does not deal with the virtual array implementations directly anymore (since rBrBd4c868da9f97a), we can get away with sharing one implementation for both cases. This means that we have to do a `const_cast` in a few places, but this is an implementation detail that does not leak into "user code" (only when explicitly casting a `VArrayImpl` to a `VMutableArrayImpl`, which should happen nowhere). --- .../blenkernel/intern/geometry_component_curve.cc | 214 +++++++-------------- 1 file changed, 67 insertions(+), 147 deletions(-) (limited to 'source/blender/blenkernel/intern/geometry_component_curve.cc') diff --git a/source/blender/blenkernel/intern/geometry_component_curve.cc b/source/blender/blenkernel/intern/geometry_component_curve.cc index 598c61fd877..a0d7bfe135a 100644 --- a/source/blender/blenkernel/intern/geometry_component_curve.cc +++ b/source/blender/blenkernel/intern/geometry_component_curve.cc @@ -713,47 +713,16 @@ static bool remove_point_attribute(GeometryComponent &component, return layer_freed; } -/** - * Virtual array for any control point data accessed with spans and an offset array. - */ -template class VArray_For_SplinePoints : public VArrayImpl { - private: - const Array> data_; - Array offsets_; - - public: - VArray_For_SplinePoints(Array> data, Array offsets) - : VArrayImpl(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) - { - } - - T get(const int64_t index) const final - { - const PointIndices indices = lookup_point_indices(offsets_, index); - return data_[indices.spline_index][indices.point_index]; - } - - void materialize(const IndexMask mask, MutableSpan r_span) const final - { - point_attribute_materialize(data_.as_span(), offsets_, mask, r_span); - } - - void materialize_to_uninitialized(const IndexMask mask, MutableSpan r_span) const final - { - point_attribute_materialize_to_uninitialized(data_.as_span(), offsets_, mask, r_span); - } -}; - /** * Mutable virtual array for any control point data accessed with spans and an offset array. */ -template class VMutableArray_For_SplinePoints final : public VMutableArrayImpl { +template class VArrayImpl_For_SplinePoints final : public VMutableArrayImpl { private: Array> data_; Array offsets_; public: - VMutableArray_For_SplinePoints(Array> data, Array offsets) + VArrayImpl_For_SplinePoints(Array> data, Array offsets) : VMutableArrayImpl(offsets.last()), data_(std::move(data)), offsets_(std::move(offsets)) { } @@ -791,16 +760,17 @@ template class VMutableArray_For_SplinePoints final : public VMutabl } }; -template VArray point_data_varray(Array> spans, Array offsets) +template VArray point_data_varray(Array> spans, Array offsets) { - return VArray::template For>(std::move(spans), std::move(offsets)); + return VArray::template For>(std::move(spans), + std::move(offsets)); } template -VMutableArray point_data_varray(Array> spans, Array offsets) +VMutableArray point_data_varray_mutable(Array> spans, Array offsets) { - return VMutableArray::template For>(std::move(spans), - std::move(offsets)); + return VMutableArray::template For>(std::move(spans), + std::move(offsets)); } /** @@ -811,13 +781,13 @@ VMutableArray point_data_varray(Array> spans, Array offse * \note There is no need to check the handle type to avoid changing auto handles, since * retrieving write access to the position data will mark them for recomputation anyway. */ -class VMutableArray_For_SplinePosition final : public VMutableArrayImpl { +class VArrayImpl_For_SplinePosition final : public VMutableArrayImpl { private: MutableSpan splines_; Array offsets_; public: - VMutableArray_For_SplinePosition(MutableSpan splines, Array offsets) + VArrayImpl_For_SplinePosition(MutableSpan splines, Array offsets) : VMutableArrayImpl(offsets.last()), splines_(splines), offsets_(std::move(offsets)) { } @@ -889,104 +859,16 @@ class VMutableArray_For_SplinePosition final : public VMutableArrayImpl } }; -class VArray_For_BezierHandle final : public VArrayImpl { - private: - Span splines_; - Array offsets_; - bool is_right_; - - public: - VArray_For_BezierHandle(Span splines, Array offsets, const bool is_right) - : VArrayImpl(offsets.last()), - splines_(std::move(splines)), - offsets_(std::move(offsets)), - is_right_(is_right) - { - } - - static float3 get_internal(const int64_t index, - Span splines, - Span offsets, - const bool is_right) - { - const PointIndices indices = lookup_point_indices(offsets, index); - const Spline &spline = *splines[indices.spline_index]; - if (spline.type() == Spline::Type::Bezier) { - const BezierSpline &bezier_spline = static_cast(spline); - return is_right ? bezier_spline.handle_positions_right()[indices.point_index] : - bezier_spline.handle_positions_left()[indices.point_index]; - } - return float3(0); - } - - float3 get(const int64_t index) const final - { - return get_internal(index, splines_, offsets_, is_right_); - } - - /** - * Utility so we can pass handle positions to the materialize functions above. - * - * \note This relies on the ability of the materialize implementations to - * handle empty spans, since only Bezier splines have handles. - */ - static Array> get_handle_spans(Span splines, const bool is_right) - { - Array> spans(splines.size()); - for (const int i : spans.index_range()) { - if (splines[i]->type() == Spline::Type::Bezier) { - BezierSpline &bezier_spline = static_cast(*splines[i]); - spans[i] = is_right ? bezier_spline.handle_positions_right() : - bezier_spline.handle_positions_left(); - } - else { - spans[i] = {}; - } - } - return spans; - } - - static void materialize_internal(const IndexMask mask, - Span splines, - Span offsets, - const bool is_right, - MutableSpan r_span) - { - Array> spans = get_handle_spans(splines, is_right); - point_attribute_materialize(spans.as_span(), offsets, mask, r_span); - } - - static void materialize_to_uninitialized_internal(const IndexMask mask, - Span splines, - Span offsets, - const bool is_right, - MutableSpan r_span) - { - Array> spans = get_handle_spans(splines, is_right); - point_attribute_materialize_to_uninitialized(spans.as_span(), offsets, mask, r_span); - } - - void materialize(const IndexMask mask, MutableSpan r_span) const final - { - materialize_internal(mask, splines_, offsets_, is_right_, r_span); - } - - void materialize_to_uninitialized(const IndexMask mask, MutableSpan r_span) const final - { - materialize_to_uninitialized_internal(mask, splines_, offsets_, is_right_, r_span); - } -}; - -class VMutableArray_For_BezierHandles final : public VMutableArrayImpl { +class VArrayImpl_For_BezierHandles final : public VMutableArrayImpl { private: MutableSpan splines_; Array offsets_; bool is_right_; public: - VMutableArray_For_BezierHandles(MutableSpan splines, - Array offsets, - const bool is_right) + VArrayImpl_For_BezierHandles(MutableSpan splines, + Array offsets, + const bool is_right) : VMutableArrayImpl(offsets.last()), splines_(splines), offsets_(std::move(offsets)), @@ -996,7 +878,14 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl { float3 get(const int64_t index) const final { - return VArray_For_BezierHandle::get_internal(index, splines_, offsets_, is_right_); + const PointIndices indices = lookup_point_indices(offsets_, index); + const Spline &spline = *splines_[indices.spline_index]; + if (spline.type() == Spline::Type::Bezier) { + const BezierSpline &bezier_spline = static_cast(spline); + return is_right_ ? bezier_spline.handle_positions_right()[indices.point_index] : + bezier_spline.handle_positions_left()[indices.point_index]; + } + return float3(0); } void set(const int64_t index, float3 value) final @@ -1040,13 +929,36 @@ class VMutableArray_For_BezierHandles final : public VMutableArrayImpl { void materialize(const IndexMask mask, MutableSpan r_span) const final { - VArray_For_BezierHandle::materialize_internal(mask, splines_, offsets_, is_right_, r_span); + Array> spans = get_handle_spans(splines_, is_right_); + point_attribute_materialize(spans.as_span(), offsets_, mask, r_span); } void materialize_to_uninitialized(const IndexMask mask, MutableSpan r_span) const final { - VArray_For_BezierHandle::materialize_to_uninitialized_internal( - mask, splines_, offsets_, is_right_, r_span); + Array> spans = get_handle_spans(splines_, is_right_); + point_attribute_materialize_to_uninitialized(spans.as_span(), offsets_, mask, r_span); + } + + /** + * Utility so we can pass handle positions to the materialize functions above. + * + * \note This relies on the ability of the materialize implementations to + * handle empty spans, since only Bezier splines have handles. + */ + static Array> get_handle_spans(Span splines, const bool is_right) + { + Array> spans(splines.size()); + for (const int i : spans.index_range()) { + if (splines[i]->type() == Spline::Type::Bezier) { + BezierSpline &bezier_spline = static_cast(*splines[i]); + spans[i] = is_right ? bezier_spline.handle_positions_right() : + bezier_spline.handle_positions_left(); + } + else { + spans[i] = {}; + } + } + return spans; } }; @@ -1102,9 +1014,12 @@ template class BuiltinPointAttributeProvider : public BuiltinAttribu } Array offsets = curve->control_point_offsets(); - Array> spans(splines.size()); + Array> spans(splines.size()); for (const int i : splines.index_range()) { - spans[i] = get_span_(*splines[i]); + Span span = get_span_(*splines[i]); + /* Use const-cast because the underlying virtual array implementation is shared between const + * and non const data. */ + spans[i] = MutableSpan(const_cast(span.data()), span.size()); } return point_data_varray(spans, offsets); @@ -1143,7 +1058,7 @@ template class BuiltinPointAttributeProvider : public BuiltinAttribu spans[i] = get_mutable_span_(*splines[i]); } - return {point_data_varray(spans, offsets), domain_, tag_modified_fn}; + return {point_data_varray_mutable(spans, offsets), domain_, tag_modified_fn}; } bool try_delete(GeometryComponent &component) const final @@ -1235,8 +1150,8 @@ class PositionAttributeProvider final : public BuiltinPointAttributeProvider offsets = curve->control_point_offsets(); - return {VMutableArray::For(curve->splines(), - std::move(offsets)), + return {VMutableArray::For(curve->splines(), + std::move(offsets)), domain_, tag_modified_fn}; } @@ -1270,8 +1185,10 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { } Array offsets = curve->control_point_offsets(); - return VArray::For( - curve->splines(), std::move(offsets), is_right_); + /* Use const-cast because the underlying virtual array implementation is shared between const + * and non const data. */ + return VArray::For( + const_cast(curve)->splines(), std::move(offsets), is_right_); } WriteAttributeLookup try_get_for_write(GeometryComponent &component) const override @@ -1288,7 +1205,7 @@ class BezierHandleAttributeProvider : public BuiltinAttributeProvider { auto tag_modified_fn = [curve]() { curve->mark_cache_invalid(); }; Array offsets = curve->control_point_offsets(); - return {VMutableArray::For( + return {VMutableArray::For( curve->splines(), std::move(offsets), is_right_), domain_, tag_modified_fn}; @@ -1377,9 +1294,12 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { Array offsets = curve->control_point_offsets(); attribute_math::convert_to_static_type(spans[0].type(), [&](auto dummy) { using T = decltype(dummy); - Array> data(splines.size()); + Array> data(splines.size()); for (const int i : splines.index_range()) { - data[i] = spans[i].typed(); + Span span = spans[i].typed(); + /* Use const-cast because the underlying virtual array implementation is shared between + * const and non const data. */ + data[i] = MutableSpan(const_cast(span.data()), span.size()); BLI_assert(data[i].data() != nullptr); } attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; @@ -1435,7 +1355,7 @@ class DynamicPointAttributeProvider final : public DynamicAttributesProvider { data[i] = spans[i].typed(); BLI_assert(data[i].data() != nullptr); } - attribute = {point_data_varray(data, offsets), ATTR_DOMAIN_POINT}; + attribute = {point_data_varray_mutable(data, offsets), ATTR_DOMAIN_POINT}; }); return attribute; } -- cgit v1.2.3