44 KDTree_3d *original_curve_roots_kdtree_ =
nullptr;
46 KDTree_3d *deformed_curve_roots_kdtree_ =
nullptr;
49 int original_curve_num_ = 0;
56 if (original_curve_roots_kdtree_ !=
nullptr) {
57 BLI_kdtree_3d_free(original_curve_roots_kdtree_);
59 if (deformed_curve_roots_kdtree_ !=
nullptr) {
60 BLI_kdtree_3d_free(deformed_curve_roots_kdtree_);
190 const int already_added_curves =
self_->new_deformed_root_positions_.size();
191 KDTree_3d *new_roots_kdtree = BLI_kdtree_3d_new(already_added_curves +
192 new_positions_cu.
size());
199 512 < already_added_curves + new_positions_cu.
size(),
202 for (const int i : IndexRange(already_added_curves)) {
203 BLI_kdtree_3d_insert(new_roots_kdtree, -1, self_->new_deformed_root_positions_[i]);
205 for (
const int new_i : new_positions_cu.
index_range()) {
206 const float3 &root_pos_cu = new_positions_cu[new_i];
207 BLI_kdtree_3d_insert(new_roots_kdtree, new_i, root_pos_cu);
209 BLI_kdtree_3d_balance(new_roots_kdtree);
215 new_positions_cu.index_range(), 128, [&](
const IndexRange range) {
216 for (const int new_i : range) {
217 const float3 &new_root_pos_cu = new_positions_cu[new_i];
218 KDTreeNearest_3d nearest;
219 nearest.dist = FLT_MAX;
220 BLI_kdtree_3d_find_nearest(
221 self_->deformed_curve_roots_kdtree_, new_root_pos_cu, &nearest);
222 if (nearest.dist < brush_settings_->minimum_distance) {
223 new_curve_skipped[new_i] = true;
230 for (
const int new_i : new_positions_cu.index_range()) {
231 if (new_curve_skipped[new_i]) {
234 const float3 &root_pos_cu = new_positions_cu[new_i];
235 BLI_kdtree_3d_range_search_cb_cpp(
239 [&](
const int other_new_i,
const float *
UNUSED(co),
float UNUSED(dist_sq)) {
240 if (other_new_i == -1) {
241 new_curve_skipped[new_i] =
true;
244 if (new_i == other_new_i) {
247 new_curve_skipped[other_new_i] =
true;
253 for (
int64_t i = new_positions_cu.size() - 1; i >= 0; i--) {
254 if (new_curve_skipped[i]) {
255 new_positions_cu.remove_and_reorder(i);
256 new_uvs.remove_and_reorder(i);
259 self_->new_deformed_root_positions_.extend(new_positions_cu);
265 const Span<float3> corner_normals_su = {
271 const geometry::ReverseUVSampler reverse_uv_sampler{surface_uv_map, surface_looptris_orig};
273 geometry::AddCurvesOnMeshInputs add_inputs;
274 add_inputs.uvs = new_uvs;
275 add_inputs.interpolate_length = brush_settings_->
flag &
277 add_inputs.interpolate_shape = brush_settings_->
flag &
279 add_inputs.interpolate_point_count = brush_settings_->
flag &
281 add_inputs.fallback_curve_length = brush_settings_->
curve_length;
283 add_inputs.transforms = &transforms_;
284 add_inputs.surface = surface_orig_;
285 add_inputs.corner_normals_su = corner_normals_su;
286 add_inputs.reverse_uv_sampler = &reverse_uv_sampler;
287 add_inputs.old_roots_kdtree = self_->original_curve_roots_kdtree_;
290 *curves_orig_, add_inputs);
292 if (add_outputs.uv_error) {
311 KDTree_3d *kdtree = BLI_kdtree_3d_new(curves_orig_->
curves_num());
312 for (
const int curve_i : curves_orig_->
curves_range()) {
313 const int root_point_i = curve_offsets[curve_i];
314 BLI_kdtree_3d_insert(kdtree, curve_i,
positions[root_point_i]);
316 BLI_kdtree_3d_balance(kdtree);
321 1024 < original_positions.
size() + deformed_positions.
size(),
323 self_->original_curve_roots_kdtree_ = roots_kdtree_from_positions(original_positions);
326 self_->deformed_curve_roots_kdtree_ = roots_kdtree_from_positions(deformed_positions);
339 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
367 for (
int i = new_points - 1; i >= 0; i--) {
368 const float3 pos_su = positions_su[i];
372 const float dist_to_brush_re =
math::distance(brush_pos_re_, pos_re);
374 brush_, dist_to_brush_re, brush_radius_re_);
375 const float weight = brush_strength_ * radius_falloff;
385 bary_coords[i], surface_looptris_eval_[looptri_indices[i]], surface_uv_map_eval_);
388 r_positions_su.
extend(positions_su);
403 if (!brush_3d.has_value()) {
409 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
410 const float3 brush_pos_cu = brush_transform * brush_3d->position_cu;
414 const float brush_radius_sq_su =
pow2f(brush_radius_su);
417 BLI_bvhtree_range_query_cpp(
418 *surface_bvh_eval_.
tree,
422 selected_looptri_indices.
append(index);
425 const float brush_plane_area_su =
M_PI * brush_radius_sq_su;
435 selected_looptri_indices,
438 approximate_density_su,
444 for (
int i = new_points - 1; i >= 0; i--) {
445 const float3 pos_su = positions_su[i];
447 const float dist_to_brush_cu =
math::distance(pos_cu, brush_pos_cu);
449 brush_, dist_to_brush_cu, brush_3d->radius_cu);
450 const float weight = brush_strength_ * radius_falloff;
460 bary_coords[i], surface_looptris_eval_[looptri_indices[i]], surface_uv_map_eval_);
463 r_positions_su.
extend(positions_su);
468 void DensityAddOperation::on_stroke_extended(
const bContext &
C,
472 executor.execute(*
this,
C, stroke_extension);
537 curves_id_ =
static_cast<Curves *
>(object_->
data);
543 surface_ob_orig_ = curves_id_->
surface;
544 if (surface_ob_orig_ ==
nullptr) {
547 surface_orig_ =
static_cast<Mesh *
>(surface_ob_orig_->
data);
550 if (surface_ob_eval_ ==
nullptr) {
577 const int first_point_i = curves_->
offsets()[curve_i];
578 self_->deformed_root_positions_.append(deformation.
positions[first_point_i]);
582 root_points_kdtree_ = BLI_kdtree_3d_new(curve_selection_.
size());
584 for (
const int curve_i : curve_selection_) {
585 const float3 &pos_cu = self_->deformed_root_positions_[curve_i];
586 BLI_kdtree_3d_insert(root_points_kdtree_, curve_i, pos_cu);
588 BLI_kdtree_3d_balance(root_points_kdtree_);
593 this->reduce_density_projected_with_symmetry(curves_to_delete);
596 this->reduce_density_spherical_with_symmetry(curves_to_delete);
605 return curves_to_delete[curve_i];
613 for (
const IndexRange range : ranges_to_keep) {
614 new_deformed_positions.
extend(self_->deformed_root_positions_.as_span().slice(range));
616 self_->deformed_root_positions_ = std::move(new_deformed_positions);
630 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
631 this->reduce_density_projected(brush_transform, curves_to_delete);
638 const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
639 const float brush_radius_sq_re =
pow2f(brush_radius_re);
648 RandomNumberGenerator rng((int)(PIL_check_seconds_timer() * 1000000.0));
650 for (const int curve_i : range) {
651 if (curves_to_delete[curve_i]) {
652 allow_remove_curve[curve_i] = true;
655 const float3 pos_cu = brush_transform * self_->deformed_root_positions_[curve_i];
658 ED_view3d_project_float_v2_m4(ctx_.region, pos_cu, pos_re, projection.values);
659 const float dist_to_brush_sq_re = math::distance_squared(brush_pos_re_, pos_re);
660 if (dist_to_brush_sq_re > brush_radius_sq_re) {
663 const float dist_to_brush_re = std::sqrt(dist_to_brush_sq_re);
664 const float radius_falloff = BKE_brush_curve_strength(
665 brush_, dist_to_brush_re, brush_radius_re);
666 const float weight = brush_strength_ * radius_falloff;
667 if (rng.get_float() < weight) {
668 allow_remove_curve[curve_i] = true;
674 for (
const int curve_i : curve_selection_) {
675 if (curves_to_delete[curve_i]) {
678 if (!allow_remove_curve[curve_i]) {
681 const float3 orig_pos_cu = self_->deformed_root_positions_[curve_i];
682 const float3 pos_cu = brush_transform * orig_pos_cu;
686 if (dist_to_brush_sq_re > brush_radius_sq_re) {
689 BLI_kdtree_3d_range_search_cb_cpp(
693 [&](
const int other_curve_i,
const float *
UNUSED(co),
float UNUSED(dist_sq)) {
694 if (other_curve_i == curve_i) {
697 if (allow_remove_curve[other_curve_i]) {
698 curves_to_delete[other_curve_i] =
true;
707 const float brush_radius_re = brush_radius_base_re_ * brush_radius_factor_;
715 if (!brush_3d.has_value()) {
721 for (
const float4x4 &brush_transform : symmetry_brush_transforms) {
722 const float3 brush_pos_cu = brush_transform * brush_3d->position_cu;
723 this->reduce_density_spherical(brush_pos_cu, brush_3d->radius_cu, curves_to_delete);
728 const float brush_radius_cu,
731 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
737 RandomNumberGenerator rng((int)(PIL_check_seconds_timer() * 1000000.0));
739 for (const int curve_i : range) {
740 if (curves_to_delete[curve_i]) {
741 allow_remove_curve[curve_i] = true;
744 const float3 pos_cu = self_->deformed_root_positions_[curve_i];
746 const float dist_to_brush_sq_cu = math::distance_squared(brush_pos_cu, pos_cu);
747 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
750 const float dist_to_brush_cu = std::sqrt(dist_to_brush_sq_cu);
751 const float radius_falloff = BKE_brush_curve_strength(
752 brush_, dist_to_brush_cu, brush_radius_cu);
753 const float weight = brush_strength_ * radius_falloff;
754 if (rng.get_float() < weight) {
755 allow_remove_curve[curve_i] = true;
761 for (
const int curve_i : curve_selection_) {
762 if (curves_to_delete[curve_i]) {
765 if (!allow_remove_curve[curve_i]) {
768 const float3 &pos_cu = self_->deformed_root_positions_[curve_i];
770 if (dist_to_brush_sq_cu > brush_radius_sq_cu) {
774 BLI_kdtree_3d_range_search_cb_cpp(
778 [&](
const int other_curve_i,
const float *
UNUSED(co),
float UNUSED(dist_sq)) {
779 if (other_curve_i == curve_i) {
782 if (allow_remove_curve[other_curve_i]) {
783 curves_to_delete[other_curve_i] =
true;
791 void DensitySubtractOperation::on_stroke_extended(
const bContext &
C,
795 executor.execute(*
this,
C, stroke_extension);
825 if (surface_ob_orig ==
nullptr) {
829 if (surface_ob_eval ==
nullptr) {
833 if (
curves.curves_num() <= 1) {
837 if (surface_mesh_eval ==
nullptr) {
852 depsgraph, region, v3d, transforms, surface_bvh_eval, brush_pos_re, brush_radius_re);
853 if (!brush_3d.has_value()) {
857 const float3 brush_pos_cu = brush_3d->position_cu;
858 const float brush_radius_cu = brush_3d->radius_cu;
859 const float brush_radius_sq_cu =
pow2f(brush_radius_cu);
869 int &valid_curve_count = valid_curve_count_by_thread.local();
870 for (const int curve_i : range) {
871 const int root_point_i = offsets[curve_i];
872 const float3 &root_pos_cu = deformation.positions[root_point_i];
873 const float dist_sq_cu = math::distance_squared(root_pos_cu, brush_pos_cu);
874 if (dist_sq_cu < brush_radius_sq_cu) {
875 distances_sq_to_brush[curve_i] = {math::distance_squared(root_pos_cu, brush_pos_cu),
880 distances_sq_to_brush[curve_i] = {FLT_MAX, -1};
884 const int valid_curve_count = std::accumulate(
885 valid_curve_count_by_thread.begin(), valid_curve_count_by_thread.end(), 0);
888 const int check_curve_count = std::min<int>(8, valid_curve_count);
889 std::partial_sort(distances_sq_to_brush.begin(),
890 distances_sq_to_brush.begin() + check_curve_count,
891 distances_sq_to_brush.end());
895 float min_dist_sq_cu = FLT_MAX;
896 for (
const int i :
IndexRange(check_curve_count)) {
897 const float3 &pos_i = deformation.positions[offsets[distances_sq_to_brush[i].second]];
898 for (
int j = i + 1; j < check_curve_count; j++) {
899 const float3 &pos_j = deformation.positions[offsets[distances_sq_to_brush[j].second]];
905 const float min_dist_cu =
std::sqrt(min_dist_sq_cu);
906 if (min_dist_cu > brush.curves_sculpt_settings->minimum_distance) {
917 return std::make_unique<DensityAddOperation>();
919 return std::make_unique<DensitySubtractOperation>();
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 Scene * CTX_data_scene(const bContext *C)
struct Depsgraph * CTX_data_depsgraph_on_load(const bContext *C)
struct Object * CTX_data_active_object(const bContext *C)
struct View3D * CTX_wm_view3d(const bContext *C)
struct ARegion * CTX_wm_region(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)
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)
#define BLI_assert_unreachable()
A KD-tree for nearest neighbor search.
MINLINE float pow2f(float x)
#define BLI_SCOPED_DEFER(function_to_defer)
struct Depsgraph Depsgraph
void DEG_id_tag_update(struct ID *id, int flag)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
@ BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_POINT_COUNT
@ BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_LENGTH
@ BRUSH_CURVES_SCULPT_FLAG_INTERPOLATE_SHAPE
eBrushCurvesSculptDensityMode
@ BRUSH_CURVES_SCULPT_DENSITY_MODE_REMOVE
@ BRUSH_CURVES_SCULPT_DENSITY_MODE_ADD
void ED_region_tag_redraw(struct ARegion *region)
bool ED_view3d_win_to_segment_clipped(const struct Depsgraph *depsgraph, const struct ARegion *region, const struct View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], bool do_clip_planes)
void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, const struct Object *ob, float r_pmat[4][4])
void ED_view3d_project_float_v2_m4(const struct ARegion *region, const float co[3], float r_co[2], const float mat[4][4])
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
Platform independent time functions.
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
Vector< IndexRange > extract_ranges_invert(const IndexRange full_range, Vector< int64_t > *r_skip_amounts=nullptr) const
constexpr int64_t size() const
constexpr bool is_empty() const
void remove_and_reorder(const int64_t index)
void append(const T &value)
IndexRange index_range() const
void extend(Span< T > array)
GAttributeReader lookup(const AttributeIDRef &attribute_id) const
IndexRange curves_range() const
Span< int > offsets() const
void remove_curves(IndexMask curves_to_delete)
static CurvesGeometry & wrap(::CurvesGeometry &dna_struct)
Span< float3 > positions() const
const Depsgraph * depsgraph
~DensityAddOperation() override
void on_stroke_extended(const bContext &C, const StrokeExtension &stroke_extension) override
const Depsgraph * depsgraph
ccl_gpu_kernel_postfix int ccl_global int * indices
GeometryDeformation get_evaluated_curves_deformation(const Depsgraph &depsgraph, const Object &ob_orig)
static struct PartialUpdateUser * wrap(PartialUpdateUserImpl *user)
T sample_corner_attrribute_with_bary_coords(const float3 &bary_weights, const MLoopTri &looptri, const Span< T > corner_attribute)
int sample_surface_points_spherical(RandomNumberGenerator &rng, const Mesh &mesh, Span< int > looptri_indices_to_sample, const float3 &sample_pos, float sample_radius, float approximate_density, Vector< float3 > &r_bary_coords, Vector< int > &r_looptri_indices, Vector< float3 > &r_positions)
int sample_surface_points_projected(RandomNumberGenerator &rng, const Mesh &mesh, BVHTreeFromMesh &mesh_bvhtree, const float2 &sample_pos_re, float sample_radius_re, FunctionRef< void(const float2 &pos_re, float3 &r_start, float3 &r_end)> region_position_to_ray, bool front_face_only, int tries_num, int max_points, Vector< float3 > &r_bary_coords, Vector< int > &r_looptri_indices, Vector< float3 > &r_positions)
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_invalid_uv_map(ReportList *reports)
void report_empty_evaluated_surface(ReportList *reports)
float brush_radius_get(const Scene &scene, const Brush &brush, const StrokeExtension &stroke_extension)
void report_missing_uv_map_on_original_surface(ReportList *reports)
static bool use_add_density_mode(const BrushStrokeMode brush_mode, const bContext &C, const StrokeExtension &stroke_start)
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)
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
std::unique_ptr< CurvesSculptStrokeOperation > new_density_operation(const BrushStrokeMode brush_mode, const bContext &C, const StrokeExtension &stroke_start)
float transform_brush_radius(const float4x4 &transform, const float3 &brush_position, const float old_radius)
AddCurvesOnMeshOutputs add_curves_on_mesh(bke::CurvesGeometry &curves, const AddCurvesOnMeshInputs &inputs)
IndexMask find_indices_based_on_predicate(const IndexMask indices_to_check, const int64_t parallel_grain_size, Vector< int64_t > &r_indices, const Predicate &predicate)
T distance_squared(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T distance(const T &a, const T &b)
void min_inplace(T &a, const T &b)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
void parallel_invoke(Functions &&...functions)
MutableSpan< float3 > positions
struct BrushCurvesSculptSettings * curves_sculpt_settings
struct ToolSettings * toolsettings
const CurvesSculpt * curves_sculpt_
BVHTreeFromMesh surface_bvh_eval_
Object * surface_ob_orig_
VArraySpan< float2 > surface_uv_map_eval_
Object * surface_ob_eval_
void sample_projected_with_symmetry(RandomNumberGenerator &rng, Vector< float2 > &r_uvs, Vector< float3 > &r_positions_su)
Span< MLoopTri > surface_looptris_eval_
DensityAddOperation * self_
CurvesSurfaceTransforms transforms_
void sample_spherical_with_symmetry(RandomNumberGenerator &rng, Vector< float2 > &r_uvs, Vector< float3 > &r_positions_su)
CurvesSculptCommonContext ctx_
const BrushCurvesSculptSettings * brush_settings_
DensityAddOperationExecutor(const bContext &C)
CurvesGeometry * curves_orig_
void execute(DensityAddOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
void prepare_curve_roots_kdtrees()
void execute(DensitySubtractOperation &self, const bContext &C, const StrokeExtension &stroke_extension)
float brush_radius_factor_
void reduce_density_spherical(const float3 &brush_pos_cu, const float brush_radius_cu, MutableSpan< bool > curves_to_delete)
float brush_radius_base_re_
Vector< int64_t > selected_curve_indices_
CurvesSculptCommonContext ctx_
void reduce_density_projected_with_symmetry(MutableSpan< bool > curves_to_delete)
IndexMask curve_selection_
void reduce_density_spherical_with_symmetry(MutableSpan< bool > curves_to_delete)
CurvesSurfaceTransforms transforms_
DensitySubtractOperationExecutor(const bContext &C)
KDTree_3d * root_points_kdtree_
BVHTreeFromMesh surface_bvh_eval_
void reduce_density_projected(const float4x4 &brush_transform, MutableSpan< bool > curves_to_delete)
float4x4 inverted() const
double PIL_check_seconds_timer(void)
void WM_main_add_notifier(unsigned int type, void *reference)