47using bke::CurvesGeometry;
71 struct ParameterizationBuffers {
78 void resize(
const int points_num)
80 this->old_positions.
resize(points_num);
82 this->sample_lengths.
resize(points_num);
83 this->indices.
resize(points_num);
84 this->factors.
resize(points_num);
96 const OffsetIndices points_by_curve = curves.points_by_curve();
98 ParameterizationBuffers
data;
99 for (
const int curve_i : segment) {
100 const float move_distance_cu = move_distances_cu[curve_i];
101 const IndexRange points = points_by_curve[curve_i];
102 this->shrink_curve(positions_cu.
slice(points), move_distance_cu, data);
109 const float shrink_length,
110 ParameterizationBuffers &data)
const
112 namespace lp = length_parameterize;
113 data.resize(positions.size());
116 data.old_positions.as_mutable_span().copy_from(positions);
118 lp::accumulate_lengths<float3>(data.old_positions,
false, data.old_lengths);
121 const float old_length = data.old_lengths.last();
122 const float new_length = std::max(min_length, old_length - shrink_length);
123 const float length_factor = std::clamp(new_length / old_length, 0.0f, 1.0f);
125 data.sample_lengths.first() = 0.0f;
126 for (
const int i : data.old_lengths.index_range()) {
127 data.sample_lengths[i + 1] = data.old_lengths[i] * length_factor;
130 lp::sample_at_lengths(data.old_lengths, data.sample_lengths, data.indices, data.factors);
132 lp::interpolate<float3>(data.old_positions, data.indices, data.factors, positions);
145 const OffsetIndices points_by_curve = curves.points_by_curve();
148 for (
const int curve_i : segment) {
149 const float move_distance_cu = move_distances_cu[curve_i];
150 const IndexRange points = points_by_curve[curve_i];
151 if (points.size() <= 1) {
155 const float3 old_last_pos_cu = positions_cu[points.last()];
158 const float3 direction_reference_point =
159 positions_cu[points.size() > 2 ? points[points.size() / 2] : points.first()];
162 const float3 new_last_pos_cu = old_last_pos_cu + direction * move_distance_cu;
185 const OffsetIndices points_by_curve = curves.points_by_curve();
187 const float move_distance_cu = move_distances_cu[curve_i];
188 const IndexRange points = points_by_curve[curve_i];
191 const float length_diff = scale_up_ ? move_distance_cu : -move_distance_cu;
193 const float new_length = std::max(min_length, old_length + length_diff);
196 const float3 &root_pos_cu = positions_cu[points[0]];
197 for (
float3 &pos_cu : positions_cu.
slice(points.drop_front(1))) {
198 pos_cu = (pos_cu - root_pos_cu) * scale_factor + root_pos_cu;
206 const int segments_num = positions.size() - 1;
207 for (
const int segment_i :
IndexRange(segments_num)) {
208 const float3 &p1 = positions[segment_i];
209 const float3 &p2 = positions[segment_i + 1];
218 std::unique_ptr<CurvesEffect> effect_;
219 float2 last_mouse_position_;
305 self.brush_3d_ = *brush_3d;
325 return move_distances_cu[curve_i] > 0.0f;
330 self_->effect_->execute(*
curves_, curves_mask, move_distances_cu, positions_cu);
349 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
354 const float brush_radius_sq_re =
pow2f(brush_radius_re);
357 const IndexRange points = points_by_curve[curve_i];
361 float max_move_distance_cu = 0.0f;
362 for (
const float4x4 &brush_transform_inv : symmetry_brush_transforms_inv) {
363 for (
const int segment_i : points.drop_back(1)) {
365 deformation.positions[segment_i]);
367 deformation.positions[segment_i + 1]);
372 float2 closest_on_brush_re;
373 float2 closest_on_segment_re;
374 float lambda_on_brush;
375 float lambda_on_segment;
377 closest_on_segment_re,
385 if (dist_to_brush_sq_re > brush_radius_sq_re) {
389 const float dist_to_brush_re = std::sqrt(dist_to_brush_sq_re);
391 brush_, dist_to_brush_re, brush_radius_re);
392 const float weight =
brush_strength_ * radius_falloff * curve_selection_factor;
396 float3 brush_start_pos_wo, brush_end_pos_wo;
414 const float move_distance_cu = weight *
416 max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
419 move_distances_cu[curve_i] = max_move_distance_cu;
431 float3 brush_pos_start_wo, brush_pos_end_wo;
439 const float3 brush_pos_diff_cu = brush_pos_end_cu - brush_pos_start_cu;
440 const float brush_pos_diff_length_cu =
math::length(brush_pos_diff_cu);
442 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
449 const IndexRange points = points_by_curve[curve_i];
453 float max_move_distance_cu = 0.0f;
454 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
460 for (
const int segment_i : points.drop_back(1)) {
461 const float3 &p1_cu = deformation.positions[segment_i];
462 const float3 &p2_cu = deformation.positions[segment_i + 1];
464 float3 closest_on_segment_cu;
465 float3 closest_on_brush_cu;
468 brush_pos_start_transformed_cu,
469 brush_pos_end_transformed_cu,
470 closest_on_segment_cu,
471 closest_on_brush_cu);
474 closest_on_brush_cu);
475 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
479 const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
481 brush_, dist_to_brush_cu, brush_radius_cu);
482 const float weight =
brush_strength_ * radius_falloff * curve_selection_factor;
484 const float move_distance_cu = weight * brush_pos_diff_length_cu;
485 max_move_distance_cu = std::max(max_move_distance_cu, move_distance_cu);
488 move_distances_cu[curve_i] = max_move_distance_cu;
497 executor.
execute(*
this, C, stroke_extension);
510 if (use_scale_uniform) {
511 return std::make_unique<CurvesEffectOperation>(
512 std::make_unique<ScaleCurvesEffect>(
true, brush));
514 return std::make_unique<CurvesEffectOperation>(std::make_unique<ExtrapolateCurvesEffect>());
516 if (use_scale_uniform) {
517 return std::make_unique<CurvesEffectOperation>(
518 std::make_unique<ScaleCurvesEffect>(
false, brush));
520 return std::make_unique<CurvesEffectOperation>(std::make_unique<ShrinkCurvesEffect>(brush));
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
float BKE_brush_curve_strength(eBrushCurvePreset preset, const CurveMapping *cumap, float distance, float brush_radius)
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)
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
void append(const T &value)
void resize(const int64_t new_size)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
void tag_positions_changed()
AttributeAccessor attributes() const
CurvesEffectOperation(std::unique_ptr< CurvesEffect > effect)
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
const Depsgraph * depsgraph
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
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
void foreach_index(Fn &&fn) const
void foreach_segment(Fn &&fn) const
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig)
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
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)
float brush_strength_get(const Scene &scene, const Brush &brush, const StrokeExtension &stroke_extension)
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)
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)
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)