39using bke::CurvesGeometry;
44 bool clear_selection_;
52 : use_select_(use_select), clear_selection_(clear_selection)
105 if (
self.clear_selection_) {
154 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
170 const float brush_radius_sq_re =
pow2f(brush_radius_re);
173 for (const int point_i : point_range) {
174 const float3 pos_cu = math::transform_point(brush_transform_inv,
175 deformation.positions[point_i]);
178 const float2 pos_re = ED_view3d_project_float_v2_m4(ctx_.region, pos_cu, projection);
180 const float distance_to_brush_sq_re = math::distance_squared(pos_re, brush_pos_re_);
181 if (distance_to_brush_sq_re > brush_radius_sq_re) {
186 const float distance_to_brush_re = std::sqrt(distance_to_brush_sq_re);
188 const float radius_falloff = BKE_brush_curve_strength(
189 brush_, distance_to_brush_re, brush_radius_re);
191 const float weight = brush_strength_ * radius_falloff;
193 selection[point_i] = math::interpolate(selection[point_i], selection_goal_, weight);
212 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
213 this->paint_point_selection_spherical(selection,
223 const float brush_radius_cu = self_->brush_3d_.radius_cu;
224 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
227 for (const int i : point_range) {
228 const float3 pos_old_cu = deformation.positions[i];
231 const float distance_to_brush_sq_cu = math::distance_squared(pos_old_cu, brush_cu);
232 if (distance_to_brush_sq_cu > brush_radius_sq_cu) {
237 const float distance_to_brush_cu = std::sqrt(distance_to_brush_sq_cu);
240 const float radius_falloff = BKE_brush_curve_strength(
241 brush_, distance_to_brush_cu, brush_radius_cu);
243 const float weight = brush_strength_ * radius_falloff;
245 selection[i] = math::interpolate(selection[i], selection_goal_, weight);
254 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
255 this->paint_curve_selection_projected(brush_transform, selection);
265 bke::crazyspace::get_evaluated_curves_deformation(*ctx_.depsgraph, *object_);
266 const OffsetIndices points_by_curve = curves_->points_by_curve();
270 const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
271 const float brush_radius_sq_re =
pow2f(brush_radius_re);
273 threading::parallel_for(curves_->curves_range(), 1024, [&](
const IndexRange curves_range) {
274 for (const int curve_i : curves_range) {
275 const float max_weight = threading::parallel_reduce(
276 points_by_curve[curve_i].drop_back(1),
279 [&](const IndexRange segment_range, const float init) {
280 float max_weight = init;
281 for (const int segment_i : segment_range) {
282 const float3 pos1_cu = math::transform_point(brush_transform_inv,
283 deformation.positions[segment_i]);
284 const float3 pos2_cu = math::transform_point(brush_transform_inv,
285 deformation.positions[segment_i + 1]);
287 const float2 pos1_re = ED_view3d_project_float_v2_m4(
288 ctx_.region, pos1_cu, projection);
289 const float2 pos2_re = ED_view3d_project_float_v2_m4(
290 ctx_.region, pos2_cu, projection);
292 const float distance_sq_re = dist_squared_to_line_segment_v2(
293 brush_pos_re_, pos1_re, pos2_re);
294 if (distance_sq_re > brush_radius_sq_re) {
297 const float radius_falloff = BKE_brush_curve_strength(
298 brush_, std::sqrt(distance_sq_re), brush_radius_re);
299 const float weight = brush_strength_ * radius_falloff;
300 max_weight = std::max(max_weight, weight);
304 [](float a, float b) { return std::max(a, b); });
305 selection[curve_i] = math::interpolate(selection[curve_i], selection_goal_, max_weight);
324 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
325 this->paint_curve_selection_spherical(selection,
333 bke::crazyspace::get_evaluated_curves_deformation(*ctx_.depsgraph, *object_);
334 const OffsetIndices points_by_curve = curves_->points_by_curve();
336 const float brush_radius_cu = self_->brush_3d_.radius_cu;
337 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
339 threading::parallel_for(curves_->curves_range(), 1024, [&](
const IndexRange curves_range) {
340 for (const int curve_i : curves_range) {
341 const float max_weight = threading::parallel_reduce(
342 points_by_curve[curve_i].drop_back(1),
345 [&](const IndexRange segment_range, const float init) {
346 float max_weight = init;
347 for (const int segment_i : segment_range) {
348 const float3 &pos1_cu = deformation.positions[segment_i];
349 const float3 &pos2_cu = deformation.positions[segment_i + 1];
351 const float distance_sq_cu = dist_squared_to_line_segment_v3(
352 brush_cu, pos1_cu, pos2_cu);
353 if (distance_sq_cu > brush_radius_sq_cu) {
356 const float radius_falloff = BKE_brush_curve_strength(
357 brush_, std::sqrt(distance_sq_cu), brush_radius_cu);
358 const float weight = brush_strength_ * radius_falloff;
359 max_weight = std::max(max_weight, weight);
363 [](float a, float b) { return std::max(a, b); });
364 selection[curve_i] = math::interpolate(selection[curve_i], selection_goal_, max_weight);
377 brush_radius_base_re_);
378 if (brush_3d.has_value()) {
379 self_->brush_3d_ = *brush_3d;
384void SelectionPaintOperation::on_stroke_extended(
const bContext &C,
388 executor.
execute(*
this, C, stroke_extension);
400 return std::make_unique<SelectionPaintOperation>(use_select, clear_selection);
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
float BKE_brush_alpha_get(const Scene *scene, 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)
Brush * BKE_paint_brush(Paint *paint)
MINLINE float pow2f(float x)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
void ED_region_tag_redraw(ARegion *region)
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)
IndexRange points_range() const
const Depsgraph * depsgraph
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
SelectionPaintOperation(const bool use_select, const bool clear_selection)
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig)
void fill_selection_false(GMutableSpan selection)
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)
bke::SpanAttributeWriter< float > float_selection_ensure(Curves &curves_id)
std::unique_ptr< CurvesSculptStrokeOperation > new_selection_paint_operation(const BrushStrokeMode brush_mode, const bContext &C)
Vector< float4x4 > get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
CartesianBasis invert(const CartesianBasis &basis)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
struct ToolSettings * toolsettings
MutableVArraySpan< T > span
bke::SpanAttributeWriter< float > selection_
CurvesSculptCommonContext ctx_
void paint_point_selection_spherical_with_symmetry(MutableSpan< float > selection)
CurvesSurfaceTransforms transforms_
void paint_point_selection_spherical(MutableSpan< float > selection, const float3 &brush_cu)
void paint_curve_selection_projected(const float4x4 &brush_transform, MutableSpan< float > selection)
float brush_radius_factor_
SelectionPaintOperation * self_
void paint_point_selection_projected_with_symmetry(MutableSpan< float > selection)
SelectionPaintOperationExecutor(const bContext &C)
void paint_curve_selection_spherical(MutableSpan< float > selection, const float3 &brush_cu)
void paint_point_selection_projected(const float4x4 &brush_transform, MutableSpan< float > selection)
float brush_radius_base_re_
void paint_curve_selection_spherical_with_symmetry(MutableSpan< float > selection)
void paint_curve_selection_projected_with_symmetry(MutableSpan< float > selection)
void execute(SelectionPaintOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
void initialize_spherical_brush_reference_point()
void WM_main_add_notifier(uint type, void *reference)