44using bke::CurvesGeometry;
68 struct ParameterizationBuffers {
75 void resize(
const int points_num)
77 this->old_positions.
resize(points_num);
79 this->sample_lengths.
resize(points_num);
80 this->indices.
resize(points_num);
81 this->factors.
resize(points_num);
95 ParameterizationBuffers
data;
96 for (
const int curve_i : segment) {
97 const float move_distance_cu = move_distances_cu[curve_i];
98 const IndexRange points = points_by_curve[curve_i];
99 this->shrink_curve(positions_cu.
slice(points), move_distance_cu,
data);
106 const float shrink_length,
107 ParameterizationBuffers &
data)
const
113 data.old_positions.as_mutable_span().copy_from(positions);
115 lp::accumulate_lengths<float3>(
data.old_positions,
false,
data.old_lengths);
118 const float old_length =
data.old_lengths.last();
119 const float new_length = std::max(min_length, old_length - shrink_length);
120 const float length_factor = std::clamp(new_length / old_length, 0.0f, 1.0f);
122 data.sample_lengths.first() = 0.0f;
123 for (
const int i :
data.old_lengths.index_range()) {
124 data.sample_lengths[
i + 1] =
data.old_lengths[
i] * length_factor;
127 lp::sample_at_lengths(
data.old_lengths,
data.sample_lengths,
data.indices,
data.factors);
129 lp::interpolate<float3>(
data.old_positions,
data.indices,
data.factors, positions);
145 for (
const int curve_i : segment) {
146 const float move_distance_cu = move_distances_cu[curve_i];
147 const IndexRange points = points_by_curve[curve_i];
148 if (points.
size() <= 1) {
152 const float3 old_last_pos_cu = positions_cu[points.
last()];
155 const float3 direction_reference_point =
156 positions_cu[points.
size() > 2 ? points[points.
size() / 2] : points.
first()];
159 const float3 new_last_pos_cu = old_last_pos_cu + direction * move_distance_cu;
184 const float move_distance_cu = move_distances_cu[curve_i];
185 const IndexRange points = points_by_curve[curve_i];
188 const float length_diff = scale_up_ ? move_distance_cu : -move_distance_cu;
189 const float min_length = brush_.curves_sculpt_settings->minimum_length;
190 const float new_length = std::max(min_length, old_length + length_diff);
193 const float3 &root_pos_cu = positions_cu[points[0]];
195 pos_cu = (pos_cu - root_pos_cu) * scale_factor + root_pos_cu;
203 const int segments_num = positions.
size() - 1;
204 for (
const int segment_i :
IndexRange(segments_num)) {
205 const float3 &p1 = positions[segment_i];
206 const float3 &p2 = positions[segment_i + 1];
215 std::unique_ptr<CurvesEffect> effect_;
216 float2 last_mouse_position_;
301 self.brush_3d_ = *brush_3d;
324 return move_distances_cu[curve_i] > 0.0f;
329 self_->effect_->execute(*
curves_, curves_mask, move_distances_cu, positions_cu);
331 curves_->tag_positions_changed();
348 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
353 const float brush_radius_sq_re =
pow2f(brush_radius_re);
356 const IndexRange points = points_by_curve[curve_i];
360 float max_move_distance_cu = 0.0f;
361 for (
const float4x4 &brush_transform_inv : symmetry_brush_transforms_inv) {
362 for (
const int segment_i : points.
drop_back(1)) {
371 float2 closest_on_brush_re;
372 float2 closest_on_segment_re;
373 float lambda_on_brush;
374 float lambda_on_segment;
376 closest_on_segment_re,
384 if (dist_to_brush_sq_re > brush_radius_sq_re) {
388 const float dist_to_brush_re = std::sqrt(dist_to_brush_sq_re);
390 brush_, dist_to_brush_re, brush_radius_re);
391 const float weight =
brush_strength_ * radius_falloff * curve_selection_factor;
395 float3 brush_start_pos_wo, brush_end_pos_wo;
413 const float move_distance_cu = weight *
415 max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
418 move_distances_cu[curve_i] = max_move_distance_cu;
428 self_->brush_3d_.position_cu);
430 float3 brush_pos_start_wo, brush_pos_end_wo;
438 const float3 brush_pos_diff_cu = brush_pos_end_cu - brush_pos_start_cu;
439 const float brush_pos_diff_length_cu =
math::length(brush_pos_diff_cu);
441 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
448 const IndexRange points = points_by_curve[curve_i];
452 float max_move_distance_cu = 0.0f;
453 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
459 for (
const int segment_i : points.
drop_back(1)) {
463 float3 closest_on_segment_cu;
464 float3 closest_on_brush_cu;
467 brush_pos_start_transformed_cu,
468 brush_pos_end_transformed_cu,
469 closest_on_segment_cu,
470 closest_on_brush_cu);
473 closest_on_brush_cu);
474 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
478 const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
480 brush_, dist_to_brush_cu, brush_radius_cu);
481 const float weight =
brush_strength_ * radius_falloff * curve_selection_factor;
483 const float move_distance_cu = weight * brush_pos_diff_length_cu;
484 max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
487 move_distances_cu[curve_i] = max_move_distance_cu;
496 executor.
execute(*
this,
C, stroke_extension);
509 if (use_scale_uniform) {
510 return std::make_unique<CurvesEffectOperation>(
511 std::make_unique<ScaleCurvesEffect>(
true, brush));
513 return std::make_unique<CurvesEffectOperation>(std::make_unique<ExtrapolateCurvesEffect>());
515 if (use_scale_uniform) {
516 return std::make_unique<CurvesEffectOperation>(
517 std::make_unique<ScaleCurvesEffect>(
false, brush));
519 return std::make_unique<CurvesEffectOperation>(std::make_unique<ShrinkCurvesEffect>(brush));
float BKE_brush_curve_strength(eBrushCurvePreset preset, const CurveMapping *cumap, float distance, float brush_radius)
float BKE_brush_radius_get(const Paint *paint, const Brush *brush)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Low-level operations for curves.
const Brush * BKE_paint_brush_for_read(const Paint *paint)
MINLINE float pow2f(float x)
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])
void isect_seg_seg_v3(const float a0[3], const float a1[3], const float b0[3], const float b1[3], float r_a[3], float r_b[3])
#define BLI_SCOPED_DEFER(function_to_defer)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
@ BRUSH_CURVES_SCULPT_FLAG_SCALE_UNIFORM
Object is a sort of wrapper for general info.
void ED_region_tag_redraw(ARegion *region)
blender::float2 ED_view3d_project_float_v2_m4(const ARegion *region, const float co[3], const blender::float4x4 &mat)
void ED_view3d_win_to_3d(const View3D *v3d, const ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
blender::float4x4 ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob)
BMesh const char void * data
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
constexpr int64_t first() const
constexpr IndexRange drop_back(int64_t n) const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr IndexRange drop_front(int64_t n) const
constexpr int64_t size() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr int64_t size() const
void append(const T &value)
void resize(const int64_t new_size)
CurvesEffectOperation(std::unique_ptr< CurvesEffect > effect)
friend struct CurvesEffectOperationExecutor
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
virtual ~CurvesEffect()=default
virtual void execute(CurvesGeometry &curves, const IndexMask &curve_mask, Span< float > move_distances_cu, MutableSpan< float3 > positions_cu)=0
ScaleCurvesEffect(bool scale_up, const Brush &brush)
void execute(CurvesGeometry &curves, const IndexMask &curve_mask, const Span< float > move_distances_cu, MutableSpan< float3 > positions_cu) override
float compute_poly_curve_length(const Span< float3 > positions)
ShrinkCurvesEffect(const Brush &brush)
void execute(CurvesGeometry &curves, const IndexMask &curve_mask, const Span< float > move_distances_cu, MutableSpan< float3 > positions_cu) override
void foreach_index(Fn &&fn) const
void foreach_segment(Fn &&fn) const
float length(VecOp< float, D >) RET
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig)
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
float brush_strength_get(const Paint &paint, const Brush &brush, const StrokeExtension &stroke_extension)
std::optional< CurvesBrush3D > sample_curves_3d_brush(const Depsgraph &depsgraph, const ARegion ®ion, const View3D &v3d, const RegionView3D &rv3d, const Object &curves_object, const float2 &brush_pos_re, const float brush_radius_re)
std::unique_ptr< CurvesSculptStrokeOperation > new_grow_shrink_operation(const BrushStrokeMode brush_mode, const bContext &C)
void remember_stroke_position(CurvesSculpt &curves_sculpt, const float3 &brush_position_wo)
Vector< float4x4 > get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
void move_last_point_and_resample(MoveAndResampleBuffers &buffer, MutableSpan< float3 > positions, const float3 &new_last_position)
int segments_num(const int points_num, const bool cyclic)
T safe_divide(const T &a, const T &b)
T distance(const T &a, const T &b)
T length(const VecBase< T, Size > &a)
CartesianBasis invert(const CartesianBasis &basis)
T interpolate(const T &a, const T &b, const FactorT &t)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
VecBase< float, 2 > float2
VecBase< float, 3 > float3
struct BrushCurvesSculptSettings * curves_sculpt_settings
struct ToolSettings * toolsettings
IndexMaskMemory selected_curve_memory_
void gather_influences_projected(MutableSpan< float > move_distances_cu)
CurvesEffectOperation * self_
eBrushFalloffShape falloff_shape_
void gather_influences_spherical(MutableSpan< float > move_distances_cu)
CurvesSculpt * curves_sculpt_
IndexMask curve_selection_
VArray< float > curve_selection_factors_
float2 brush_pos_start_re_
float brush_radius_factor_
CurvesEffectOperationExecutor(const bContext &C)
void execute(CurvesEffectOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
CurvesSculptCommonContext ctx_
CurvesSurfaceTransforms transforms_
float brush_radius_base_re_
void WM_main_add_notifier(uint type, void *reference)