[Bf-blender-cvs] [190334b47df] master: Curves: new Grow/Shrink brush

Jacques Lucke noreply at git.blender.org
Tue Apr 5 15:24:27 CEST 2022


Commit: 190334b47df46f0e912c873077163e6129e4cbae
Author: Jacques Lucke
Date:   Tue Apr 5 15:24:12 2022 +0200
Branches: master
https://developer.blender.org/rB190334b47df46f0e912c873077163e6129e4cbae

Curves: new Grow/Shrink brush

This adds a new Grow/Shrink brush which is similar to the Length
brush in the old hair system.
* It's possible to switch between growing and shrinking by hold
  down ctrl and/or by changing the direction enum.
* 3d brush is supported.
* Different brush falloffs are supported.
* Supports scaling curves uniformly or shrinking/extrapolating
  them. Extrapolation is linear only in this patch.
* A minimum length settings helps to avoid creating zero-sized curves.

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

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

R100	release/datafiles/icons/ops.curves.sculpt_grow.dat	release/datafiles/icons/ops.curves.sculpt_grow_shrink.dat
M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenlib/BLI_math_geom.h
M	source/blender/blenlib/intern/math_geom.c
M	source/blender/editors/datafiles/CMakeLists.txt
M	source/blender/editors/sculpt_paint/CMakeLists.txt
A	source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
M	source/blender/editors/sculpt_paint/curves_sculpt_intern.hh
M	source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
M	source/blender/makesdna/DNA_brush_enums.h
M	source/blender/makesdna/DNA_brush_types.h
M	source/blender/makesrna/intern/rna_brush.c

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

diff --git a/release/datafiles/icons/ops.curves.sculpt_grow.dat b/release/datafiles/icons/ops.curves.sculpt_grow_shrink.dat
similarity index 100%
rename from release/datafiles/icons/ops.curves.sculpt_grow.dat
rename to release/datafiles/icons/ops.curves.sculpt_grow_shrink.dat
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 2c30859a2f3..0422f1afc58 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -5576,7 +5576,10 @@ def km_sculpt_curves(params):
     )
 
     items.extend([
-        ("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None),
+        ("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS'},
+         {"properties": [("mode", 'NORMAL')]}),
+        ("sculpt_curves.brush_stroke", {"type": 'LEFTMOUSE', "value": 'PRESS', "ctrl": True},
+         {"properties": [("mode", 'INVERT')]}),
         *_template_paint_radial_control("curves_sculpt"),
     ])
 
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 3c663f1371a..b786f5adf33 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -514,6 +514,13 @@ class _draw_tool_settings_context_mode:
             layout.prop(tool_settings.curves_sculpt, "interpolate_length")
             layout.prop(tool_settings.curves_sculpt, "interpolate_shape")
 
+        if brush.curves_sculpt_tool == 'GROW_SHRINK':
+            layout.prop(brush, "direction", expand=True, text="")
+            layout.prop(brush, "falloff_shape", expand=True)
+            layout.prop(brush.curves_sculpt_settings, "scale_uniform")
+            layout.prop(brush.curves_sculpt_settings, "minimum_length")
+            layout.prop(brush, "curve_preset")
+
         if brush.curves_sculpt_tool == 'SNAKE_HOOK':
             layout.prop(brush, "falloff_shape", expand=True)
             layout.prop(brush, "curve_preset")
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index ff07d061a20..601c867d8db 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1558,6 +1558,7 @@ void BKE_brush_init_curves_sculpt_settings(Brush *brush)
     brush->curves_sculpt_settings = MEM_callocN(sizeof(BrushCurvesSculptSettings), __func__);
   }
   brush->curves_sculpt_settings->add_amount = 1;
+  brush->curves_sculpt_settings->minimum_length = 0.01f;
 }
 
 struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 9e65093a05f..5c1b6c8d774 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -329,6 +329,24 @@ float closest_to_line_segment_v2(float r_close[2],
                                  const float p[2],
                                  const float l1[2],
                                  const float l2[2]);
