[Bf-blender-cvs] [9e393fc2f12] master: Curves: Port set type node to new data-block

Hans Goudey noreply at git.blender.org
Wed Jun 8 15:37:53 CEST 2022


Commit: 9e393fc2f12583d32dddf00bad8174d2bb06b61d
Author: Hans Goudey
Date:   Wed Jun 8 15:37:46 2022 +0200
Branches: master
https://developer.blender.org/rB9e393fc2f12583d32dddf00bad8174d2bb06b61d

Curves: Port set type node to new data-block

This commit ports the "Set Spline Type" node to the new curves type.
Performance should be improved in similar ways to the other refactors
from the conversion task (T95443). Converting to and from Catmull Rom
curves is now supported. There are a few cases where a lot of work can
be skipped: when the number of points doesn't change, and when the
types already match the goal type.

The refactor has a few other explicit goals as well:
 - Don't count on initialization of attribute arrays when they are
   first allocated.
 - Avoid copying the entire data-block when possible.
 - Make decisions about which attributes to copy when changing curves
   more obvious.
 - Use higher-level methods to copy data between curve points.
 - Optimize for the common cases of single types and full selections.
 - Process selected curves of the same types in the same loop.

The Bezier to NURBS conversion is written by Piotr Makal (@pmakal).

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

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

M	source/blender/blenkernel/BKE_blender_version.h
M	source/blender/blenkernel/BKE_curves.hh
M	source/blender/blenkernel/BKE_curves_utils.hh
M	source/blender/blenkernel/intern/curves_geometry.cc
M	source/blender/blenkernel/intern/curves_utils.cc
M	source/blender/blenlib/BLI_index_mask.hh
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/geometry/intern/resample_curves.cc
M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/RNA_enum_items.h
M	source/blender/makesrna/intern/rna_curves.c
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc

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

diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index ab13a2e85d0..2cd753da9d3 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -25,7 +25,7 @@ extern "C" {
 
 /* Blender file format version. */
 #define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 0
+#define BLENDER_FILE_SUBVERSION 1
 
 /* Minimum Blender version that supports reading file written with the current
  * version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index dc67f1e7403..28d03f96db1 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -182,6 +182,7 @@ class CurvesGeometry : public ::CurvesGeometry {
   void update_curve_types();
 
   bool has_curve_with_type(CurveType type) const;
+  bool has_curve_with_type(Span<CurveType> types) const;
   /** Return true if all of the curves have the provided type. */
   bool is_single_type(CurveType type) const;
   /** Return the number of curves with each type. */
@@ -394,6 +395,11 @@ class CurvesGeometry : public ::CurvesGeometry {
    */
   void reverse_curves(IndexMask curves_to_reverse);
 
+  /**
+   * Remove any attributes that are unused based on the types in the curves.
+   */
+  void remove_attributes_based_on_types();
+
   /* --------------------------------------------------------------------
    * Attributes.
    */
@@ -710,6 +716,12 @@ inline bool CurvesGeometry::has_curve_with_type(const CurveType type) const
   return this->curve_type_counts()[type] > 0;
 }
 
+inline bool CurvesGeometry::has_curve_with_type(const Span<CurveType> types) const
+{
+  return std::any_of(
+      types.begin(), types.end(), [&](CurveType type) { return this->has_curve_with_type(type); });
+}
+
 inline const std::array<int, CURVE_TYPES_NUM> &CurvesGeometry::curve_type_counts() const
 {
   BLI_assert(this->runtime->type_counts == calculate_type_counts(this->curve_types()));
diff --git a/source/blender/blenkernel/BKE_curves_utils.hh b/source/blender/blenkernel/BKE_curves_utils.hh
index 62b060093e9..f223e173ea9 100644
--- a/source/blender/blenkernel/BKE_curves_utils.hh
+++ b/source/blender/blenkernel/BKE_curves_utils.hh
@@ -9,8 +9,52 @@
  * \brief Low-level operations for curves.
  */
 
+#include "BLI_function_ref.hh"
+#include "BLI_generic_pointer.hh"
+
 namespace blender::bke::curves {
 
+/**
+ * Copy the provided point attribute values between all curves in the #curve_ranges index
+ * ranges, assuming that all curves have the same number of control points in #src_curves
+ * and #dst_curves.
+ */
+void copy_point_data(const CurvesGeometry &src_curves,
+                     const CurvesGeometry &dst_curves,
+                     Span<IndexRange> curve_ranges,
+                     GSpan src,
+                     GMutableSpan dst);
+
+void copy_point_data(const CurvesGeometry &src_curves,
+                     const CurvesGeometry &dst_curves,
+                     IndexMask src_curve_selection,
+                     GSpan src,
+                     GMutableSpan dst);
+
+template<typename T>
+void copy_point_data(const CurvesGeometry &src_curves,
+                     const CurvesGeometry &dst_curves,
+                     const IndexMask src_curve_selection,
+                     const Span<T> src,
+                     MutableSpan<T> dst)
+{
+  copy_point_data(src_curves, dst_curves, src_curve_selection, GSpan(src), GMutableSpan(dst));
+}
+
+void fill_points(const CurvesGeometry &curves,
+                 IndexMask curve_selection,
+                 GPointer value,
+                 GMutableSpan dst);
+
+template<typename T>
+void fill_points(const CurvesGeometry &curves,
+                 const IndexMask curve_selection,
+                 const T &value,
+                 MutableSpan<T> dst)
+{
+  fill_points(curves, curve_selection, &value, dst);
+}
+
 /**
  * Copy the size of every curve in #curve_ranges to the corresponding index in #counts.
  */
@@ -23,4 +67,18 @@ void fill_curve_counts(const bke::CurvesGeometry &curves,
  */
 void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets, int start_offset = 0);
 
+IndexMask indices_for_type(const VArray<int8_t> &types,
+                           const std::array<int, CURVE_TYPES_NUM> &type_counts,
+                           const CurveType type,
+                           const IndexMask selection,
+                           Vector<int64_t> &r_indices);
+
+void foreach_curve_by_type(const VArray<int8_t> &types,
+                           const std::array<int, CURVE_TYPES_NUM> &type_counts,
+                           IndexMask selection,
+                           FunctionRef<void(IndexMask)> catmull_rom_fn,
+                           FunctionRef<void(IndexMask)> poly_fn,
+                           FunctionRef<void(IndexMask)> bezier_fn,
+                           FunctionRef<void(IndexMask)> nurbs_fn);
+
 }  // namespace blender::bke::curves
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index eb9b201c5b5..3c060bd1b8f 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -18,6 +18,7 @@
 
 #include "BKE_attribute_math.hh"
 #include "BKE_curves.hh"
+#include "BKE_curves_utils.hh"
 
 namespace blender::bke {
 
@@ -550,16 +551,8 @@ IndexMask CurvesGeometry::indices_for_curve_type(const CurveType type,
                                                  const IndexMask selection,
                                                  Vector<int64_t> &r_indices) const
 {
-  if (this->curve_type_counts()[type] == this->curves_num()) {
-    return selection;
-  }
-  const VArray<int8_t> types = this->curve_types();
-  if (types.is_single()) {
-    return types.get_internal_single() == type ? IndexMask(this->curves_num()) : IndexMask(0);
-  }
-  Span<int8_t> types_span = types.get_internal_span();
-  return index_mask_ops::find_indices_based_on_predicate(
-      selection, 1024, r_indices, [&](const int index) { return types_span[index] == type; });
+  return curves::indices_for_type(
+      this->curve_types(), this->curve_type_counts(), type, selection, r_indices);
 }
 
 void CurvesGeometry::ensure_nurbs_basis_cache() const
@@ -1322,6 +1315,27 @@ void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse)
   this->tag_topology_changed();
 }
 
+void CurvesGeometry::remove_attributes_based_on_types()
+{
+  const int points_num = this->points_num();
+  const int curves_num = this->curves_num();
+  if (!this->has_curve_with_type(CURVE_TYPE_BEZIER)) {
+    CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_TYPE_LEFT.c_str(), points_num);
+    CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_TYPE_RIGHT.c_str(), points_num);
+    CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_POSITION_LEFT.c_str(), points_num);
+    CustomData_free_layer_named(&this->point_data, ATTR_HANDLE_POSITION_RIGHT.c_str(), points_num);
+  }
+  if (!this->has_curve_with_type(CURVE_TYPE_NURBS)) {
+    CustomData_free_layer_named(&this->point_data, ATTR_NURBS_WEIGHT.c_str(), points_num);
+    CustomData_free_layer_named(&this->curve_data, ATTR_NURBS_ORDER.c_str(), curves_num);
+    CustomData_free_layer_named(&this->curve_data, ATTR_NURBS_KNOTS_MODE.c_str(), curves_num);
+  }
+  if (!this->has_curve_with_type({CURVE_TYPE_BEZIER, CURVE_TYPE_CATMULL_ROM, CURVE_TYPE_NURBS})) {
+    CustomData_free_layer_named(&this->curve_data, ATTR_RESOLUTION.c_str(), curves_num);
+  }
+  this->update_customdata_pointers();
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/blenkernel/intern/curves_utils.cc b/source/blender/blenkernel/intern/curves_utils.cc
index 78c2382b62f..802469399ab 100644
--- a/source/blender/blenkernel/intern/curves_utils.cc
+++ b/source/blender/blenkernel/intern/curves_utils.cc
@@ -4,6 +4,8 @@
  * \ingroup bke
  */
 
