151 this->
puff(curve_weights);
164 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
178 const float brush_radius_sq_re =
pow2f(brush_radius_re);
184 for (const int curve_selection_i : range) {
185 const int curve_i = curve_selection_[curve_selection_i];
186 const IndexRange points = curves_->points_for_curve(curve_i);
187 const float3 first_pos_cu = brush_transform_inv * deformation.positions[points[0]];
189 ED_view3d_project_float_v2_m4(ctx_.region, first_pos_cu, prev_pos_re, projection.values);
190 for (const int point_i : points.drop_front(1)) {
191 const float3 pos_cu = brush_transform_inv * deformation.positions[point_i];
193 ED_view3d_project_float_v2_m4(ctx_.region, pos_cu, pos_re, projection.values);
194 BLI_SCOPED_DEFER([&]() { prev_pos_re = pos_re; });
196 const float dist_to_brush_sq_re = dist_squared_to_line_segment_v2(
197 brush_pos_re_, prev_pos_re, pos_re);
198 if (dist_to_brush_sq_re > brush_radius_sq_re) {
202 const float dist_to_brush_re = std::sqrt(dist_to_brush_sq_re);
203 const float radius_falloff = BKE_brush_curve_strength(
204 brush_, dist_to_brush_re, brush_radius_re);
205 const float weight = radius_falloff;
206 math::max_inplace(r_curve_weights[curve_selection_i], weight);
220 transforms_.curves_to_world * self_->brush_3d_.position_cu,
223 const float3 brush_pos_cu = transforms_.world_to_curves * brush_pos_wo;
224 const float brush_radius_cu = self_->brush_3d_.radius_cu * brush_radius_factor_;
228 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
229 this->find_curves_weights_spherical(
230 brush_transform * brush_pos_cu, brush_radius_cu, r_curve_weights);
235 const float brush_radius_cu,
238 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
244 for (const int curve_selection_i : range) {
245 const int curve_i = curve_selection_[curve_selection_i];
246 const IndexRange points = curves_->points_for_curve(curve_i);
247 for (const int point_i : points.drop_front(1)) {
248 const float3 &prev_pos_cu = deformation.positions[point_i - 1];
249 const float3 &pos_cu = deformation.positions[point_i];
250 const float dist_to_brush_sq_cu = dist_squared_to_line_segment_v3(
251 brush_pos_cu, prev_pos_cu, pos_cu);
252 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
256 const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
257 const float radius_falloff = BKE_brush_curve_strength(
258 brush_, dist_to_brush_cu, brush_radius_cu);
259 const float weight = radius_falloff;
260 math::max_inplace(r_curve_weights[curve_selection_i], weight);
272 Vector<float> accumulated_lengths_cu;
273 for (const int curve_selection_i : range) {
274 const int curve_i = curve_selection_[curve_selection_i];
275 const IndexRange points = curves_->points_for_curve(curve_i);
276 const int first_point_i = points[0];
277 const float3 first_pos_cu = positions_cu[first_point_i];
278 const float3 first_pos_su = transforms_.curves_to_surface * first_pos_cu;
282 BVHTreeNearest nearest;
283 nearest.dist_sq = FLT_MAX;
284 BLI_bvhtree_find_nearest(surface_bvh_.tree,
287 surface_bvh_.nearest_callback,
290 const MLoopTri &looptri = surface_looptris_[nearest.index];
291 const float3 closest_pos_su = nearest.co;
292 const float3 &v0_su = surface_->mvert[surface_->mloop[looptri.tri[0]].v].co;
293 const float3 &v1_su = surface_->mvert[surface_->mloop[looptri.tri[1]].v].co;
294 const float3 &v2_su = surface_->mvert[surface_->mloop[looptri.tri[2]].v].co;
296 interp_weights_tri_v3(bary_coords, v0_su, v1_su, v2_su, closest_pos_su);
297 const float3 normal_su = geometry::compute_surface_point_normal(
298 looptri, bary_coords, corner_normals_su_);
299 const float3 normal_cu = math::normalize(transforms_.surface_to_curves_normal * normal_su);
301 accumulated_lengths_cu.reinitialize(points.size() - 1);
302 length_parameterize::accumulate_lengths<float3>(
303 positions_cu.slice(points), false, accumulated_lengths_cu);
307 for (const int i : IndexRange(points.size()).drop_front(1)) {
308 const int point_i = points[i];
309 const float3 old_pos_cu = positions_cu[point_i];
312 const float length_param_cu = accumulated_lengths_cu[i - 1];
313 const float3 goal_pos_cu = first_pos_cu + length_param_cu * normal_cu;
315 const float weight = 0.01f * brush_strength_ * point_factors_[point_i] *
316 curve_weights[curve_selection_i];
317 float3 new_pos_cu = math::interpolate(old_pos_cu, goal_pos_cu, weight);
321 const float old_dist_to_root_cu = math::distance(old_pos_cu, first_pos_cu);
322 const float new_dist_to_root_cu = math::distance(new_pos_cu, first_pos_cu);
323 if (new_dist_to_root_cu < old_dist_to_root_cu) {
324 const float3 offset = math::normalize(new_pos_cu - first_pos_cu);
325 new_pos_cu += (old_dist_to_root_cu - new_dist_to_root_cu) * offset;
328 positions_cu[point_i] = new_pos_cu;
337 self_->segment_lengths_cu_.reinitialize(curves_->points_num());
339 for (const int curve_i : range) {
340 const IndexRange points = curves_->points_for_curve(curve_i);
341 for (const int point_i : points.drop_back(1)) {
342 const float3 &p1_cu = positions_cu[point_i];
343 const float3 &p2_cu = positions_cu[point_i + 1];
344 const float length_cu = math::distance(p1_cu, p2_cu);
345 self_->segment_lengths_cu_[point_i] = length_cu;
353 const Span<float> expected_lengths_cu = self_->segment_lengths_cu_;
357 for (const int curve_i : range) {
358 const IndexRange points = curves_->points_for_curve(curve_i);
359 for (const int segment_i : points.drop_back(1)) {
360 const float3 &p1_cu = positions_cu[segment_i];
361 float3 &p2_cu = positions_cu[segment_i + 1];
362 const float3 direction = math::normalize(p2_cu - p1_cu);
363 const float expected_length_cu = expected_lengths_cu[segment_i];
364 p2_cu = p1_cu + direction * expected_length_cu;
374 executor.execute(*
this,
C, stroke_extension);
379 return std::make_unique<PuffOperation>();
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)
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)
const struct Brush * BKE_paint_brush_for_read(const struct Paint *p)
#define BLI_assert_unreachable()
MINLINE float pow2f(float x)
#define BLI_SCOPED_DEFER(function_to_defer)
void DEG_id_tag_update(struct ID *id, int flag)
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
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])
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
IndexRange index_range() const
constexpr int64_t size() const
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
void tag_positions_changed()
const Depsgraph * depsgraph
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig)
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)
VArray< float > get_point_selection(const Curves &curves_id)
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_puff_operation()
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
struct ToolSettings * toolsettings
void initialize_segment_lengths()
void execute(PuffOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
PuffOperationExecutor(const bContext &C)
void find_curve_weights_projected_with_symmetry(MutableSpan< float > r_curve_weights)
float brush_radius_factor_
CurvesSculptCommonContext ctx_
void find_curves_weights_spherical_with_symmetry(MutableSpan< float > r_curve_weights)
void restore_segment_lengths()
const CurvesSculpt * curves_sculpt_
Span< float3 > corner_normals_su_
IndexMask curve_selection_
void find_curves_weights_spherical(const float3 &brush_pos_cu, const float brush_radius_cu, MutableSpan< float > r_curve_weights)
VArray< float > point_factors_
Span< MLoopTri > surface_looptris_
CurvesSurfaceTransforms transforms_
eBrushFalloffShape falloff_shape_
float brush_radius_base_re_
void find_curve_weights_projected(const float4x4 &brush_transform, MutableSpan< float > r_curve_weights)
Vector< int64_t > selected_curve_indices_
BVHTreeFromMesh surface_bvh_
void puff(const Span< float > curve_weights)
float4x4 inverted() const
void WM_main_add_notifier(unsigned int type, void *reference)