From 23951e1b124b0e5d6431dfa987e10fbdaec1ce74 Mon Sep 17 00:00:00 2001 From: Sean Kim Date: Fri, 6 Jun 2025 22:48:18 +0200 Subject: [PATCH] Fix #139846: Plane brushes behave incorrectly with constant falloff When constant falloff is used, `BKE_brush_calc_curve_factors` doesn't do any extra filtering of the given distances. The Plane brush previously didn't filter the distances, leading to incorrect deformations when the constant falloff was used. To fix this, this commit makes a number of changes: * `BKE_brush_calc_curve_factors` no longer sets the factor for an element to 0 if it is outside of the provided distance. This is replaced with an assert. * The Plane brush and Cloth brush have an explicit `filter_distances_with_radius` added. Pull Request: https://projects.blender.org/blender/blender/pulls/139851 --- source/blender/blenkernel/BKE_brush.hh | 3 ++ source/blender/blenkernel/intern/brush.cc | 39 ++----------------- .../editors/sculpt_paint/brushes/plane.cc | 3 ++ .../editors/sculpt_paint/sculpt_cloth.cc | 3 ++ 4 files changed, 12 insertions(+), 36 deletions(-) diff --git a/source/blender/blenkernel/BKE_brush.hh b/source/blender/blenkernel/BKE_brush.hh index bf4db19bc98..83cf02324e6 100644 --- a/source/blender/blenkernel/BKE_brush.hh +++ b/source/blender/blenkernel/BKE_brush.hh @@ -105,6 +105,9 @@ void BKE_brush_curve_preset(Brush *b, eCurveMappingPreset preset); /** * Combine the brush strength based on the distances and brush settings with the existing factors. + * + * \note Unlike BKE_brush_curve_strength, if a given distance is greater the brush radius, it does + * not result in a factor of 0 for the corresponding element. */ void BKE_brush_calc_curve_factors(eBrushCurvePreset preset, const CurveMapping *cumap, diff --git a/source/blender/blenkernel/intern/brush.cc b/source/blender/blenkernel/intern/brush.cc index ac5cb6dcd43..4df217c75e2 100644 --- a/source/blender/blenkernel/intern/brush.cc +++ b/source/blender/blenkernel/intern/brush.cc @@ -1385,16 +1385,15 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, const blender::MutableSpan factors) { BLI_assert(factors.size() == distances.size()); + for (const int i : distances.index_range()) { + BLI_assert(distances[i] < brush_radius || factors[i] == 0.0f); + } const float radius_rcp = blender::math::rcp(brush_radius); switch (preset) { case BRUSH_CURVE_CUSTOM: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } factors[i] *= BKE_curvemapping_evaluateF(cumap, 0, distance * radius_rcp); } break; @@ -1402,10 +1401,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_SHARP: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= factor * factor; } @@ -1414,10 +1409,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_SMOOTH: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= 3.0f * factor * factor - 2.0f * factor * factor * factor; } @@ -1426,10 +1417,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_SMOOTHER: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= pow3f(factor) * (factor * (factor * 6.0f - 15.0f) + 10.0f); } @@ -1438,10 +1425,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_ROOT: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= sqrtf(factor); } @@ -1450,10 +1433,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_LIN: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= factor; } @@ -1465,10 +1444,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_SPHERE: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= sqrtf(2 * factor - factor * factor); } @@ -1477,10 +1452,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_POW4: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= factor * factor * factor * factor; } @@ -1489,10 +1460,6 @@ void BKE_brush_calc_curve_factors(const eBrushCurvePreset preset, case BRUSH_CURVE_INVSQUARE: { for (const int i : distances.index_range()) { const float distance = distances[i]; - if (distance >= brush_radius) { - factors[i] = 0.0f; - continue; - } const float factor = 1.0f - distance * radius_rcp; factors[i] *= factor * (2.0f - factor); } diff --git a/source/blender/editors/sculpt_paint/brushes/plane.cc b/source/blender/editors/sculpt_paint/brushes/plane.cc index 808cd99b4b7..0b48420450a 100644 --- a/source/blender/editors/sculpt_paint/brushes/plane.cc +++ b/source/blender/editors/sculpt_paint/brushes/plane.cc @@ -231,6 +231,7 @@ static void calc_faces(const Depsgraph &depsgraph, tls.distances.resize(verts.size()); const MutableSpan distances = tls.distances; calc_local_distances(height, depth, local_positions, distances); + filter_distances_with_radius(1.0f, distances, factors); apply_hardness_to_distances(1.0f, cache.hardness, distances); BKE_brush_calc_curve_factors( @@ -284,6 +285,7 @@ static void calc_grids(const Depsgraph &depsgraph, tls.distances.resize(positions.size()); const MutableSpan distances = tls.distances; calc_local_distances(height, depth, local_positions, distances); + filter_distances_with_radius(1.0f, distances, factors); apply_hardness_to_distances(1.0f, cache.hardness, distances); BKE_brush_calc_curve_factors( @@ -335,6 +337,7 @@ static void calc_bmesh(const Depsgraph &depsgraph, tls.distances.resize(positions.size()); const MutableSpan distances = tls.distances; calc_local_distances(height, depth, local_positions, distances); + filter_distances_with_radius(1.0f, distances, factors); apply_hardness_to_distances(1.0f, cache.hardness, distances); BKE_brush_calc_curve_factors( diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.cc b/source/blender/editors/sculpt_paint/sculpt_cloth.cc index 0e02839bd3d..5dde54acc65 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.cc @@ -808,6 +808,7 @@ static void calc_forces_mesh(const Depsgraph &depsgraph, calc_brush_distances( ss, current_positions, eBrushFalloffShape(brush.falloff_shape), distances); } + filter_distances_with_radius(cache.radius, distances, factors); apply_hardness_to_distances(cache, distances); calc_brush_strength_factors(cache, brush, distances, factors); @@ -918,6 +919,7 @@ static void calc_forces_grids(const Depsgraph &depsgraph, calc_brush_distances( ss, current_positions, eBrushFalloffShape(brush.falloff_shape), distances); } + filter_distances_with_radius(cache.radius, distances, factors); apply_hardness_to_distances(cache, distances); calc_brush_strength_factors(cache, brush, distances, factors); @@ -1026,6 +1028,7 @@ static void calc_forces_bmesh(const Depsgraph &depsgraph, calc_brush_distances( ss, current_positions, eBrushFalloffShape(brush.falloff_shape), distances); } + filter_distances_with_radius(cache.radius, distances, factors); apply_hardness_to_distances(cache, distances); calc_brush_strength_factors(cache, brush, distances, factors);