+
+/**
+ * Finds the points where two line segments are closest to each other.
+ *
+ * `lambda_*` is a value between 0 and 1 for each segment that indicates where `r_closest_*` is on
+ * the corresponding segment.
+ *
+ * \return Squared distance between both segments.
+ */
+float closest_seg_seg_v2(float r_closest_a[2],
+                         float r_closest_b[2],
+                         float *r_lambda_a,
+                         float *r_lambda_b,
+                         const float a1[2],
+                         const float a2[2],
+                         const float b1[2],
+                         const float b2[2]);
+
 /**
  * Point closest to v1 on line v2-v3 in 3D.
  *
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 1b13493e00c..e7ccdeab80a 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -294,6 +294,66 @@ float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l
   return sqrtf(dist_squared_to_line_segment_v2(p, l1, l2));
 }
 
+float closest_seg_seg_v2(float r_closest_a[2],
+                         float r_closest_b[2],
+                         float *r_lambda_a,
+                         float *r_lambda_b,
+                         const float a1[2],
+                         const float a2[2],
+                         const float b1[2],
+                         const float b2[2])
+{
+  if (isect_seg_seg_v2_simple(a1, a2, b1, b2)) {
+    float intersection[2];
+    isect_line_line_v2_point(a1, a2, b1, b2, intersection);
+    copy_v2_v2(r_closest_a, intersection);
+    copy_v2_v2(r_closest_b, intersection);
+    float tmp[2];
+    *r_lambda_a = closest_to_line_v2(tmp, intersection, a1, a2);
+    *r_lambda_b = closest_to_line_v2(tmp, intersection, b1, b2);
+    const float min_dist_sq = len_squared_v2v2(r_closest_a, r_closest_b);
+    return min_dist_sq;
+  }
+
+  float p1[2], p2[2], p3[2], p4[2];
+  const float lambda1 = closest_to_line_segment_v2(p1, a1, b1, b2);
+  const float lambda2 = closest_to_line_segment_v2(p2, a2, b1, b2);
+  const float lambda3 = closest_to_line_segment_v2(p3, b1, a1, a2);
+  const float lambda4 = closest_to_line_segment_v2(p4, b2, a1, a2);
+  const float dist_sq1 = len_squared_v2v2(p1, a1);
+  const float dist_sq2 = len_squared_v2v2(p2, a2);
+  const float dist_sq3 = len_squared_v2v2(p3, b1);
+  const float dist_sq4 = len_squared_v2v2(p4, b2);
+
+  const float min_dist_sq = min_ffff(dist_sq1, dist_sq2, dist_sq3, dist_sq4);
+  if (min_dist_sq == dist_sq1) {
+    copy_v2_v2(r_closest_a, a1);
+    copy_v2_v2(r_closest_b, p1);
+    *r_lambda_a = 0.0f;
+    *r_lambda_b = lambda1;
+  }
+  else if (min_dist_sq == dist_sq2) {
+    copy_v2_v2(r_closest_a, a2);
+    copy_v2_v2(r_closest_b, p2);
+    *r_lambda_a = 1.0f;
+    *r_lambda_b = lambda2;
+  }
+  else if (min_dist_sq == dist_sq3) {
+    copy_v2_v2(r_closest_a, p3);
+    copy_v2_v2(r_closest_b, b1);
+    *r_lambda_a = lambda3;
+    *r_lambda_b = 0.0f;
+  }
+  else {
+    BLI_assert(min_dist_sq == dist_sq4);
+    copy_v2_v2(r_closest_a, p4);
+    copy_v2_v2(r_closest_b, b2);
+    *r_lambda_a = lambda4;
+    *r_lambda_b = 1.0f;
+  }
+  return min_dist_sq;
+}
+
 float closest_to_line_segment_v2(float r_close[2],
                                  const float p[2],
                                  const float l1[2],
diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index 0810e76fe37..ebe61d217ed 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -774,7 +774,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
   ops.curves.sculpt_comb
   ops.curves.sculpt_cut
   ops.curves.sculpt_delete
-  ops.curves.sculpt_grow
+  ops.curves.sculpt_grow_shrink
   ops.generic.cursor
   ops.generic.select
   ops.generic.select_box
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index c422c8c2033..fe7683d12f5 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -31,6 +31,7 @@ set(SRC
   curves_sculpt_add.cc
   curves_sculpt_comb.cc
   curves_sculpt_delete.cc
+  curves_sculpt_grow_shrink.cc
   curves_sculpt_ops.cc
   curves_sculpt_snake_hook.cc
   paint_cursor.c
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
new file mode 100644
index 00000000000..d26af20799e
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_grow_shrink.cc
@@ -0,0 +1,526 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <algorithm>
+
+#include "curves_sculpt_intern.hh"
+
+#include "BLI_enumerable_thread_specific.hh"
+#include "BLI_float4x4.hh"
+#include "BLI_kdtree.h"
+#include "BLI_rand.hh"
+#include "BLI_vector.hh"
+
+#include "PIL_time.h"
+
+#include "DEG_depsgraph.h"
+
+#include "BKE_attribute_math.hh"
+#include "BKE_brush.h"
+#include "BKE_bvhutils.h"
+#include "BKE_context.h"
+#include "BKE_curves.hh"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_paint.h"
+#include "BKE_spline.hh"
+
+#include "DNA_brush_enums.h"
+#include "DNA_brush_types.h"
+#include "DNA_curves_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_space_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "curves_sculpt_intern.hh"
+
+/**
+ * The code below uses a suffix naming convention to indicate the coordinate space:
+ * - `cu`: Local space of the curves object that is being edited.
+ * - `su`: Local space of the surface object.
+ * - `wo`: World space.
+ * - `re`: 2D coordinates within the region.
+ */
+
+namespace blender::ed::sculpt_paint {
+
+using bke::CurvesGeometry;
+
+/**
+ * Utility class to wrap different grow/shrink behaviors.
+ * It might be useful to use this for other future brushes as well, but better see if this
+ * abstraction holds up for a while before using it in more places.
+ */
+class CurvesEffect {
+ public:
+  virtual void execute(CurvesGeometry &curves,
+                       Span<int> curve_indices,
+                       Span<float> move_distances_cu) = 0;
+};
+
+/**
+ * Make curves smaller by trimming the end off.
+ */
+class ShrinkCurvesEffect : public CurvesEffect {
+ private:
+  Brush &brush_;
+
+ public:
+  ShrinkCurvesEffect(Brush &brush) : brush_(brush)
+  {
+  }
+
+  void execute(CurvesGeometry &curves,
+               const Span<int> curve_indices,
+               const Span<float> move_distances_cu) override
+  {
+    MutableSpan<float3> positions_cu = curves.positions();
+    threading::parallel_for(curve_indices.index_range(), 256, [&](const IndexRange range) {
+      for (const int influence_i : range) {
+        const int curve_i = curve_indices[influence_i];
+        const float move_distance_cu = move_dist

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list