diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 6230f7dd305..76f8ec108da 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -1882,45 +1882,32 @@ struct AreaNormalCenterData { std::array count_no; }; -static void calc_area_normal_and_center_task(const Object &ob, - const Brush &brush, - const bool use_area_nos, - const bool use_area_cos, - const bool has_bm_orco, - PBVHNode *node, - AreaNormalCenterData *anctd, - bool &r_any_vertex_sampled) +static SculptBrushTestFn area_normal_and_center_get_normal_test(const SculptSession &ss, + const Brush &brush, + SculptBrushTest &r_test) { - const SculptSession &ss = *ob.sculpt; - - undo::Node *unode = nullptr; - - bool use_original = false; - if (ss.cache && !ss.cache->accum) { - unode = undo::get_node(node, undo::Type::Position); - if (unode) { - use_original = (!unode->position.is_empty() || unode->bm_entry); - } - } - - SculptBrushTest normal_test; SculptBrushTestFn sculpt_brush_normal_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, normal_test, brush.falloff_shape); + ss, r_test, brush.falloff_shape); /* Update the test radius to sample the normal using the normal radius of the brush. */ if (brush.ob_mode == OB_MODE_SCULPT) { - float test_radius = std::sqrt(normal_test.radius_squared); + float test_radius = std::sqrt(r_test.radius_squared); test_radius *= brush.normal_radius_factor; - normal_test.radius = test_radius; - normal_test.radius_squared = test_radius * test_radius; + r_test.radius = test_radius; + r_test.radius_squared = test_radius * test_radius; } + return sculpt_brush_normal_test_sq_fn; +} - SculptBrushTest area_test; +static SculptBrushTestFn area_normal_and_center_get_area_test(const SculptSession &ss, + const Brush &brush, + SculptBrushTest &r_test) +{ SculptBrushTestFn sculpt_brush_area_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, area_test, brush.falloff_shape); + ss, r_test, brush.falloff_shape); if (brush.ob_mode == OB_MODE_SCULPT) { - float test_radius = std::sqrt(area_test.radius_squared); + float test_radius = std::sqrt(r_test.radius_squared); /* Layer brush produces artifacts with normal and area radius */ /* Enable area radius control only on Scrape for now */ if (ELEM(brush.sculpt_tool, SCULPT_TOOL_SCRAPE, SCULPT_TOOL_FILL) && @@ -1934,9 +1921,60 @@ static void calc_area_normal_and_center_task(const Object &ob, else { test_radius *= brush.normal_radius_factor; } - area_test.radius = test_radius; - area_test.radius_squared = test_radius * test_radius; + r_test.radius = test_radius; + r_test.radius_squared = test_radius * test_radius; } + return sculpt_brush_area_test_sq_fn; +} + +/* Weight the normals towards the center. */ +static float area_normal_calc_weight(const float distance, const float radius) +{ + float p = 1.0f - (std::sqrt(distance) / radius); + return std::clamp(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); +} + +/* Weight the coordinates towards the center. */ +static float3 area_center_calc_weighted(const float3 &test_location, + const float distance, + const float radius, + const float3 &co) +{ + /* Weight the coordinates towards the center. */ + float p = 1.0f - (std::sqrt(distance) / radius); + const float afactor = std::clamp(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); + + const float3 disp = (co - test_location) * (1.0f - afactor); + return test_location + disp; +} + +static void calc_area_normal_and_center_task(const Object &ob, + const Brush &brush, + const bool use_area_nos, + const bool use_area_cos, + const bool has_bm_orco, + PBVHNode *node, + AreaNormalCenterData *anctd, + bool &r_any_vertex_sampled) +{ + const SculptSession &ss = *ob.sculpt; + + undo::Node *unode = nullptr; + bool use_original = false; + if (ss.cache && !ss.cache->accum) { + unode = undo::get_node(node, undo::Type::Position); + if (unode) { + use_original = (!unode->position.is_empty() || unode->bm_entry); + } + } + + SculptBrushTest normal_test; + SculptBrushTestFn sculpt_brush_normal_test_sq_fn = area_normal_and_center_get_normal_test( + ss, brush, normal_test); + + SculptBrushTest area_test; + SculptBrushTestFn sculpt_brush_area_test_sq_fn = area_normal_and_center_get_area_test( + ss, brush, area_test); /* When the mesh is edited we can't rely on original coords * (original mesh may not even have verts in brush radius). */ @@ -1968,20 +2006,14 @@ static void calc_area_normal_and_center_task(const Object &ob, const int flip_index = (math::dot(ss.cache->view_normal, no) <= 0.0f); if (use_area_cos && area_test_r) { - /* Weight the coordinates towards the center. */ - float p = 1.0f - (std::sqrt(area_test.dist) / area_test.radius); - const float afactor = std::clamp(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - - const float3 disp = (co - area_test.location) * (1.0f - afactor); - anctd->area_cos[flip_index] += area_test.location + disp; + anctd->area_cos[flip_index] += area_center_calc_weighted( + area_test.location, area_test.dist, area_test.radius, co); anctd->count_co[flip_index] += 1; } if (use_area_nos && normal_test_r) { - /* Weight the normals towards the center. */ - float p = 1.0f - (std::sqrt(normal_test.dist) / normal_test.radius); - const float nfactor = std::clamp(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - anctd->area_nos[flip_index] += no * nfactor; + anctd->area_nos[flip_index] += no * area_normal_calc_weight(normal_test.dist, + normal_test.radius); anctd->count_no[flip_index] += 1; } } @@ -2026,20 +2058,13 @@ static void calc_area_normal_and_center_task(const Object &ob, no) <= 0.0f); if (use_area_cos && area_test_r) { - /* Weight the coordinates towards the center. */ - float p = 1.0f - (sqrtf(area_test.dist) / area_test.radius); - const float afactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - - const float3 disp = (co - area_test.location) * (1.0f - afactor); - - anctd->area_cos[flip_index] += area_test.location + disp; + anctd->area_cos[flip_index] += area_center_calc_weighted( + area_test.location, area_test.dist, area_test.radius, co); anctd->count_co[flip_index] += 1; } if (use_area_nos && normal_test_r) { - /* Weight the normals towards the center. */ - float p = 1.0f - (sqrtf(normal_test.dist) / normal_test.radius); - const float nfactor = clamp_f(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f); - anctd->area_nos[flip_index] += no * nfactor; + anctd->area_nos[flip_index] += no * area_normal_calc_weight(normal_test.dist, + normal_test.radius); anctd->count_no[flip_index] += 1; } }