[Bf-blender-cvs] [3f91e7d7792] master: Curves: actually delete curves with Delete brush

Jacques Lucke noreply at git.blender.org
Thu Mar 10 18:06:59 CET 2022


Commit: 3f91e7d7792ed5315e8b0c80de4355f064db4a6d
Author: Jacques Lucke
Date:   Thu Mar 10 18:06:43 2022 +0100
Branches: master
https://developer.blender.org/rB3f91e7d7792ed5315e8b0c80de4355f064db4a6d

Curves: actually delete curves with Delete brush

Previously, the position was just set to zero as part of the prototype.

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

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

M	source/blender/blenkernel/BKE_curves.hh
M	source/blender/blenkernel/intern/curves_geometry.cc
M	source/blender/editors/sculpt_paint/curves_sculpt_ops.cc

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

diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index f3d9090d16b..6cab9c8ff90 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -95,6 +95,7 @@ class CurvesGeometry : public ::CurvesGeometry {
    * Access a range of indices of point data for a specific curve.
    */
   IndexRange range_for_curve(int index) const;
+  IndexRange range_for_curves(IndexRange curves) const;
 
   /** The type (#CurveType) of each curve, or potentially a single if all are the same type. */
   VArray<int8_t> curve_types() const;
@@ -147,6 +148,8 @@ class CurvesGeometry : public ::CurvesGeometry {
 
   void update_customdata_pointers();
 
+  void remove_curves(IndexMask curves_to_delete);
+
   /* --------------------------------------------------------------------
    * Attributes.
    */
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 0ae5654546b..afa0e6e452d 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -129,6 +129,13 @@ IndexRange CurvesGeometry::range_for_curve(const int index) const
   return {offset, offset_next - offset};
 }
 
+IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const
+{
+  const int offset = this->curve_offsets[curves.start()];
+  const int offset_next = this->curve_offsets[curves.one_after_last()];
+  return {offset, offset_next - offset};
+}
+
 static int domain_size(const CurvesGeometry &curves, const AttributeDomain domain)
 {
   return domain == ATTR_DOMAIN_POINT ? curves.points_size() : curves.curves_size();
@@ -305,6 +312,134 @@ void CurvesGeometry::update_customdata_pointers()
       &this->point_data, CD_PROP_INT8, ATTR_CURVE_TYPE.c_str());
 }
 
