53 using geometry::ReverseUVSampler;
75 float2 initial_brush_pos_re_;
155 TIP_(
"Curves do not have surface attachment information"));
255 if (!brush_3d.has_value()) {
259 for (
const float4x4 &brush_transform : brush_transforms) {
260 self_->slide_info_.append_as();
265 reverse_uv_sampler_orig,
271 const float brush_radius_cu,
276 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
280 const int first_point_i = offsets[curve_i];
281 const float3 old_pos_cu =
self_->initial_deformed_positions_cu_[first_point_i];
283 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
287 const float dist_to_brush_cu =
std::sqrt(dist_to_brush_sq_cu);
289 brush_, dist_to_brush_cu, brush_radius_cu);
291 const float2 uv = surface_uv_coords[curve_i];
304 r_curves_to_slide.
append({curve_i, radius_falloff, normal_cu});
339 for (const SlideCurveInfo &slide_curve_info : slide_curves.slice(range)) {
340 const int curve_i = slide_curve_info.curve_i;
341 const IndexRange points = curves_orig_->points_for_curve(curve_i);
342 const int first_point_i = points[0];
344 const float3 old_first_pos_eval_cu = self_->initial_deformed_positions_cu_[first_point_i];
345 const float3 old_first_symm_pos_eval_cu = brush_transform_inv * old_first_pos_eval_cu;
346 const float3 old_first_pos_eval_su = transforms_.curves_to_surface * old_first_pos_eval_cu;
348 float2 old_first_symm_pos_eval_re;
349 ED_view3d_project_float_v2_m4(ctx_.region,
350 old_first_symm_pos_eval_cu,
351 old_first_symm_pos_eval_re,
354 const float radius_falloff = slide_curve_info.radius_falloff;
355 const float curve_weight = brush_strength_ * radius_falloff * curve_factors_[curve_i];
356 const float2 new_first_symm_pos_eval_re = old_first_symm_pos_eval_re +
357 curve_weight * brush_pos_diff_re;
360 float3 ray_start_wo, ray_end_wo;
361 ED_view3d_win_to_segment_clipped(ctx_.depsgraph,
364 new_first_symm_pos_eval_re,
368 const float3 ray_start_su = world_to_surface_with_symmetry_mat * ray_start_wo;
369 const float3 ray_end_su = world_to_surface_with_symmetry_mat * ray_end_wo;
370 const float3 ray_direction_su = math::normalize(ray_end_su - ray_start_su);
373 int looptri_index_eval;
374 float3 hit_pos_eval_su;
375 if (!this->find_closest_ray_hit(ray_start_su,
377 old_first_pos_eval_su,
384 const MLoopTri &looptri_eval = surface_looptris_eval_[looptri_index_eval];
385 const float3 bary_weights_eval = bke::mesh_surface_sample::compute_bary_coord_in_triangle(
386 *surface_eval_, looptri_eval, hit_pos_eval_su);
387 const float2 uv = attribute_math::mix3(bary_weights_eval,
388 surface_uv_map_eval_[looptri_eval.tri[0]],
389 surface_uv_map_eval_[looptri_eval.tri[1]],
390 surface_uv_map_eval_[looptri_eval.tri[2]]);
393 const ReverseUVSampler::Result result = reverse_uv_sampler_orig.sample(uv);
394 if (result.type != ReverseUVSampler::ResultType::Ok) {
395 found_invalid_uv_mapping_.store(true);
398 const MLoopTri &looptri_orig = *result.looptri;
399 const float3 &bary_weights_orig = result.bary_weights;
402 const float3 &initial_normal_cu = slide_curve_info.initial_normal_cu;
403 const float3 new_normal_cu = math::normalize(
404 transforms_.surface_to_curves_normal *
405 geometry::compute_surface_point_normal(
406 *result.looptri, result.bary_weights, corner_normals_orig_su_));
409 const float3 old_first_pos_orig_cu = self_->initial_positions_cu_[first_point_i];
410 const float3 new_first_pos_orig_cu =
411 transforms_.surface_to_curves *
412 attribute_math::mix3<float3>(bary_weights_orig,
413 verts_orig_su[loops_orig[looptri_orig.tri[0]].v].co,
414 verts_orig_su[loops_orig[looptri_orig.tri[1]].v].co,
415 verts_orig_su[loops_orig[looptri_orig.tri[2]].v].co);
418 const float4x4 slide_transform = this->get_slide_transform(
419 old_first_pos_orig_cu, new_first_pos_orig_cu, initial_normal_cu, new_normal_cu);
420 for (const int point_i : points) {
421 positions_orig_cu[point_i] = slide_transform * self_->initial_positions_cu_[point_i];
423 surface_uv_coords[curve_i] = uv;
429 const float3 &ray_direction_su,
431 int &r_looptri_index,
434 float best_dist_sq_su = FLT_MAX;
435 int best_looptri_index_eval;
437 BLI_bvhtree_ray_cast_all_cpp(
438 *surface_bvh_eval_.tree,
444 surface_bvh_eval_.raycast_callback(&surface_bvh_eval_, looptri_index, &ray, &hit);
450 if (dist_sq_su < best_dist_sq_su) {
451 best_dist_sq_su = dist_sq_su;
452 best_hit_pos_su = hit_pos_su;
453 best_looptri_index_eval = hit.
index;
457 if (best_dist_sq_su == FLT_MAX) {
460 r_looptri_index = best_looptri_index_eval;
461 r_hit_pos = best_hit_pos_su;
466 const float3 &new_root_pos,
486 executor.execute(*
this,
C, stroke_extension);
491 return std::make_unique<SlideOperation>();
float BKE_brush_curve_strength(const struct Brush *br, float p, float len)
int BKE_brush_size_get(const struct Scene *scene, const struct Brush *brush)
void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
BVHTree * BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data, const struct Mesh *mesh, BVHCacheType bvh_cache_type, int tree_type)
struct Object * CTX_data_active_object(const bContext *C)
Low-level operations for curves.
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
void BKE_mesh_calc_normals_split(struct Mesh *mesh)
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
const struct Brush * BKE_paint_brush_for_read(const struct Paint *p)
void BKE_report(ReportList *reports, eReportType type, const char *message)
MINLINE float pow2f(float x)
void mul_m4_m4_pre(float R[4][4], const float A[4][4])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float v2[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define BLI_SCOPED_DEFER(function_to_defer)
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
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])
Platform independent time functions.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
constexpr IndexRange index_range() const
void append(const T &value)
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
MutableSpan< float3 > positions_for_write()
MutableSpan< float2 > surface_uv_coords_for_write()
Span< int > offsets() const
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Span< float3 > positions() const
void tag_positions_changed()
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
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig)
AttributeAccessor mesh_attributes(const Mesh &mesh)
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)
VArray< float > get_curves_selection(const Curves &curves_id)
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)
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)
std::unique_ptr< CurvesSculptStrokeOperation > new_slide_operation()
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
float3 compute_surface_point_normal(const MLoopTri &looptri, const float3 &bary_coord, const Span< float3 > corner_normals)
T distance_squared(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
struct ToolSettings * toolsettings
Vector< SlideCurveInfo > curves_to_slide
Span< MLoopTri > surface_looptris_eval_
void execute(SlideOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
Vector< int64_t > selected_curve_indices_
CurvesSurfaceTransforms transforms_
VArraySpan< float2 > surface_uv_map_orig_
VArraySpan< float2 > surface_uv_map_eval_
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_
CurvesSculptCommonContext ctx_
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_
void slide_with_symmetry()
bool find_closest_ray_hit(const float3 &ray_start_su, const float3 &ray_direction_su, const float3 &point_su, int &r_looptri_index, float3 &r_hit_pos)
Span< MLoopTri > surface_looptris_orig_
std::atomic< bool > found_invalid_uv_mapping_
SlideOperationExecutor(const bContext &C)
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_
float4x4 inverted() const
void WM_main_add_notifier(unsigned int type, void *reference)