+#include "BLI_index_mask_ops.hh"
+
 #include "BKE_curves_utils.hh"
 
 namespace blender::bke::curves {
@@ -35,4 +37,86 @@ void accumulate_counts_to_offsets(MutableSpan<int> counts_to_offsets, const int
   counts_to_offsets.last() = offset;
 }
 
+void copy_point_data(const CurvesGeometry &src_curves,
+                     const CurvesGeometry &dst_curves,
+                     const Span<IndexRange> curve_ranges,
+                     const GSpan src,
+                     GMutableSpan dst)
+{
+  threading::parallel_for(curve_ranges.index_range(), 512, [&](IndexRange range) {
+    for (const IndexRange range : curve_ranges.slice(range)) {
+      const IndexRange src_points = src_curves.points_for_curves(range);
+      const IndexRange dst_points = dst_curves.points_for_curves(range);
+      /* The arrays might be large, so a threaded copy might make sense here too. */
+      dst.slice(dst_points).copy_from(src.slice(src_points));
+    }
+  });
+}
+
+void copy_point_data(const CurvesGeometry &src_curves,
+                     const CurvesGeometry &dst_curves,
+                     const IndexMask src_curve_selection,
+                     const GSpan src,
+                     GMutableSpan dst)
+{
+  threading::parallel_for(src_curve_selection.index_range(), 512, [&](IndexRange range) {
+    for (const int i : src_curve_selection.slice(range)) {
+      const IndexRange src_points = src_curves.points_for_curve(i);
+      const IndexRange dst_points = dst_curves.points_for_curve(i);
+      /* The arrays might be large, so a threaded copy might make sense here too. */
+      dst.slice(dst_points).copy_from(src.slice(src_points));
+    }
+  });
+}
+
+void fill_points(const CurvesGeometry &curves,
+                 const IndexMask curve_selection,
+                 const GPointer value,
+                 GMutableSpan dst)
+{
+  BLI_assert(*value.type() == dst.type());
+  const CPPType &type = dst.type();
+  threading::parallel_for(curve_selection.index_range(), 512, [&](IndexRange range) {
+    for (const int i : curve_selection.slice(range)) 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list