[Bf-blender-cvs] [2551cf90873] master: Curves: Port fillet node to the new data-block

Hans Goudey noreply at git.blender.org
Wed Jul 20 01:50:38 CEST 2022


Commit: 2551cf908732bab2865654571164d74e8bbad47e
Author: Hans Goudey
Date:   Tue Jul 19 18:50:27 2022 -0500
Branches: master
https://developer.blender.org/rB2551cf908732bab2865654571164d74e8bbad47e

Curves: Port fillet node to the new data-block

This commit ports the fillet curves node to the new curves data-block,
and moves the fillet node implementation to the geometry module to help
separate the implementation from the node.

The changes are similar to the subdivide node or resample node. I've
resused common utilities where it makes sense, though some things like
the iteration over attributes can be generalized further. The node
is now multi-threaded per-curve and inside each curve, and some buffers
are reused per curve to avoid many allocations.

The code is more explicit now, and though there is more boilerplate to
pass around many spans, the more complex logic should be more readable.

Differential Revision: https://developer.blender.org/D15346

===================================================================

M	source/blender/blenkernel/BKE_attribute.hh
M	source/blender/blenkernel/intern/attribute_access.cc
M	source/blender/blenlib/BLI_index_range.hh
M	source/blender/blenlib/BLI_math_rotation.hh
M	source/blender/blenlib/intern/math_rotation.cc
M	source/blender/blenlib/tests/BLI_index_range_test.cc
M	source/blender/geometry/CMakeLists.txt
A	source/blender/geometry/GEO_fillet_curves.hh
A	source/blender/geometry/intern/fillet_curves.cc
M	source/blender/geometry/intern/subdivide_curves.cc
M	source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc

===================================================================

diff --git a/source/blender/blenkernel/BKE_attribute.hh b/source/blender/blenkernel/BKE_attribute.hh
index 05ab4f1f1f1..108993d91c0 100644
--- a/source/blender/blenkernel/BKE_attribute.hh
+++ b/source/blender/blenkernel/BKE_attribute.hh
@@ -666,6 +666,22 @@ class MutableAttributeAccessor : public AttributeAccessor {
   void remove_anonymous();
 };
 
+struct AttributeTransferData {
+  /* Expect that if an attribute exists, it is stored as a contiguous array internally anyway. */
+  GVArraySpan src;
+  AttributeMetaData meta_data;
+  bke::GSpanAttributeWriter dst;
+};
+/**
+ * Retrieve attribute arrays and writers for attributes that should be transferred between
+ * data-blocks of the same type.
+ */
+Vector<AttributeTransferData> retrieve_attributes_for_transfer(
+    const bke::AttributeAccessor &src_attributes,
+    bke::MutableAttributeAccessor &dst_attributes,
+    eAttrDomainMask domain_mask,
+    const Set<std::string> &skip = {});
+
 bool allow_procedural_attribute_access(StringRef attribute_name);
 extern const char *no_procedural_access_message;
 
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index ac1ee19927c..a834b77d65e 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -1011,6 +1011,37 @@ GSpanAttributeWriter MutableAttributeAccessor::lookup_or_add_for_write_only_span
   return {};
 }
 
+Vector<AttributeTransferData> retrieve_attributes_for_transfer(
+    const bke::AttributeAccessor &src_attributes,
+    bke::MutableAttributeAccessor &dst_attributes,
+    const eAttrDomainMask domain_mask,
+    const Set<std::string> &skip)
+{
+  Vector<AttributeTransferData> attributes;
+  src_attributes.for_all(
+      [&](const bke::AttributeIDRef &id, const bke::AttributeMetaData meta_data) {
+        if (!(ATTR_DOMAIN_AS_MASK(meta_data.domain) & domain_mask)) {
+          return true;
+        }
+        if (id.is_named() && skip.contains(id.name())) {
+          return true;
+        }
+        if (!id.should_be_kept()) {
+          return true;
+        }
+
+        GVArray src = src_attributes.lookup(id, meta_data.domain);
+        BLI_assert(src);
+        bke::GSpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span(
+            id, meta_data.domain, meta_data.data_type);
+        BLI_assert(dst);
+        attributes.append({std::move(src), meta_data, std::move(dst)});
+
+        return true;
+      });
+  return attributes;
+}
+
 }  // namespace blender::bke
 
 /** \} */
