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. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
