From 5c855bd6bf97d6da65dfe26bd36c01ed3f31f410 Mon Sep 17 00:00:00 2001 From: Sean Kim Date: Thu, 10 Oct 2024 22:49:12 +0200 Subject: [PATCH] Fix: Sculpt: Reduce clay strips z-axis influence This commit changes the Clay Strips brush in the following ways: * Removes hardcoded displacement and scaling of brush matrix * Applies a falloff to the factor based on the distance to the point in the brush-local z-axis This change has the effect of reducing the brush influence on nearby or other back-facing planes, reducing overall unwanted deformations. Pull Request: https://projects.blender.org/blender/blender/pulls/128775 --- .../sculpt_paint/brushes/clay_strips.cc | 55 +++++++++++++------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/sculpt_paint/brushes/clay_strips.cc b/source/blender/editors/sculpt_paint/brushes/clay_strips.cc index 3291bc52556..ff990ab9196 100644 --- a/source/blender/editors/sculpt_paint/brushes/clay_strips.cc +++ b/source/blender/editors/sculpt_paint/brushes/clay_strips.cc @@ -40,6 +40,41 @@ struct LocalData { Vector translations; }; +/** + * Applies a linear falloff based on the z distance in brush local space to the factor. + * + * Note: We may want to provide users the ability to change this falloff in the future, the + * important detail is that we reduce the influence of the brush on vertices that are potentially + * "deep" inside the cube test area (i.e. on a nearby plane). + * + * TODO: Depending on if other brushes begin to use the calc_brush_cube_distances, we may want + * to consider either inlining this falloff in that method, or making this a commonly accessible + * function. + */ +BLI_NOINLINE static void apply_z_axis_falloff(const Span vert_positions, + const Span verts, + const float4x4 &mat, + const MutableSpan factors) +{ + BLI_assert(factors.size() == verts.size()); + for (const int i : factors.index_range()) { + const float local_z_distance = math::abs( + math::transform_point(mat, vert_positions[verts[i]]).z); + factors[i] *= 1 - local_z_distance; + } +} + +BLI_NOINLINE static void apply_z_axis_falloff(const Span positions, + const float4x4 &mat, + const MutableSpan factors) +{ + BLI_assert(factors.size() == positions.size()); + for (const int i : factors.index_range()) { + const float local_z_distance = math::abs(math::transform_point(mat, positions[i]).z); + factors[i] *= 1 - local_z_distance; + } +} + static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, @@ -70,6 +105,7 @@ static void calc_faces(const Depsgraph &depsgraph, tls.distances.resize(verts.size()); const MutableSpan distances = tls.distances; calc_brush_cube_distances(brush, mat, position_data.eval, verts, distances, factors); + apply_z_axis_falloff(position_data.eval, verts, mat, factors); filter_distances_with_radius(1.0f, distances, factors); apply_hardness_to_distances(1.0f, cache.hardness, distances); BKE_brush_calc_curve_factors( @@ -127,6 +163,7 @@ static void calc_grids(const Depsgraph &depsgraph, tls.distances.resize(positions.size()); const MutableSpan distances = tls.distances; calc_brush_cube_distances(brush, mat, positions, distances, factors); + apply_z_axis_falloff(positions, mat, factors); filter_distances_with_radius(1.0f, distances, factors); apply_hardness_to_distances(1.0f, cache.hardness, distances); BKE_brush_calc_curve_factors( @@ -183,6 +220,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, tls.distances.resize(verts.size()); const MutableSpan distances = tls.distances; calc_brush_cube_distances(brush, mat, positions, distances, factors); + apply_z_axis_falloff(positions, mat, factors); filter_distances_with_radius(1.0f, distances, factors); apply_hardness_to_distances(1.0f, cache.hardness, distances); BKE_brush_calc_curve_factors( @@ -244,21 +282,11 @@ void do_clay_strips_brush(const Depsgraph &depsgraph, area_normal = plane_normal; } - /* Clay Strips uses a cube test with falloff in the XY axis (not in Z) and a plane to deform the - * vertices. When in Add mode, vertices that are below the plane and inside the cube are moved - * towards the plane. In this situation, there may be cases where a vertex is outside the cube - * but below the plane, so won't be deformed, causing artifacts. In order to prevent these - * artifacts, this displaces the test cube space in relation to the plane in order to - * deform more vertices that may be below it. */ - /* The 0.7 and 1.25 factors are arbitrary and don't have any relation between them, they were set - * by doing multiple tests using the default "Clay Strips" brush preset. */ - const float3 area_position_displaced = area_position + area_normal * -radius * 0.7f; - float4x4 mat = float4x4::identity(); mat.x_axis() = math::cross(area_normal, ss.cache->grab_delta_symm); mat.y_axis() = math::cross(area_normal, float3(mat[0])); mat.z_axis() = area_normal; - mat.location() = area_position_displaced; + mat.location() = area_position; mat = math::normalize(mat); /* Scale brush local space matrix. */ @@ -267,11 +295,6 @@ void do_clay_strips_brush(const Depsgraph &depsgraph, tmat.y_axis() *= brush.tip_scale_x; - /* Deform the local space in Z to scale the test cube. As the test cube does not have falloff in - * Z this does not produce artifacts in the falloff cube and allows to deform extra vertices - * during big deformation while keeping the surface as uniform as possible. */ - tmat.z_axis() *= 1.25f; - mat = math::invert(tmat); float4 plane;