44using geometry::ReverseUVSampler;
66 float2 initial_brush_pos_re_;
146 "Curves do not have surface attachment information");
210 self_->initial_deformed_positions_cu_ = deformation.positions;
240 if (!brush_3d.has_value()) {
245 for (
const float4x4 &brush_transform : brush_transforms) {
246 self_->slide_info_.append_as();
251 reverse_uv_sampler_orig,
257 const float brush_radius_cu,
262 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
266 for (
const int curve_i : segment) {
267 const int first_point_i = offsets[curve_i];
268 const float3 old_pos_cu =
self_->initial_deformed_positions_cu_[first_point_i];
270 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
274 const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
276 brush_, dist_to_brush_cu, brush_radius_cu);
278 const float2 uv = surface_uv_coords[curve_i];
293 r_curves_to_slide.
append({curve_i, radius_falloff, normal_cu});
303 this->
slide(slide_info.curves_to_slide, reverse_uv_sampler_orig, slide_info.brush_transform);
330 for (const SlideCurveInfo &slide_curve_info : slide_curves.slice(range)) {
331 const int curve_i = slide_curve_info.curve_i;
332 const IndexRange points = points_by_curve[curve_i];
333 const int first_point_i = points[0];
335 const float3 old_first_pos_eval_cu = self_->initial_deformed_positions_cu_[first_point_i];
336 const float3 old_first_symm_pos_eval_cu = math::transform_point(brush_transform_inv,
337 old_first_pos_eval_cu);
338 const float3 old_first_pos_eval_su = math::transform_point(transforms_.curves_to_surface,
339 old_first_pos_eval_cu);
341 const float2 old_first_symm_pos_eval_re = ED_view3d_project_float_v2_m4(
342 ctx_.region, old_first_symm_pos_eval_cu, projection);
344 const float radius_falloff = slide_curve_info.radius_falloff;
345 const float curve_weight = brush_strength_ * radius_falloff * curve_factors_[curve_i];
346 const float2 new_first_symm_pos_eval_re = old_first_symm_pos_eval_re +
347 curve_weight * brush_pos_diff_re;
350 float3 ray_start_wo, ray_end_wo;
351 ED_view3d_win_to_segment_clipped(ctx_.depsgraph,
354 new_first_symm_pos_eval_re,
358 const float3 ray_start_su = math::transform_point(world_to_surface_with_symmetry_mat,
360 const float3 ray_end_su = math::transform_point(world_to_surface_with_symmetry_mat,
362 const float3 ray_direction_su = math::normalize(ray_end_su - ray_start_su);
366 float3 hit_pos_eval_su;
367 if (!this->find_closest_ray_hit(ray_start_su,
369 old_first_pos_eval_su,
377 const int3 &tri_eval = surface_corner_tris_eval_[tri_index_eval];
378 const float3 bary_weights_eval = bke::mesh_surface_sample::compute_bary_coord_in_triangle(
379 surface_positions_eval_, surface_corner_verts_eval_, tri_eval, hit_pos_eval_su);
380 const float2 uv = bke::attribute_math::mix3(bary_weights_eval,
381 surface_uv_map_eval_[tri_eval[0]],
382 surface_uv_map_eval_[tri_eval[1]],
383 surface_uv_map_eval_[tri_eval[2]]);
386 const ReverseUVSampler::Result result = reverse_uv_sampler_orig.sample(uv);
387 if (result.type != ReverseUVSampler::ResultType::Ok) {
388 found_invalid_uv_mapping_.store(true);
391 const int3 &tri_orig = surface_corner_tris_orig_[result.tri_index];
392 const float3 &bary_weights_orig = result.bary_weights;
395 const float3 &initial_normal_cu = slide_curve_info.initial_normal_cu;
396 const float3 new_normal_cu = math::normalize(
397 math::transform_point(transforms_.surface_to_curves_normal,
398 geometry::compute_surface_point_normal(
399 tri_orig, result.bary_weights, corner_normals_orig_su_)));
402 const float3 new_first_pos_orig_su = bke::attribute_math::mix3<float3>(
404 positions_orig_su[corner_verts_orig[tri_orig[0]]],
405 positions_orig_su[corner_verts_orig[tri_orig[1]]],
406 positions_orig_su[corner_verts_orig[tri_orig[2]]]);
407 const float3 old_first_pos_orig_cu = self_->initial_positions_cu_[first_point_i];
408 const float3 new_first_pos_orig_cu = math::transform_point(transforms_.surface_to_curves,
409 new_first_pos_orig_su);
412 const float4x4 slide_transform = this->get_slide_transform(
413 old_first_pos_orig_cu, new_first_pos_orig_cu, initial_normal_cu, new_normal_cu);
414 for (const int point_i : points) {
415 positions_orig_cu[point_i] = math::transform_point(
416 slide_transform, self_->initial_positions_cu_[point_i]);
418 surface_uv_coords[curve_i] = uv;
424 const float3 &ray_direction_su,
429 float best_dist_sq_su =
FLT_MAX;
430 int best_tri_index_eval;
432 BLI_bvhtree_ray_cast_all_cpp(
433 *surface_bvh_eval_.tree,
439 surface_bvh_eval_.raycast_callback(&surface_bvh_eval_, tri_index, &ray, &hit);
443 const float3 &hit_pos_su = hit.co;
445 if (dist_sq_su < best_dist_sq_su) {
446 best_dist_sq_su = dist_sq_su;
447 best_hit_pos_su = hit_pos_su;
448 best_tri_index_eval = hit.index;
452 if (best_dist_sq_su ==
FLT_MAX) {
455 r_tri_index = best_tri_index_eval;
456 r_hit_pos = best_hit_pos_su;
461 const float3 &new_root_pos,
468 float4x4 transform = float4x4::identity();
469 transform.location() -= old_root_pos;
471 transform.location() += new_root_pos;
479 executor.
execute(*
this, C, stroke_extension);
484 return std::make_unique<SlideOperation>();
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
float BKE_brush_curve_strength(eBrushCurvePreset preset, const CurveMapping *cumap, float distance, float brush_radius)
void free_bvhtree_from_mesh(BVHTreeFromMesh *data)
BVHTree * BKE_bvhtree_from_mesh_get(BVHTreeFromMesh *data, const Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
@ BVHTREE_FROM_CORNER_TRIS
Object * CTX_data_active_object(const bContext *C)
Low-level operations for curves.
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
const Brush * BKE_paint_brush_for_read(const Paint *paint)
void BKE_report(ReportList *reports, eReportType type, const char *message)
MINLINE float pow2f(float x)
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
#define BLI_SCOPED_DEFER(function_to_defer)
void DEG_id_tag_update(ID *id, unsigned int flags)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
void ED_region_tag_redraw(ARegion *region)
blender::float4x4 ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
constexpr IndexRange index_range() const
void append(const T &value)
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const void *default_value=nullptr) const
MutableSpan< float3 > positions_for_write()
OffsetIndices< int > points_by_curve() const
MutableSpan< float2 > surface_uv_coords_for_write()
Span< int > offsets() const
Span< float3 > positions() const
void tag_positions_changed()
AttributeAccessor attributes() const
Span< float2 > surface_uv_coords() const
const Depsgraph * depsgraph
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
Result sample(const float2 &query_uv) const
void foreach_segment(Fn &&fn) const
GeometryDeformation get_evaluated_curves_deformation(const Object *ob_eval, const Object &ob_orig)
IndexMask retrieve_selected_curves(const bke::CurvesGeometry &curves, IndexMaskMemory &memory)
std::optional< CurvesBrush3D > sample_curves_surface_3d_brush(const Depsgraph &depsgraph, const ARegion ®ion, const View3D &v3d, const CurvesSurfaceTransforms &transforms, const BVHTreeFromMesh &surface_bvh, const float2 &brush_pos_re, const float brush_radius_re)
void report_empty_evaluated_surface(ReportList *reports)
void report_missing_uv_map_on_original_surface(ReportList *reports)
void report_missing_uv_map_on_evaluated_surface(ReportList *reports)
void report_missing_surface(ReportList *reports)
void report_empty_original_surface(ReportList *reports)
float brush_strength_get(const Scene &scene, const Brush &brush, const StrokeExtension &stroke_extension)
Vector< float4x4 > get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
std::unique_ptr< CurvesSculptStrokeOperation > new_slide_operation()
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
float3 compute_surface_point_normal(const int3 &tri, const float3 &bary_coord, Span< float3 > corner_normals)
CartesianBasis invert(const CartesianBasis &basis)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
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
const c_style_mat & ptr() const
Vector< SlideCurveInfo > curves_to_slide
const Mesh * surface_orig_
void execute(SlideOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
CurvesSurfaceTransforms transforms_
VArraySpan< float2 > surface_uv_map_orig_
VArraySpan< float2 > surface_uv_map_eval_
IndexMaskMemory selected_curve_memory_
const CurvesSculpt * curves_sculpt_
void find_curves_to_slide_with_symmetry()
Span< float3 > corner_normals_orig_su_
BVHTreeFromMesh surface_bvh_eval_
Object * surface_ob_orig_
Span< int3 > surface_corner_tris_eval_
CurvesSculptCommonContext ctx_
Span< float3 > surface_positions_eval_
Span< int > surface_corner_verts_eval_
void find_curves_to_slide(const float3 &brush_pos_cu, const float brush_radius_cu, const ReverseUVSampler &reverse_uv_sampler_orig, Vector< SlideCurveInfo > &r_curves_to_slide)
VArray< float > curve_factors_
void slide(const Span< SlideCurveInfo > slide_curves, const ReverseUVSampler &reverse_uv_sampler_orig, const float4x4 &brush_transform)
float brush_radius_factor_
bool find_closest_ray_hit(const float3 &ray_start_su, const float3 &ray_direction_su, const float3 &point_su, int &r_tri_index, float3 &r_hit_pos)
void slide_with_symmetry()
std::atomic< bool > found_invalid_uv_mapping_
SlideOperationExecutor(const bContext &C)
Span< int3 > surface_corner_tris_orig_
float4x4 get_slide_transform(const float3 &old_root_pos, const float3 &new_root_pos, const float3 &old_normal, const float3 &new_normal)
float brush_radius_base_re_
CurvesGeometry * curves_orig_
IndexMask curve_selection_
Object * surface_ob_eval_
void WM_main_add_notifier(uint type, void *reference)