151 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
167 const float brush_radius_sq_re =
pow2f(brush_radius_re);
170 for (const int curve_i : curve_selection_.slice(range)) {
171 const IndexRange points = curves_->points_for_curve(curve_i);
172 for (const int point_i : points.drop_front(1)) {
173 const float3 old_pos_cu = deformation.positions[point_i];
174 const float3 old_symm_pos_cu = brush_transform_inv * old_pos_cu;
175 float2 old_symm_pos_re;
176 ED_view3d_project_float_v2_m4(
177 ctx_.region, old_symm_pos_cu, old_symm_pos_re, projection.values);
179 const float dist_to_brush_sq_re = math::distance_squared(old_symm_pos_re, brush_pos_re_);
180 if (dist_to_brush_sq_re > brush_radius_sq_re) {
184 const float dist_to_brush_re = std::sqrt(dist_to_brush_sq_re);
185 const float t = safe_divide(dist_to_brush_re, brush_radius_base_re_);
186 const float radius_falloff = t * BKE_brush_curve_strength(brush_, t, 1.0f);
187 const float weight = invert_factor_ * 0.1f * brush_strength_ * radius_falloff *
188 point_factors_[point_i];
190 const float2 new_symm_pos_re = math::interpolate(old_symm_pos_re, brush_pos_re_, weight);
192 float3 new_symm_pos_wo;
193 ED_view3d_win_to_3d(ctx_.v3d,
195 transforms_.curves_to_world * old_symm_pos_cu,
199 const float3 new_pos_cu = brush_transform * transforms_.world_to_curves *
201 const float3 translation_eval = new_pos_cu - old_pos_cu;
202 const float3 translation_orig = deformation.translation_from_deformed_to_original(
203 point_i, translation_eval);
204 positions_cu[point_i] += translation_orig;
205 r_changed_curves[curve_i] = true;
216 transforms_.curves_to_world * self_->brush_3d_.position_cu,
219 const float3 brush_pos_cu = transforms_.world_to_curves * brush_pos_wo;
220 const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_;
224 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
225 this->pinch_spherical(brush_transform * brush_pos_cu, brush_radius_cu, r_changed_curves);
230 const float brush_radius_cu,
234 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
240 for (const int curve_i : curve_selection_.slice(range)) {
241 const IndexRange points = curves_->points_for_curve(curve_i);
242 for (const int point_i : points.drop_front(1)) {
243 const float3 old_pos_cu = deformation.positions[point_i];
245 const float dist_to_brush_sq_cu = math::distance_squared(old_pos_cu, brush_pos_cu);
246 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
250 const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
251 const float t = safe_divide(dist_to_brush_cu, brush_radius_cu);
252 const float radius_falloff = t * BKE_brush_curve_strength(brush_, t, 1.0f);
253 const float weight = invert_factor_ * 0.1f * brush_strength_ * radius_falloff *
254 point_factors_[point_i];
256 const float3 new_pos_cu = math::interpolate(old_pos_cu, brush_pos_cu, weight);
257 const float3 translation_eval = new_pos_cu - old_pos_cu;
258 const float3 translation_orig = deformation.translation_from_deformed_to_original(
259 point_i, translation_eval);
260 positions_cu[point_i] += translation_orig;
262 r_changed_curves[curve_i] = true;
271 self_->segment_lengths_cu_.reinitialize(curves_->points_num());
273 for (const int curve_i : curve_selection_.slice(range)) {
274 const IndexRange points = curves_->points_for_curve(curve_i);
275 for (const int point_i : points.drop_back(1)) {
276 const float3 &p1_cu = positions_cu[point_i];
277 const float3 &p2_cu = positions_cu[point_i + 1];
278 const float length_cu = math::distance(p1_cu, p2_cu);
279 self_->segment_lengths_cu_[point_i] = length_cu;
287 const Span<float> expected_lengths_cu = self_->segment_lengths_cu_;
291 for (const int curve_i : range) {
292 if (!changed_curves[curve_i]) {
295 const IndexRange points = curves_->points_for_curve(curve_i);
296 for (const int segment_i : IndexRange(points.size() - 1)) {
297 const float3 &p1_cu = positions_cu[points[segment_i]];
298 float3 &p2_cu = positions_cu[points[segment_i] + 1];
299 const float3 direction = math::normalize(p2_cu - p1_cu);
300 const float expected_length_cu = expected_lengths_cu[points[segment_i]];
301 p2_cu = p1_cu + direction * expected_length_cu;
311 executor.execute(*
this,
C, stroke_extension);
322 return std::make_unique<PinchOperation>(invert_pinch);
float BKE_brush_alpha_get(const struct Scene *scene, const struct Brush *brush)
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush)
struct Scene * CTX_data_scene(const bContext *C)
struct Object * CTX_data_active_object(const bContext *C)
Low-level operations for curves.
const struct Brush * BKE_paint_brush_for_read(const struct Paint *p)
#define BLI_assert_unreachable()
MINLINE float pow2f(float x)
void DEG_id_tag_update(struct ID *id, int flag)
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
Object is a sort of wrapper for general info.
void ED_region_tag_redraw(struct ARegion *region)
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, const struct Object *ob, float r_pmat[4][4])
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
Platform independent time functions.
IndexRange index_range() const
constexpr IndexRange index_range() const
MutableSpan< float3 > positions_for_write()
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
void tag_positions_changed()
const Depsgraph * depsgraph
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
PinchOperation(const bool invert_pinch)
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig)
std::unique_ptr< CurvesSculptStrokeOperation > new_pinch_operation(const BrushStrokeMode brush_mode, const bContext &C)
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)
VArray< float > get_point_selection(const Curves &curves_id)
static IndexMask retrieve_selected_curves(const CurvesGeometry &curves, const eAttrDomain domain, Vector< int64_t > &r_indices)
Vector< float4x4 > get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
struct ToolSettings * toolsettings
void initialize_segment_lengths()
PinchOperationExecutor(const bContext &C)
Vector< int64_t > selected_curve_indices_
const CurvesSculpt * curves_sculpt_
void execute(PinchOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
void pinch_spherical_with_symmetry(MutableSpan< bool > r_changed_curves)
void pinch_projected(const float4x4 &brush_transform, MutableSpan< bool > r_changed_curves)
void restore_segment_lengths(const Span< bool > changed_curves)
float brush_radius_base_re_
VArray< float > point_factors_
CurvesSculptCommonContext ctx_
CurvesSurfaceTransforms transforms_
void pinch_projected_with_symmetry(MutableSpan< bool > r_changed_curves)
void pinch_spherical(const float3 &brush_pos_cu, const float brush_radius_cu, MutableSpan< bool > r_changed_curves)
float brush_radius_factor_
IndexMask curve_selection_
float4x4 inverted() const
void WM_main_add_notifier(unsigned int type, void *reference)