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
This commit is contained in:
Sean Kim
2024-10-10 22:49:12 +02:00
committed by Sean Kim
parent 57c4e9dd2c
commit 5c855bd6bf

View File

@@ -40,6 +40,41 @@ struct LocalData {
Vector<float3> 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<float3> vert_positions,
const Span<int> verts,
const float4x4 &mat,
const MutableSpan<float> 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<float3> positions,
const float4x4 &mat,
const MutableSpan<float> 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<float> 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<float> 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<float> 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;