+static void *ensure_customdata_layer(CustomData &custom_data,
+                                     const StringRefNull name,
+                                     const CustomDataType data_type,
+                                     const int tot_elements)
+{
+  for (const int other_layer_i : IndexRange(custom_data.totlayer)) {
+    CustomDataLayer &new_layer = custom_data.layers[other_layer_i];
+    if (name == StringRef(new_layer.name)) {
+      return new_layer.data;
+    }
+  }
+  return CustomData_add_layer_named(
+      &custom_data, data_type, CD_DEFAULT, nullptr, tot_elements, name.c_str());
+}
+
+static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
+                                               const IndexMask curves_to_delete)
+{
+  const Span<int> old_offsets = curves.offsets();
+  const Vector<IndexRange> old_curve_ranges = curves_to_delete.extract_ranges_invert(
+      curves.curves_range(), nullptr);
+  Vector<IndexRange> new_curve_ranges;
+  Vector<IndexRange> old_point_ranges;
+  Vector<IndexRange> new_point_ranges;
+  int new_tot_points = 0;
+  int new_tot_curves = 0;
+  for (const IndexRange &curve_range : old_curve_ranges) {
+    new_curve_ranges.append(IndexRange(new_tot_curves, curve_range.size()));
+    new_tot_curves += curve_range.size();
+
+    const IndexRange old_point_range = curves.range_for_curves(curve_range);
+    old_point_ranges.append(old_point_range);
+    new_point_ranges.append(IndexRange(new_tot_points, old_point_range.size()));
+    new_tot_points += old_point_range.size();
+  }
+
+  CurvesGeometry new_curves{new_tot_points, new_tot_curves};
+
+  threading::parallel_invoke(
+      /* Initialize curve offsets. */
+      [&]() {
+        MutableSpan<int> new_offsets = new_curves.offsets();
+        new_offsets.last() = new_tot_points;
+        threading::parallel_for(
+            old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+              for (const int range_i : ranges_range) {
+                const IndexRange old_curve_range = old_curve_ranges[range_i];
+                const IndexRange new_curve_range = new_curve_ranges[range_i];
+                const IndexRange old_point_range = old_point_ranges[range_i];
+                const IndexRange new_point_range = new_point_ranges[range_i];
+                const int offset_shift = new_point_range.start() - old_point_range.start();
+                const int curves_in_range = old_curve_range.size();
+                threading::parallel_for(
+                    IndexRange(curves_in_range), 512, [&](const IndexRange range) {
+                      for (const int i : range) {
+                        const int old_curve_i = old_curve_range[i];
+                        const int new_curve_i = new_curve_range[i];
+                        const int old_offset = old_offsets[old_curve_i];
+                        const int new_offset = old_offset + offset_shift;
+                        new_offsets[new_curve_i] = new_offset;
+                      }
+                    });
+              }
+            });
+      },
+      /* Copy over point attributes. */
+      [&]() {
+        const CustomData &old_point_data = curves.point_data;
+        CustomData &new_point_data = new_curves.point_data;
+        for (const int layer_i : IndexRange(old_point_data.totlayer)) {
+          const CustomDataLayer &old_layer = old_point_data.layers[layer_i];
+          const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
+          const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
+
+          const void *src_buffer = old_layer.data;
+          void *dst_buffer = ensure_customdata_layer(
+              new_point_data, old_layer.name, data_type, new_tot_points);
+
+          threading::parallel_for(
+              old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+                for (const int range_i : ranges_range) {
+                  const IndexRange old_point_range = old_point_ranges[range_i];
+                  const IndexRange new_point_range = new_point_ranges[range_i];
+
+                  type.copy_construct_n(
+                      POINTER_OFFSET(src_buffer, type.size() * old_point_range.start()),
+                      POINTER_OFFSET(dst_buffer, type.size() * new_point_range.start()),
+                      old_point_range.size());
+                }
+              });
+        }
+      },
+      /* Copy over curve attributes. */
+      [&]() {
+        const CustomData &old_curve_data = curves.curve_data;
+        CustomData &new_curve_data = new_curves.curve_data;
+        for (const int layer_i : IndexRange(old_curve_data.totlayer)) {
+          const CustomDataLayer &old_layer = old_curve_data.layers[layer_i];
+          const CustomDataType data_type = static_cast<CustomDataType>(old_layer.type);
+          const CPPType &type = *bke::custom_data_type_to_cpp_type(data_type);
+
+          const void *src_buffer = old_layer.data;
+          void *dst_buffer = ensure_customdata_layer(
+              new_curve_data, old_layer.name, data_type, new_tot_points);
+
+          threading::parallel_for(
+              old_curve_ranges.index_range(), 128, [&](const IndexRange ranges_range) {
+                for (const int range_i : ranges_range) {
+                  const IndexRange old_curve_range = old_curve_ranges[range_i];
+                  const IndexRange new_curve_range = new_curve_ranges[range_i];
+
+                  type.copy_construct_n(
+                      POINTER_OFFSET(src_buffer, type.size() * old_curve_range.start()),
+                      POINTER_OFFSET(dst_buffer, type.size() * new_curve_range.start()),
+                      old_curve_range.size());
+                }
+              });
+        }
+      });
+
+  return new_curves;
+}
+
+void CurvesGeometry::remove_curves(const IndexMask curves_to_delete)
+{
+  *this = copy_with_removed_curves(*this, curves_to_delete);
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
index 1411f30bffd..47bf7a28352 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
@@ -7,6 +7,7 @@
 #include "BKE_bvhutils.h"
 #include "BKE_context.h"
 #include "BKE_curves.hh"
+#include "BKE_geometry_set.hh"
 #include "BKE_lib_id.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_runtime.h"
@@ -67,6 +68,7 @@ bool CURVES_SCULPT_mode_poll_view3d(bContext *C)
 namespace blender::ed::sculpt_paint {
 
 using blender::bke::CurvesGeometry;
+using blender::fn::CPPType;
 
 /* -------------------------------------------------------------------- */
 /** \name * SCULPT_CURVES_OT_brush_stroke
@@ -134,14 +136,7 @@ class DeleteOperation : public CurvesSculptStrokeOperation {
           return false;
         });
 
-    /* Just reset positions instead of actually removing the curves. This is just a prototype. */
-    threading::parallel_for(curves_to_remove.index_range(), 512, [&](const IndexRange range) {
-      for (const int curve_i : curves_to_remove.slice(range)) {
-        for (const int point_i : curves.range_for_curve(curve_i)) {
-          positions[point_i] = {0.0f, 0.0f, 0.0f};
-        }
-      }
-    });
+    curves.remove_curves(curves_to_remove);
 
     curves.tag_positions_changed();
     DEG_id_tag_update(&curves_id.id, ID_RECALC_GEOMETRY);



More information about the Bf-blender-cvs mailing list