diff --git a/scripts/startup/bl_ui/space_view3d.py b/scripts/startup/bl_ui/space_view3d.py index c18dd8c9cc5..e258891fdd5 100644 --- a/scripts/startup/bl_ui/space_view3d.py +++ b/scripts/startup/bl_ui/space_view3d.py @@ -170,7 +170,11 @@ class VIEW3D_HT_tool_header(Header): sub.prop(ob.data, "use_mirror_y", text="Y", toggle=True) sub.prop(ob.data, "use_mirror_z", text="Z", toggle=True) - layout.prop(ob.data, "use_sculpt_collision", icon='MOD_PHYSICS', icon_only=True, toggle=True) + row = layout.row(align=True) + row.prop(ob.data, "use_sculpt_collision", icon='MOD_PHYSICS', icon_only=True, toggle=True) + sub = row.row(align=True) + sub.active = ob.data.use_sculpt_collision + sub.prop(ob.data, "surface_collision_distance") # Expand panels from the side-bar as popovers. popover_kw = {"space_type": 'VIEW_3D', "region_type": 'UI', "category": "Tool"} diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 77f876a98c2..1cc3f9aabfa 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -31,7 +31,7 @@ extern "C" { /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 22 +#define BLENDER_FILE_SUBVERSION 23 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc index 02e07380474..d9181ba23b7 100644 --- a/source/blender/blenkernel/intern/curves.cc +++ b/source/blender/blenkernel/intern/curves.cc @@ -315,6 +315,7 @@ void curves_copy_parameters(const Curves &src, Curves &dst) if (src.surface_uv_map != nullptr) { dst.surface_uv_map = BLI_strdup(src.surface_uv_map); } + dst.surface_collision_distance = src.surface_collision_distance; } CurvesSurfaceTransforms::CurvesSurfaceTransforms(const Object &curves_ob, const Object *surface_ob) diff --git a/source/blender/blenloader/intern/versioning_400.cc b/source/blender/blenloader/intern/versioning_400.cc index 68bfc3b83fa..7877af59bb8 100644 --- a/source/blender/blenloader/intern/versioning_400.cc +++ b/source/blender/blenloader/intern/versioning_400.cc @@ -5638,6 +5638,14 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 404, 23)) { + if (!DNA_struct_member_exists(fd->filesdna, "Curves", "float", "surface_collision_distance")) { + LISTBASE_FOREACH (Curves *, curves, &bmain->hair_curves) { + curves->surface_collision_distance = 0.005f; + } + } + } + /* Always run this versioning; meshes are written with the legacy format which always needs to * be converted to the new format on file load. Can be moved to a subversion check in a larger * breaking release. */ diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc index c5eb270fd73..e8b2d0fd52c 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc @@ -439,9 +439,11 @@ void report_invalid_uv_map(ReportList *reports) void CurvesConstraintSolver::initialize(const bke::CurvesGeometry &curves, const IndexMask &curve_selection, - const bool use_surface_collision) + const bool use_surface_collision, + const float surface_collision_distance) { use_surface_collision_ = use_surface_collision; + surface_collision_distance_ = surface_collision_distance; segment_lengths_.reinitialize(curves.points_num()); geometry::curve_constraints::compute_segment_lengths( curves.points_by_curve(), curves.positions(), curve_selection, segment_lengths_); @@ -463,7 +465,8 @@ void CurvesConstraintSolver::solve_step(bke::CurvesGeometry &curves, start_positions_, *surface, transforms, - curves.positions_for_write()); + curves.positions_for_write(), + surface_collision_distance_); start_positions_ = curves.positions(); } else { diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc index 2b7956bf7c3..100533fc10a 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_comb.cc @@ -140,8 +140,10 @@ struct CombOperationExecutor { if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE || (U.uiflag & USER_ORBIT_SELECTION)) { this->initialize_spherical_brush_reference_point(); } - self_->constraint_solver_.initialize( - *curves_orig_, curve_selection_, curves_id_orig_->flag & CV_SCULPT_COLLISION_ENABLED); + self_->constraint_solver_.initialize(*curves_orig_, + curve_selection_, + curves_id_orig_->flag & CV_SCULPT_COLLISION_ENABLED, + curves_id_orig_->surface_collision_distance); self_->curve_lengths_.reinitialize(curves_orig_->curves_num()); const Span segment_lengths = self_->constraint_solver_.segment_lengths(); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh index ca97d655a78..7077949d4cd 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/curves_sculpt_intern.hh @@ -162,13 +162,15 @@ void report_invalid_uv_map(ReportList *reports); struct CurvesConstraintSolver { private: bool use_surface_collision_; + float surface_collision_distance_; Array start_positions_; Array segment_lengths_; public: void initialize(const bke::CurvesGeometry &curves, const IndexMask &curve_selection, - const bool use_surface_collision); + const bool use_surface_collision, + const float surface_collision_distance); void solve_step(bke::CurvesGeometry &curves, const IndexMask &curve_selection, diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc b/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc index 29cafacdf58..b7339253566 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_pinch.cc @@ -125,8 +125,10 @@ struct PinchOperationExecutor { math::transform_point(transforms_.curves_to_world, self_->brush_3d_.position_cu)); } - self_->constraint_solver_.initialize( - *curves_, curve_selection_, curves_id_->flag & CV_SCULPT_COLLISION_ENABLED); + self_->constraint_solver_.initialize(*curves_, + curve_selection_, + curves_id_->flag & CV_SCULPT_COLLISION_ENABLED, + curves_id_->surface_collision_distance); } Array changed_curves(curves_->curves_num(), false); diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc index 0141811ea35..64d85c51a35 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_puff.cc @@ -134,8 +134,10 @@ struct PuffOperationExecutor { math::transform_point(transforms_.curves_to_world, self_->brush_3d_.position_cu)); } - self_->constraint_solver_.initialize( - *curves_, curve_selection_, curves_id_->flag & CV_SCULPT_COLLISION_ENABLED); + self_->constraint_solver_.initialize(*curves_, + curve_selection_, + curves_id_->flag & CV_SCULPT_COLLISION_ENABLED, + curves_id_->surface_collision_distance); } Array curve_weights(curves_->curves_num(), 0.0f); diff --git a/source/blender/geometry/GEO_curve_constraints.hh b/source/blender/geometry/GEO_curve_constraints.hh index 0b70fc1a772..183611f6dd2 100644 --- a/source/blender/geometry/GEO_curve_constraints.hh +++ b/source/blender/geometry/GEO_curve_constraints.hh @@ -24,6 +24,7 @@ void solve_length_and_collision_constraints(OffsetIndices points_by_curve, Span start_positions, const Mesh &surface, const bke::CurvesSurfaceTransforms &transforms, - MutableSpan positions); + MutableSpan positions, + const float surface_collision_distance); } // namespace blender::geometry::curve_constraints diff --git a/source/blender/geometry/intern/curve_constraints.cc b/source/blender/geometry/intern/curve_constraints.cc index 5fbed9fe27d..a6d2c9c8183 100644 --- a/source/blender/geometry/intern/curve_constraints.cc +++ b/source/blender/geometry/intern/curve_constraints.cc @@ -67,13 +67,13 @@ void solve_length_and_collision_constraints(const OffsetIndices points_by_c const Span start_positions_cu, const Mesh &surface, const bke::CurvesSurfaceTransforms &transforms, - MutableSpan positions_cu) + MutableSpan positions_cu, + const float surface_collision_distance) { solve_length_constraints(points_by_curve, curve_selection, segment_lengths_cu, positions_cu); blender::bke::BVHTreeFromMesh surface_bvh = surface.bvh_corner_tris(); - const float radius = 0.005f; const int max_collisions = 5; curve_selection.foreach_segment(GrainSize(64), [&](const IndexMaskSegment segment) { @@ -108,11 +108,11 @@ void solve_length_and_collision_constraints(const OffsetIndices points_by_c max_ray_length_su); BVHTreeRayHit hit; hit.index = -1; - hit.dist = max_ray_length_su + radius; + hit.dist = max_ray_length_su + surface_collision_distance; BLI_bvhtree_ray_cast(surface_bvh.tree, start_pos_su, ray_direction_su, - radius, + surface_collision_distance, &hit, surface_bvh.raycast_callback, &surface_bvh); @@ -135,7 +135,7 @@ void solve_length_and_collision_constraints(const OffsetIndices points_by_c math::transform_direction(transforms.surface_to_curves_normal, hit_normal_su)); /* Slide on a plane that is slightly above the surface. */ - const float3 plane_pos_cu = hit_pos_cu + hit_normal_cu * radius; + const float3 plane_pos_cu = hit_pos_cu + hit_normal_cu * surface_collision_distance; const float3 plane_normal_cu = hit_normal_cu; /* Decompose the current segment into the part normal and tangent to the collision diff --git a/source/blender/makesdna/DNA_curves_defaults.h b/source/blender/makesdna/DNA_curves_defaults.h index b90a4855e4c..ad4a061d3d3 100644 --- a/source/blender/makesdna/DNA_curves_defaults.h +++ b/source/blender/makesdna/DNA_curves_defaults.h @@ -17,6 +17,7 @@ #define _DNA_DEFAULT_Curves \ { \ .flag = 0, \ + .surface_collision_distance = 0.005f, \ } /** \} */ diff --git a/source/blender/makesdna/DNA_curves_types.h b/source/blender/makesdna/DNA_curves_types.h index 953c3249037..12ed9cc4188 100644 --- a/source/blender/makesdna/DNA_curves_types.h +++ b/source/blender/makesdna/DNA_curves_types.h @@ -204,6 +204,10 @@ typedef struct Curves { */ char *surface_uv_map; + /* Distance to keep the curves away from the surface. */ + float surface_collision_distance; + char _pad2[4]; + /* Draw cache to store data used for viewport drawing. */ void *batch_cache; } Curves; diff --git a/source/blender/makesrna/intern/rna_curves.cc b/source/blender/makesrna/intern/rna_curves.cc index 9aee68abaf3..d52f3f51c07 100644 --- a/source/blender/makesrna/intern/rna_curves.cc +++ b/source/blender/makesrna/intern/rna_curves.cc @@ -552,6 +552,14 @@ static void rna_def_curves(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, 0, "rna_Curves_update_draw"); + prop = RNA_def_property(srna, "surface_collision_distance", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, nullptr, "surface_collision_distance"); + RNA_def_property_range(prop, FLT_EPSILON, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, 10.0f, 0.001, 3); + RNA_def_property_ui_text( + prop, "Collision distance", "Distance to keep the curves away from the surface"); + RNA_def_property_update(prop, 0, "rna_Curves_update_draw"); + /* attributes */ rna_def_attributes_common(srna, AttributeOwnerType::Curves);