diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/curves_sculpt_add.cc')
-rw-r--r-- | source/blender/editors/sculpt_paint/curves_sculpt_add.cc | 177 |
1 files changed, 117 insertions, 60 deletions
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc index d7f4b71d2d0..f013fa05f4c 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_add.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_add.cc @@ -19,6 +19,7 @@ #include "BKE_context.h" #include "BKE_curves.hh" #include "BKE_curves_utils.hh" +#include "BKE_geometry_set.hh" #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_paint.h" @@ -85,10 +86,7 @@ static void initialize_straight_curve_positions(const float3 &p1, */ struct AddOperationExecutor { AddOperation *self_ = nullptr; - const Depsgraph *depsgraph_ = nullptr; - const Scene *scene_ = nullptr; - ARegion *region_ = nullptr; - const View3D *v3d_ = nullptr; + CurvesSculptCommonContext ctx_; Object *object_ = nullptr; Curves *curves_id_ = nullptr; @@ -98,6 +96,7 @@ struct AddOperationExecutor { Mesh *surface_ = nullptr; Span<MLoopTri> surface_looptris_; Span<float3> corner_normals_su_; + VArray_Span<float2> surface_uv_map_; const CurvesSculpt *curves_sculpt_ = nullptr; const Brush *brush_ = nullptr; @@ -117,6 +116,7 @@ struct AddOperationExecutor { /** Various matrices to convert between coordinate spaces. */ float4x4 curves_to_world_mat_; + float4x4 curves_to_surface_mat_; float4x4 world_to_curves_mat_; float4x4 world_to_surface_mat_; float4x4 surface_to_world_mat_; @@ -143,14 +143,14 @@ struct AddOperationExecutor { static constexpr int max_neighbors = 5; using NeighborsVector = Vector<NeighborInfo, max_neighbors>; + AddOperationExecutor(const bContext &C) : ctx_(C) + { + } + void execute(AddOperation &self, const bContext &C, const StrokeExtension &stroke_extension) { self_ = &self; - depsgraph_ = CTX_data_depsgraph_pointer(&C); - scene_ = CTX_data_scene(&C); object_ = CTX_data_active_object(&C); - region_ = CTX_wm_region(&C); - v3d_ = CTX_wm_view3d(&C); curves_id_ = static_cast<Curves *>(object_->data); curves_ = &CurvesGeometry::wrap(curves_id_->geometry); @@ -168,6 +168,7 @@ struct AddOperationExecutor { world_to_surface_mat_ = surface_to_world_mat_.inverted(); surface_to_curves_mat_ = world_to_curves_mat_ * surface_to_world_mat_; surface_to_curves_normal_mat_ = surface_to_curves_mat_.inverted().transposed(); + curves_to_surface_mat_ = world_to_surface_mat_ * curves_to_world_mat_; if (!CustomData_has_layer(&surface_->ldata, CD_NORMAL)) { BKE_mesh_calc_normals_split(surface_); @@ -176,10 +177,10 @@ struct AddOperationExecutor { reinterpret_cast<const float3 *>(CustomData_get_layer(&surface_->ldata, CD_NORMAL)), surface_->totloop}; - curves_sculpt_ = scene_->toolsettings->curves_sculpt; + curves_sculpt_ = ctx_.scene->toolsettings->curves_sculpt; brush_ = BKE_paint_brush_for_read(&curves_sculpt_->paint); brush_settings_ = brush_->curves_sculpt_settings; - brush_radius_re_ = brush_radius_get(*scene_, *brush_, stroke_extension); + brush_radius_re_ = brush_radius_get(*ctx_.scene, *brush_, stroke_extension); brush_pos_re_ = stroke_extension.mouse_position; use_front_face_ = brush_->flag & BRUSH_FRONTFACE; @@ -211,6 +212,15 @@ struct AddOperationExecutor { surface_looptris_ = {BKE_mesh_runtime_looptri_ensure(surface_), BKE_mesh_runtime_looptri_len(surface_)}; + if (curves_id_->surface_uv_map != nullptr) { + MeshComponent surface_component; + surface_component.replace(surface_, GeometryOwnershipType::ReadOnly); + surface_uv_map_ = surface_component + .attribute_try_get_for_read(curves_id_->surface_uv_map, + ATTR_DOMAIN_CORNER) + .typed<float2>(); + } + /* Sample points on the surface using one of multiple strategies. */ AddedPoints added_points; if (add_amount_ == 1) { @@ -256,17 +266,7 @@ struct AddOperationExecutor { 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_); - } - - float3 get_bary_coords(const Mesh &mesh, const MLoopTri &looptri, const float3 position) const - { - const float3 &v0 = mesh.mvert[mesh.mloop[looptri.tri[0]].v].co; - const float3 &v1 = mesh.mvert[mesh.mloop[looptri.tri[1]].v].co; - const float3 &v2 = mesh.mvert[mesh.mloop[looptri.tri[2]].v].co; - float3 bary_coords; - interp_weights_tri_v3(bary_coords, v0, v1, v2, position); - return bary_coords; + ED_region_tag_redraw(ctx_.region); } /** @@ -276,16 +276,16 @@ struct AddOperationExecutor { { float3 ray_start_wo, ray_end_wo; ED_view3d_win_to_segment_clipped( - depsgraph_, region_, v3d_, brush_pos_re_, ray_start_wo, ray_end_wo, true); - const float3 ray_start_su = world_to_surface_mat_ * ray_start_wo; - const float3 ray_end_su = world_to_surface_mat_ * ray_end_wo; + ctx_.depsgraph, ctx_.region, ctx_.v3d, brush_pos_re_, ray_start_wo, ray_end_wo, true); + const float3 ray_start_cu = world_to_curves_mat_ * ray_start_wo; + const float3 ray_end_cu = world_to_curves_mat_ * ray_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->sample_in_center( - r_added_points, brush_transform * ray_start_su, brush_transform * ray_end_su); + const float4x4 transform = curves_to_surface_mat_ * brush_transform; + this->sample_in_center(r_added_points, transform * ray_start_cu, transform * ray_end_cu); } } @@ -312,7 +312,7 @@ struct AddOperationExecutor { const int looptri_index = ray_hit.index; const float3 brush_pos_su = ray_hit.co; - const float3 bary_coords = this->get_bary_coords( + const float3 bary_coords = compute_bary_coord_in_triangle( *surface_, surface_looptris_[looptri_index], brush_pos_su); const float3 brush_pos_cu = surface_to_curves_mat_ * brush_pos_su; @@ -352,9 +352,12 @@ struct AddOperationExecutor { float3 ray_start_wo, ray_end_wo; ED_view3d_win_to_segment_clipped( - depsgraph_, region_, v3d_, pos_re, ray_start_wo, ray_end_wo, true); - const float3 ray_start_su = brush_transform * (world_to_surface_mat_ * ray_start_wo); - const float3 ray_end_su = brush_transform * (world_to_surface_mat_ * ray_end_wo); + ctx_.depsgraph, ctx_.region, ctx_.v3d, pos_re, ray_start_wo, ray_end_wo, true); + const float3 ray_start_cu = brush_transform * (world_to_curves_mat_ * ray_start_wo); + const float3 ray_end_cu = brush_transform * (world_to_curves_mat_ * ray_end_wo); + + const float3 ray_start_su = curves_to_surface_mat_ * ray_start_cu; + const float3 ray_end_su = curves_to_surface_mat_ * ray_end_cu; const float3 ray_direction_su = math::normalize(ray_end_su - ray_start_su); BVHTreeRayHit ray_hit; @@ -382,7 +385,7 @@ struct AddOperationExecutor { const int looptri_index = ray_hit.index; const float3 pos_su = ray_hit.co; - const float3 bary_coords = this->get_bary_coords( + const float3 bary_coords = compute_bary_coord_in_triangle( *surface_, surface_looptris_[looptri_index], pos_su); const float3 pos_cu = surface_to_curves_mat_ * pos_su; @@ -400,33 +403,39 @@ struct AddOperationExecutor { { /* Find ray that starts in the center of the brush. */ float3 brush_ray_start_wo, brush_ray_end_wo; - ED_view3d_win_to_segment_clipped( - depsgraph_, region_, v3d_, brush_pos_re_, brush_ray_start_wo, brush_ray_end_wo, true); - const float3 brush_ray_start_su = world_to_surface_mat_ * brush_ray_start_wo; - const float3 brush_ray_end_su = world_to_surface_mat_ * brush_ray_end_wo; + ED_view3d_win_to_segment_clipped(ctx_.depsgraph, + ctx_.region, + ctx_.v3d, + brush_pos_re_, + brush_ray_start_wo, + brush_ray_end_wo, + true); + const float3 brush_ray_start_cu = world_to_curves_mat_ * brush_ray_start_wo; + const float3 brush_ray_end_cu = world_to_curves_mat_ * brush_ray_end_wo; /* Find ray that starts on the boundary of the brush. That is used to compute the brush radius * in 3D. */ float3 brush_radius_ray_start_wo, brush_radius_ray_end_wo; - ED_view3d_win_to_segment_clipped(depsgraph_, - region_, - v3d_, + ED_view3d_win_to_segment_clipped(ctx_.depsgraph, + ctx_.region, + ctx_.v3d, brush_pos_re_ + float2(brush_radius_re_, 0), brush_radius_ray_start_wo, brush_radius_ray_end_wo, true); - const float3 brush_radius_ray_start_su = world_to_surface_mat_ * brush_radius_ray_start_wo; - const float3 brush_radius_ray_end_su = world_to_surface_mat_ * brush_radius_ray_end_wo; + const float3 brush_radius_ray_start_cu = world_to_curves_mat_ * brush_radius_ray_start_wo; + const float3 brush_radius_ray_end_cu = world_to_curves_mat_ * brush_radius_ray_end_wo; const Vector<float4x4> symmetry_brush_transforms = get_symmetry_brush_transforms( eCurvesSymmetryType(curves_id_->symmetry)); for (const float4x4 &brush_transform : symmetry_brush_transforms) { + const float4x4 transform = curves_to_surface_mat_ * brush_transform; this->sample_spherical(rng, r_added_points, - brush_transform * brush_ray_start_su, - brush_transform * brush_ray_end_su, - brush_transform * brush_radius_ray_start_su, - brush_transform * brush_radius_ray_end_su); + transform * brush_ray_start_cu, + transform * brush_ray_end_cu, + transform * brush_radius_ray_start_cu, + transform * brush_radius_ray_end_cu); } } @@ -650,7 +659,11 @@ struct AddOperationExecutor { } Array<float3> new_normals_su = this->compute_normals_for_added_curves_su(added_points); - this->initialize_surface_attachment(added_points); + if (!surface_uv_map_.is_empty()) { + this->initialize_surface_attachment(added_points); + } + + this->fill_new_selection(); if (interpolate_shape_) { this->initialize_position_with_interpolation( @@ -662,6 +675,33 @@ struct AddOperationExecutor { } } + /** + * Select newly created points or curves in new curves if necessary. + */ + void fill_new_selection() + { + switch (curves_id_->selection_domain) { + case ATTR_DOMAIN_CURVE: { + const VArray<float> selection = curves_->selection_curve_float(); + if (selection.is_single() && selection.get_internal_single() >= 1.0f) { + return; + } + curves_->selection_curve_float_for_write().drop_front(tot_old_curves_).fill(1.0f); + break; + } + case ATTR_DOMAIN_POINT: { + const VArray<float> selection = curves_->selection_point_float(); + if (selection.is_single() && selection.get_internal_single() >= 1.0f) { + return; + } + curves_->selection_point_float_for_write().drop_front(tot_old_points_).fill(1.0f); + break; + } + default: + BLI_assert_unreachable(); + } + } + Array<NeighborsVector> find_curve_neighbors(const AddedPoints &added_points) { const int tot_added_curves = added_points.bary_coords.size(); @@ -736,7 +776,8 @@ struct AddOperationExecutor { for (const int i : range) { const int looptri_index = added_points.looptri_indices[i]; const float3 &bary_coord = added_points.bary_coords[i]; - normals_su[i] = this->compute_point_normal_su(looptri_index, bary_coord); + normals_su[i] = compute_surface_point_normal( + surface_looptris_[looptri_index], bary_coord, corner_normals_su_); } }); return normals_su; @@ -744,14 +785,18 @@ struct AddOperationExecutor { void initialize_surface_attachment(const AddedPoints &added_points) { - MutableSpan<int> surface_triangle_indices = curves_->surface_triangle_indices_for_write(); - MutableSpan<float2> surface_triangle_coords = curves_->surface_triangle_coords_for_write(); + MutableSpan<float2> surface_uv_coords = curves_->surface_uv_coords_for_write(); threading::parallel_for( added_points.bary_coords.index_range(), 1024, [&](const IndexRange range) { for (const int i : range) { const int curve_i = tot_old_curves_ + i; - surface_triangle_indices[curve_i] = added_points.looptri_indices[i]; - surface_triangle_coords[curve_i] = float2(added_points.bary_coords[i]); + const MLoopTri &looptri = surface_looptris_[added_points.looptri_indices[i]]; + const float2 &uv0 = surface_uv_map_[looptri.tri[0]]; + const float2 &uv1 = surface_uv_map_[looptri.tri[1]]; + const float2 &uv2 = surface_uv_map_[looptri.tri[2]]; + const float3 &bary_coords = added_points.bary_coords[i]; + const float2 uv = attribute_math::mix3(bary_coords, uv0, uv1, uv2); + surface_uv_coords[curve_i] = uv; } }); } @@ -789,8 +834,6 @@ struct AddOperationExecutor { const Span<float> new_lengths_cu) { MutableSpan<float3> positions_cu = curves_->positions_for_write(); - const VArray_Span<int> surface_triangle_indices{curves_->surface_triangle_indices()}; - const Span<float2> surface_triangle_coords = curves_->surface_triangle_coords(); threading::parallel_for( added_points.bary_coords.index_range(), 256, [&](const IndexRange range) { @@ -815,13 +858,27 @@ struct AddOperationExecutor { for (const NeighborInfo &neighbor : neighbors) { const int neighbor_curve_i = neighbor.index; - const int neighbor_looptri_index = surface_triangle_indices[neighbor_curve_i]; - - float3 neighbor_bary_coord{surface_triangle_coords[neighbor_curve_i]}; - neighbor_bary_coord.z = 1.0f - neighbor_bary_coord.x - neighbor_bary_coord.y; - - const float3 neighbor_normal_su = this->compute_point_normal_su( - neighbor_looptri_index, neighbor_bary_coord); + const float3 &neighbor_first_pos_cu = + positions_cu[curves_->offsets()[neighbor_curve_i]]; + const float3 neighbor_first_pos_su = curves_to_surface_mat_ * neighbor_first_pos_cu; + + BVHTreeNearest nearest; + nearest.dist_sq = FLT_MAX; + BLI_bvhtree_find_nearest(surface_bvh_.tree, + neighbor_first_pos_su, + &nearest, + surface_bvh_.nearest_callback, + &surface_bvh_); + const int neighbor_looptri_index = nearest.index; + const MLoopTri &neighbor_looptri = surface_looptris_[neighbor_looptri_index]; + + const float3 neighbor_bary_coord = compute_bary_coord_in_triangle( + *surface_, neighbor_looptri, nearest.co); + + const float3 neighbor_normal_su = compute_surface_point_normal( + surface_looptris_[neighbor_looptri_index], + neighbor_bary_coord, + corner_normals_su_); const float3 neighbor_normal_cu = math::normalize(surface_to_curves_normal_mat_ * neighbor_normal_su); @@ -866,7 +923,7 @@ struct AddOperationExecutor { void AddOperation::on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) { - AddOperationExecutor executor; + AddOperationExecutor executor{C}; executor.execute(*this, C, stroke_extension); } |