diff --git a/source/blender/blenlib/BLI_index_range.hh b/source/blender/blenlib/BLI_index_range.hh
index bd0a7e5bb7a..6fcc560d856 100644
--- a/source/blender/blenlib/BLI_index_range.hh
+++ b/source/blender/blenlib/BLI_index_range.hh
@@ -197,6 +197,16 @@ class IndexRange {
     return start_ + size_ - 1 - n;
   }
 
+  /**
+   * Get the element one before the beginning. The returned value is undefined when the range is
+   * empty, and the range must start after zero already.
+   */
+  constexpr int64_t one_before_start() const
+  {
+    BLI_assert(start_ > 0);
+    return start_ - 1;
+  }
+
   /**
    * Get the element one after the end. The returned value is undefined when the range is empty.
    */
diff --git a/source/blender/blenlib/BLI_math_rotation.hh b/source/blender/blenlib/BLI_math_rotation.hh
index e8b746b34df..50a062162ad 100644
--- a/source/blender/blenlib/BLI_math_rotation.hh
+++ b/source/blender/blenlib/BLI_math_rotation.hh
@@ -15,4 +15,13 @@ namespace blender::math {
  */
 float3 rotate_direction_around_axis(const float3 &direction, const float3 &axis, float angle);
 
+/**
+ * Rotate any arbitrary \a vector around the \a center position, with a unit-length \a axis
+ * and the specified \a angle.
+ */
+float3 rotate_around_axis(const float3 &vector,
+                          const float3 &center,
+                          const float3 &axis,
+                          float angle);
+
 }  // namespace blender::math
diff --git a/source/blender/blenlib/intern/math_rotation.cc b/source/blender/blenlib/intern/math_rotation.cc
index 74300d55954..091e8af85d9 100644
--- a/source/blender/blenlib/intern/math_rotation.cc
+++ b/source/blender/blenlib/intern/math_rotation.cc
@@ -23,4 +23,17 @@ float3 rotate_direction_around_axis(const float3 &direction, const float3 &axis,
   return axis_scaled + diff * std::cos(angle) + cross * std::sin(angle);
 }
 
+float3 rotate_around_axis(const float3 &vector,
+                          const float3 &center,
+                          const float3 &axis,
+                          const float angle)
+
+{
+  float3 result = vector - center;
+  float mat[3][3];
+  axis_angle_normalized_to_mat3(mat, axis, angle);
+  mul_m3_v3(mat, result);
+  return result + center;
+}
+
 }  // namespace blender::math
diff --git a/source/blender/blenlib/tests/BLI_index_range_test.cc b/source/blender/blenlib/tests/BLI_index_range_test.cc
index 10f6784cd44..f5b994d409a 100644
--- a/source/blender/blenlib/tests/BLI_index_range_test.cc
+++ b/source/blender/blenlib/tests/BLI_index_range_test.cc
@@ -105,6 +105,12 @@ TEST(index_range, OneAfterEnd)
   EXPECT_EQ(range.one_after_last(), 8);
 }
 
