56 using threading::EnumerableThreadSpecific;
178 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
196 const float brush_radius_sq_re =
pow2f(brush_radius_re);
199 Vector<int> &local_changed_curves = r_changed_curves.local();
200 for (const int curve_i : curve_selection_.slice(range)) {
201 bool curve_changed = false;
202 const IndexRange points = curves_orig_->points_for_curve(curve_i);
203 for (const int point_i : points.drop_front(1)) {
204 const float3 old_pos_cu = deformation.positions[point_i];
205 const float3 old_symm_pos_cu = brush_transform_inv * old_pos_cu;
208 float2 old_symm_pos_re;
209 ED_view3d_project_float_v2_m4(
210 ctx_.region, old_symm_pos_cu, old_symm_pos_re, projection.values);
212 const float distance_to_brush_sq_re = dist_squared_to_line_segment_v2(
213 old_symm_pos_re, brush_pos_prev_re_, brush_pos_re_);
214 if (distance_to_brush_sq_re > brush_radius_sq_re) {
219 const float distance_to_brush_re = std::sqrt(distance_to_brush_sq_re);
221 const float radius_falloff = BKE_brush_curve_strength(
222 brush_, distance_to_brush_re, brush_radius_re);
224 const float weight = brush_strength_ * radius_falloff * point_factors_[point_i];
228 const float2 new_symm_pos_re = old_symm_pos_re + brush_pos_diff_re_ * weight;
229 float3 new_symm_pos_wo;
230 ED_view3d_win_to_3d(ctx_.v3d,
232 transforms_.curves_to_world * old_symm_pos_cu,
235 const float3 new_pos_cu = brush_transform *
236 (transforms_.world_to_curves * new_symm_pos_wo);
238 const float3 translation_eval = new_pos_cu - old_pos_cu;
239 const float3 translation_orig = deformation.translation_from_deformed_to_original(
240 point_i, translation_eval);
241 positions_cu_orig[point_i] += translation_orig;
243 curve_changed = true;
246 local_changed_curves.append(curve_i);
260 float3 brush_start_wo, brush_end_wo;
263 transforms_.curves_to_world * self_->brush_3d_.position_cu,
268 transforms_.curves_to_world * self_->brush_3d_.position_cu,
271 const float3 brush_start_cu = transforms_.world_to_curves * brush_start_wo;
272 const float3 brush_end_cu = transforms_.world_to_curves * brush_end_wo;
274 const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_;
278 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
279 this->comb_spherical(r_changed_curves,
280 brush_transform * brush_start_cu,
281 brush_transform * brush_end_cu,
287 const float3 &brush_start_cu,
288 const float3 &brush_end_cu,
289 const float brush_radius_cu)
292 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
293 const float3 brush_diff_cu = brush_end_cu - brush_start_cu;
299 Vector<int> &local_changed_curves = r_changed_curves.local();
300 for (const int curve_i : curve_selection_.slice(range)) {
301 bool curve_changed = false;
302 const IndexRange points = curves_orig_->points_for_curve(curve_i);
303 for (const int point_i : points.drop_front(1)) {
304 const float3 pos_old_cu = deformation.positions[point_i];
307 const float distance_to_brush_sq_cu = dist_squared_to_line_segment_v3(
308 pos_old_cu, brush_start_cu, brush_end_cu);
309 if (distance_to_brush_sq_cu > brush_radius_sq_cu) {
314 const float distance_to_brush_cu = std::sqrt(distance_to_brush_sq_cu);
317 const float radius_falloff = BKE_brush_curve_strength(
318 brush_, distance_to_brush_cu, brush_radius_cu);
320 const float weight = brush_strength_ * radius_falloff * point_factors_[point_i];
322 const float3 translation_eval_cu = weight * brush_diff_cu;
323 const float3 translation_orig_cu = deformation.translation_from_deformed_to_original(
324 point_i, translation_eval_cu);
327 positions_cu[point_i] += translation_orig_cu;
328 curve_changed = true;
331 local_changed_curves.append(curve_i);
348 brush_radius_base_re_);
349 if (brush_3d.has_value()) {
350 self_->brush_3d_ = *brush_3d;
360 const Span<float3> positions_cu = curves_orig_->positions();
361 self_->segment_lengths_cu_.reinitialize(curves_orig_->points_num());
363 for (const int curve_i : range) {
364 const IndexRange points = curves_orig_->points_for_curve(curve_i);
365 for (const int point_i : points.drop_back(1)) {
366 const float3 &p1_cu = positions_cu[point_i];
367 const float3 &p2_cu = positions_cu[point_i + 1];
368 const float length_cu = math::distance(p1_cu, p2_cu);
369 self_->segment_lengths_cu_[point_i] = length_cu;
380 const Span<float> expected_lengths_cu = self_->segment_lengths_cu_;
385 for (const int curve_i : changed_curves.as_span().slice(range)) {
386 const IndexRange points = curves_orig_->points_for_curve(curve_i);
387 for (const int segment_i : points.drop_back(1)) {
388 const float3 &p1_cu = positions_cu[segment_i];
389 float3 &p2_cu = positions_cu[segment_i + 1];
390 const float3 direction = math::normalize(p2_cu - p1_cu);
391 const float expected_length_cu = expected_lengths_cu[segment_i];
392 p2_cu = p1_cu + direction * expected_length_cu;
403 executor.execute(*
this,
C, stroke_extension);
408 return std::make_unique<CombOperation>();
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush)
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()
A KD-tree for nearest neighbor search.
MINLINE float pow2f(float x)
#define BLI_SCOPED_DEFER(function_to_defer)
void DEG_id_tag_update(struct ID *id, int flag)
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
struct CurvesGeometry CurvesGeometry
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
IndexRange index_range() const
MutableSpan< float3 > positions_for_write()
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
void tag_positions_changed()
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
const Depsgraph * depsgraph
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig)
std::unique_ptr< CurvesSculptStrokeOperation > new_comb_operation()
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)
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 parallel_for(IndexRange range, int64_t grain_size, const Function &function)
void parallel_for_each(Range &range, const Function &function)
struct ToolSettings * toolsettings
void comb_projected(EnumerableThreadSpecific< Vector< int >> &r_changed_curves, const float4x4 &brush_transform)
VArray< float > point_factors_
CombOperationExecutor(const bContext &C)
void initialize_spherical_brush_reference_point()
IndexMask curve_selection_
float brush_radius_factor_
eBrushFalloffShape falloff_shape_
void initialize_segment_lengths()
Vector< int64_t > selected_curve_indices_
void comb_spherical(EnumerableThreadSpecific< Vector< int >> &r_changed_curves, const float3 &brush_start_cu, const float3 &brush_end_cu, const float brush_radius_cu)
void restore_segment_lengths(EnumerableThreadSpecific< Vector< int >> &changed_curves)
void comb_spherical_with_symmetry(EnumerableThreadSpecific< Vector< int >> &r_changed_curves)
float brush_radius_base_re_
void comb_projected_with_symmetry(EnumerableThreadSpecific< Vector< int >> &r_changed_curves)
float2 brush_pos_prev_re_
CurvesGeometry * curves_orig_
CurvesSculptCommonContext ctx_
const CurvesSculpt * curves_sculpt_
void execute(CombOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
float2 brush_pos_diff_re_
CurvesSurfaceTransforms transforms_
float4x4 inverted() const
void WM_main_add_notifier(unsigned int type, void *reference)