diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/curves_sculpt_delete.cc')
-rw-r--r-- | source/blender/editors/sculpt_paint/curves_sculpt_delete.cc | 136 |
1 files changed, 83 insertions, 53 deletions
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc b/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc index 2841a19d677..bd0bbad3bb8 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_delete.cc @@ -35,6 +35,8 @@ #include "ED_screen.h" #include "ED_view3d.h" +#include "WM_api.h" + /** * The code below uses a suffix naming convention to indicate the coordinate space: * cu: Local space of the curves object that is being edited. @@ -117,56 +119,71 @@ struct DeleteOperationExecutor { } } + Array<bool> curves_to_delete(curves_->curves_num(), false); if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - this->delete_projected(); + this->delete_projected_with_symmetry(curves_to_delete); } else if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) { - this->delete_spherical(); + this->delete_spherical_with_symmetry(curves_to_delete); } else { BLI_assert_unreachable(); } + Vector<int64_t> indices; + const IndexMask mask = index_mask_ops::find_indices_based_on_predicate( + curves_->curves_range(), 4096, indices, [&](const int curve_i) { + return curves_to_delete[curve_i]; + }); + + curves_->remove_curves(mask); + DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY); + WM_main_add_notifier(NC_GEOM | ND_DATA, &curves_id_->id); ED_region_tag_redraw(region_); } - void delete_projected() + void delete_projected_with_symmetry(MutableSpan<bool> curves_to_delete) + { + const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( + eCurvesSymmetryType(curves_id_->symmetry)); + for (const float4x4 &brush_transform : symmetry_brush_transforms) { + this->delete_projected(curves_to_delete, brush_transform); + } + } + + void delete_projected(MutableSpan<bool> curves_to_delete, const float4x4 &brush_transform) { + const float4x4 brush_transform_inv = brush_transform.inverted(); + float4x4 projection; ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values); Span<float3> positions_cu = curves_->positions(); - /* Find indices of curves that have to be removed. */ - Vector<int64_t> indices; - const IndexMask curves_to_remove = index_mask_ops::find_indices_based_on_predicate( - curves_->curves_range(), 512, indices, [&](const int curve_i) { - const IndexRange point_range = curves_->points_for_curve(curve_i); - for (const int segment_i : IndexRange(point_range.size() - 1)) { - const float3 pos1_cu = positions_cu[point_range[segment_i]]; - const float3 pos2_cu = positions_cu[point_range[segment_i + 1]]; - - float2 pos1_re, pos2_re; - ED_view3d_project_float_v2_m4(region_, pos1_cu, pos1_re, projection.values); - ED_view3d_project_float_v2_m4(region_, pos2_cu, pos2_re, projection.values); - - const float dist = dist_seg_seg_v2( - pos1_re, pos2_re, brush_pos_prev_re_, brush_pos_re_); - if (dist <= brush_radius_re_) { - return true; - } + threading::parallel_for(curves_->curves_range(), 512, [&](IndexRange curve_range) { + for (const int curve_i : curve_range) { + const IndexRange points = curves_->points_for_curve(curve_i); + for (const int segment_i : IndexRange(points.size() - 1)) { + const float3 pos1_cu = brush_transform_inv * positions_cu[points[segment_i]]; + const float3 pos2_cu = brush_transform_inv * positions_cu[points[segment_i + 1]]; + + float2 pos1_re, pos2_re; + ED_view3d_project_float_v2_m4(region_, pos1_cu, pos1_re, projection.values); + ED_view3d_project_float_v2_m4(region_, pos2_cu, pos2_re, projection.values); + + const float dist = dist_seg_seg_v2(pos1_re, pos2_re, brush_pos_prev_re_, brush_pos_re_); + if (dist <= brush_radius_re_) { + curves_to_delete[curve_i] = true; + break; } - return false; - }); - - curves_->remove_curves(curves_to_remove); + } + } + }); } - void delete_spherical() + void delete_spherical_with_symmetry(MutableSpan<bool> curves_to_delete) { - Span<float3> positions_cu = curves_->positions(); - float4x4 projection; ED_view3d_ob_project_mat_get(rv3d_, object_, projection.values); @@ -184,35 +201,48 @@ struct DeleteOperationExecutor { const float3 brush_start_cu = world_to_curves_mat_ * brush_start_wo; const float3 brush_end_cu = world_to_curves_mat_ * brush_end_wo; + const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( + eCurvesSymmetryType(curves_id_->symmetry)); + + for (const float4x4 &brush_transform : symmetry_brush_transforms) { + this->delete_spherical( + curves_to_delete, brush_transform * brush_start_cu, brush_transform * brush_end_cu); + } + } + + void delete_spherical(MutableSpan<bool> curves_to_delete, + const float3 &brush_start_cu, + const float3 &brush_end_cu) + { + Span<float3> positions_cu = curves_->positions(); + const float brush_radius_cu = self_->brush_3d_.radius_cu; const float brush_radius_sq_cu = pow2f(brush_radius_cu); - Vector<int64_t> indices; - const IndexMask curves_to_remove = index_mask_ops::find_indices_based_on_predicate( - curves_->curves_range(), 512, indices, [&](const int curve_i) { - const IndexRange points = curves_->points_for_curve(curve_i); - for (const int segment_i : IndexRange(points.size() - 1)) { - const float3 pos1_cu = positions_cu[points[segment_i]]; - const float3 pos2_cu = positions_cu[points[segment_i] + 1]; - - float3 closest_segment_cu, closest_brush_cu; - isect_seg_seg_v3(pos1_cu, - pos2_cu, - brush_start_cu, - brush_end_cu, - closest_segment_cu, - closest_brush_cu); - const float distance_to_brush_sq_cu = math::distance_squared(closest_segment_cu, - closest_brush_cu); - if (distance_to_brush_sq_cu > brush_radius_sq_cu) { - continue; - } - return true; + threading::parallel_for(curves_->curves_range(), 512, [&](IndexRange curve_range) { + for (const int curve_i : curve_range) { + const IndexRange points = curves_->points_for_curve(curve_i); + for (const int segment_i : IndexRange(points.size() - 1)) { + const float3 pos1_cu = positions_cu[points[segment_i]]; + const float3 pos2_cu = positions_cu[points[segment_i] + 1]; + + float3 closest_segment_cu, closest_brush_cu; + isect_seg_seg_v3(pos1_cu, + pos2_cu, + brush_start_cu, + brush_end_cu, + closest_segment_cu, + closest_brush_cu); + const float distance_to_brush_sq_cu = math::distance_squared(closest_segment_cu, + closest_brush_cu); + if (distance_to_brush_sq_cu > brush_radius_sq_cu) { + continue; } - return false; - }); - - curves_->remove_curves(curves_to_remove); + curves_to_delete[curve_i] = true; + break; + } + } + }); } void initialize_spherical_brush_reference_point() |