+TEST(index_range, OneBeforeStart)
+{
+  IndexRange range = IndexRange(5, 3);
+  EXPECT_EQ(range.one_before_start(), 4);
+}
+
 TEST(index_range, Start)
 {
   IndexRange range = IndexRange(6, 2);
diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt
index df66a806c16..da83d9e8957 100644
--- a/source/blender/geometry/CMakeLists.txt
+++ b/source/blender/geometry/CMakeLists.txt
@@ -16,6 +16,7 @@ set(INC
 
 set(SRC
   intern/add_curves_on_mesh.cc
+  intern/fillet_curves.cc
   intern/mesh_merge_by_distance.cc
   intern/mesh_primitive_cuboid.cc
   intern/mesh_to_curve_convert.cc
@@ -29,6 +30,7 @@ set(SRC
   intern/uv_parametrizer.c
 
   GEO_add_curves_on_mesh.hh
+  GEO_fillet_curves.hh
   GEO_mesh_merge_by_distance.hh
   GEO_mesh_primitive_cuboid.hh
   GEO_mesh_to_curve.hh
diff --git a/source/blender/geometry/GEO_fillet_curves.hh b/source/blender/geometry/GEO_fillet_curves.hh
new file mode 100644
index 00000000000..1f832f8b6cc
--- /dev/null
+++ b/source/blender/geometry/GEO_fillet_curves.hh
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+
+#include "BLI_function_ref.hh"
+#include "BLI_index_mask.hh"
+
+#include "BKE_curves.hh"
+
+namespace blender::geometry {
+
+bke::CurvesGeometry fillet_curves_poly(const bke::CurvesGeometry &src_curves,
+                                       IndexMask curve_selection,
+                                       const VArray<float> &radius,
+                                       const VArray<int> &counts,
+                                       bool limit_radius);
+
+bke::CurvesGeometry fillet_curves_bezier(const bke::CurvesGeometry &src_curves,
+                                         IndexMask curve_selection,
+                                         const VArray<float> &radius,
+                                         bool limit_radius);
+
+}  // namespace blender::geometry
diff --git a/source/blender/geometry/intern/fillet_curves.cc b/source/blender/geometry/intern/fillet_curves.cc
new file mode 100644
index 00000000000..2cca91f40ae
--- /dev/null
+++ b/source/blender/geometry/intern/fillet_curves.cc
@@ -0,0 +1,561 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include "BKE_attribute_math.hh"
+#include "BKE_curves.hh"
+#include "BKE_curves_utils.hh"
+#include "BKE_geometry_set.hh"
+
+#include "BLI_devirtualize_parameters.hh"
+#include "BLI_math_geom.h"
+#include "BLI_math_rotation.hh"
+#include "BLI_task.hh"
+
+#include "GEO_fillet_curves.hh"
+
+namespace blender::geometry {
+
+/**
+ * Return a range used to retrieve values from an array of values stored per point, but with an
+ * extra element at the end of each curve. This is useful for offsets within curves, where it is
+ * convenient to store the first 0 and have the last offset be the total result curve size.
+ */
+static IndexRange curve_dst_offsets(const IndexRange points, const int curve_index)
+{
+  return {curve_index + points.start(), points.size() + 1};
+}
+
+template<typename T>
+static void threaded_slice_fill(const Span<T> src, const Span<int> offsets, MutableSpan<T> dst)
+{
+  threading::parallel_for(src.index_range(), 512, [&](IndexRange range) {
+    for (const int i : range) {
+      dst.slice(bke::offsets_to_range(offsets, i)).fill(src[i]);
+    }
+  });
+}
+
+template<typename T>
+static void duplicate_fillet_point_data(const bke::CurvesGeometry &src_curves,
+                                        const bke::CurvesGeometry &dst_curves,
+                                        const IndexMask curve_selection,
+                                        const Span<int> point_offsets,
+                                        const Span<T> src,
+                                        MutableSpan<T> dst)
+{
+  threading::parallel_for(curve_selection.index_range(), 512, [&](IndexRange range) {
+    for (const int curve_i : curve_selection.slice(range)) {
+      const IndexRange src_points = src_curves.points_for_curve(curve_i);
+      const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
+      const Span<int> offsets = point_offsets.slice(curve_dst_offsets(src_points, curve_i));
+      threaded_slice_fill(src.slice(src_points), offsets, dst.slice(dst_points));
+    }
+  });
+}
+
+static void duplicate_fillet_point_data(const bke::CurvesGeometry &src_curves,
+                                        const bke::CurvesGeometry &dst_curves,
+                                        const IndexMask selection,
+                                        const Span<int> point_offsets,
+                                        const GSpan src,
+                                        GMutableSpan dst)
+{
+  attribute_math::convert_to_static_type(dst.type(), [&](auto dummy) {
+    using T = decltype(dummy);
+    duplicate_fillet_point_data(
+        src_curves, dst_curves, selection, point_offsets, src.typed<T>(), dst.typed<T>());
+  });
+}
+
+static void calculate_result_offsets(const bke::CurvesGeometry &src_curves,
+    

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list