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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user