diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 2711 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_automasking.c | 24 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_boundary.c | 309 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_cloth.c | 283 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_face_set.c | 164 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c | 170 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_paint_color.c | 218 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_pose.c | 76 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_smooth.c | 162 |
9 files changed, 2132 insertions, 1985 deletions
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 42dece9ddd5..d1028e5f542 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -391,13 +391,14 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl case PBVH_FACES: case PBVH_GRIDS: for (int i = 0; i < ss->totfaces; i++) { - if (abs(ss->face_sets[i]) == face_set) { - if (visible) { - ss->face_sets[i] = abs(ss->face_sets[i]); - } - else { - ss->face_sets[i] = -abs(ss->face_sets[i]); - } + if (abs(ss->face_sets[i]) != face_set) { + continue; + } + if (visible) { + ss->face_sets[i] = abs(ss->face_sets[i]); + } + else { + ss->face_sets[i] = -abs(ss->face_sets[i]); } } break; @@ -1057,12 +1058,13 @@ bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3], char symm) { for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - float location[3]; - flip_v3_v3(location, br_co, (char)i); - if (len_squared_v3v3(location, vertex) < radius * radius) { - return true; - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + float location[3]; + flip_v3_v3(location, br_co, (char)i); + if (len_squared_v3v3(location, vertex) < radius * radius) { + return true; } } return false; @@ -1107,20 +1109,22 @@ void SCULPT_floodfill_add_initial_with_symmetry( /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - int v = -1; - if (i == 0) { - v = index; - } - else if (radius > 0.0f) { - float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; - float location[3]; - flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i); - v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); - } - if (v != -1) { - SCULPT_floodfill_add_initial(flood, v); - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + int v = -1; + if (i == 0) { + v = index; + } + else if (radius > 0.0f) { + float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; + float location[3]; + flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); + } + + if (v != -1) { + SCULPT_floodfill_add_initial(flood, v); } } } @@ -1131,20 +1135,22 @@ void SCULPT_floodfill_add_active( /* Add active vertex and symmetric vertices to the queue. */ const char symm = SCULPT_mesh_symmetry_xyz_get(ob); for (char i = 0; i <= symm; ++i) { - if (SCULPT_is_symmetry_iteration_valid(i, symm)) { - int v = -1; - if (i == 0) { - v = SCULPT_active_vertex_get(ss); - } - else if (radius > 0.0f) { - float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; - float location[3]; - flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i); - v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); - } - if (v != -1) { - SCULPT_floodfill_add_initial(flood, v); - } + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + int v = -1; + if (i == 0) { + v = SCULPT_active_vertex_get(ss); + } + else if (radius > 0.0f) { + float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius; + float location[3]; + flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i); + v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false); + } + + if (v != -1) { + SCULPT_floodfill_add_initial(flood, v); } } } @@ -1161,12 +1167,19 @@ void SCULPT_floodfill_execute( SculptVertexNeighborIter ni; SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const int to_v = ni.index; - if (!BLI_BITMAP_TEST(flood->visited_vertices, to_v) && SCULPT_vertex_visible_get(ss, to_v)) { - BLI_BITMAP_ENABLE(flood->visited_vertices, to_v); - if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { - BLI_gsqueue_push(flood->queue, &to_v); - } + if (BLI_BITMAP_TEST(flood->visited_vertices, to_v)) { + continue; + } + + if (!SCULPT_vertex_visible_get(ss, to_v)) { + continue; + } + + BLI_BITMAP_ENABLE(flood->visited_vertices, to_v); + + if (func(ss, from_v, to_v, ni.is_duplicate, userdata)) { + BLI_gsqueue_push(flood->queue, &to_v); } } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); @@ -1466,40 +1479,42 @@ static void paint_mesh_restore_co_task_cb(void *__restrict userdata, unode = SCULPT_undo_get_node(data->nodes[n]); } - if (unode) { - PBVHVertexIter vd; - SculptOrigVertData orig_data; + if (!unode) { + return; + } - SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); + PBVHVertexIter vd; + SculptOrigVertData orig_data; - BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) - { - SCULPT_orig_vert_data_update(&orig_data, &vd); + SCULPT_orig_vert_data_unode_init(&orig_data, data->ob, unode); - if (orig_data.unode->type == SCULPT_UNDO_COORDS) { - copy_v3_v3(vd.co, orig_data.co); - if (vd.no) { - copy_v3_v3_short(vd.no, orig_data.no); - } - else { - normal_short_to_float_v3(vd.fno, orig_data.no); - } - } - else if (orig_data.unode->type == SCULPT_UNDO_MASK) { - *vd.mask = orig_data.mask; - } - else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { - copy_v4_v4(vd.col, orig_data.col); - } + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) + { + SCULPT_orig_vert_data_update(&orig_data, &vd); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + if (orig_data.unode->type == SCULPT_UNDO_COORDS) { + copy_v3_v3(vd.co, orig_data.co); + if (vd.no) { + copy_v3_v3_short(vd.no, orig_data.no); + } + else { + normal_short_to_float_v3(vd.fno, orig_data.no); } } - BKE_pbvh_vertex_iter_end; + else if (orig_data.unode->type == SCULPT_UNDO_MASK) { + *vd.mask = orig_data.mask; + } + else if (orig_data.unode->type == SCULPT_UNDO_COLOR) { + copy_v4_v4(vd.col, orig_data.col); + } - BKE_pbvh_node_mark_update(data->nodes[n]); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; + } } + BKE_pbvh_vertex_iter_end; + + BKE_pbvh_node_mark_update(data->nodes[n]); } static void paint_mesh_restore_co(Sculpt *sd, Object *ob) @@ -1545,11 +1560,15 @@ static void sculpt_extend_redraw_rect_previous(Object *ob, rcti *rect) * mesh parts could disappear from screen (sergey). */ SculptSession *ss = ob->sculpt; - if (ss->cache) { - if (!BLI_rcti_is_empty(&ss->cache->previous_r)) { - BLI_rcti_union(rect, &ss->cache->previous_r); - } + if (!ss->cache) { + return; + } + + if (BLI_rcti_is_empty(&ss->cache->previous_r)) { + return; } + + BLI_rcti_union(rect, &ss->cache->previous_r); } /* Get a screen-space rectangle of the modified area. */ @@ -1651,28 +1670,30 @@ bool SCULPT_brush_test_sphere(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = sqrtf(distsq); - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + + test->dist = sqrtf(distsq); + return true; } bool SCULPT_brush_test_sphere_sq(SculptBrushTest *test, const float co[3]) { float distsq = len_squared_v3v3(co, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = distsq; - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + test->dist = distsq; + return true; } bool SCULPT_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3]) @@ -1689,14 +1710,16 @@ bool SCULPT_brush_test_circle_sq(SculptBrushTest *test, const float co[3]) closest_to_plane_normalized_v3(co_proj, test->plane_view, co); float distsq = len_squared_v3v3(co_proj, test->location); - if (distsq <= test->radius_squared) { - if (sculpt_brush_test_clipping(test, co)) { - return false; - } - test->dist = distsq; - return true; + if (distsq > test->radius_squared) { + return false; } - return false; + + if (sculpt_brush_test_clipping(test, co)) { + return false; + } + + test->dist = distsq; + return true; } bool SCULPT_brush_test_cube(SculptBrushTest *test, @@ -1724,25 +1747,26 @@ bool SCULPT_brush_test_cube(SculptBrushTest *test, const float constant_side = hardness * side; const float falloff_side = roundness * side; - if (local_co[0] <= side && local_co[1] <= side && local_co[2] <= side) { + if (!(local_co[0] <= side && local_co[1] <= side && local_co[2] <= side)) { + /* Outside the square. */ + return false; + } + if (min_ff(local_co[0], local_co[1]) > constant_side) { /* Corner, distance to the center of the corner circle. */ - if (min_ff(local_co[0], local_co[1]) > constant_side) { - float r_point[3]; - copy_v3_fl(r_point, constant_side); - test->dist = len_v2v2(r_point, local_co) / falloff_side; - return true; - } + float r_point[3]; + copy_v3_fl(r_point, constant_side); + test->dist = len_v2v2(r_point, local_co) / falloff_side; + return true; + } + if (max_ff(local_co[0], local_co[1]) > constant_side) { /* Side, distance to the square XY axis. */ - if (max_ff(local_co[0], local_co[1]) > constant_side) { - test->dist = (max_ff(local_co[0], local_co[1]) - constant_side) / falloff_side; - return true; - } - /* Inside the square, constant distance. */ - test->dist = 0.0f; + test->dist = (max_ff(local_co[0], local_co[1]) - constant_side) / falloff_side; return true; } - /* Outside the square. */ - return false; + + /* Inside the square, constant distance. */ + test->dist = 0.0f; + return true; } SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, @@ -1777,21 +1801,21 @@ static float frontface(const Brush *br, const short no[3], const float fno[3]) { - if (br->flag & BRUSH_FRONTFACE) { - float dot; + if (!(br->flag & BRUSH_FRONTFACE)) { + return 1.0f; + } - if (no) { - float tmp[3]; + float dot; + if (no) { + float tmp[3]; - normal_short_to_float_v3(tmp, no); - dot = dot_v3v3(tmp, sculpt_normal); - } - else { - dot = dot_v3v3(fno, sculpt_normal); - } - return dot > 0.0f ? dot : 0.0f; + normal_short_to_float_v3(tmp, no); + dot = dot_v3v3(tmp, sculpt_normal); + } + else { + dot = dot_v3v3(fno, sculpt_normal); } - return 1.0f; + return dot > 0.0f ? dot : 0.0f; } #if 0 @@ -1871,25 +1895,25 @@ static float calc_radial_symmetry_feather(Sculpt *sd, static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache) { - if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) { - float overlap; - const int symm = cache->symmetry; - - overlap = 0.0f; - for (int i = 0; i <= symm; i++) { - if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { - - overlap += calc_overlap(cache, i, 0, 0); + if (!(sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER)) { + return 1.0f; + } + float overlap; + const int symm = cache->symmetry; - overlap += calc_radial_symmetry_feather(sd, cache, i, 'X'); - overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y'); - overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z'); - } + overlap = 0.0f; + for (int i = 0; i <= symm; i++) { + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; } - return 1.0f / overlap; + overlap += calc_overlap(cache, i, 0, 0); + + overlap += calc_radial_symmetry_feather(sd, cache, i, 'X'); + overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y'); + overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z'); } - return 1.0f; + return 1.0f / overlap; } /* -------------------------------------------------------------------- */ @@ -1991,35 +2015,37 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co); area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co); - if (normal_test_r || area_test_r) { - float no[3]; - int flip_index; + if (!normal_test_r && !area_test_r) { + continue; + } - normal_tri_v3(no, UNPACK3(co_tri)); + float no[3]; + int flip_index; - flip_index = (dot_v3v3(ss->cache->view_normal, 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); + normal_tri_v3(no, UNPACK3(co_tri)); - float disp[3]; - sub_v3_v3v3(disp, co, area_test.location); - mul_v3_fl(disp, 1.0f - afactor); - add_v3_v3v3(co, area_test.location, disp); - add_v3_v3(anctd->area_cos[flip_index], co); + flip_index = (dot_v3v3(ss->cache->view_normal, 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); - 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); - mul_v3_fl(no, nfactor); - - add_v3_v3(anctd->area_nos[flip_index], no); - anctd->count_no[flip_index] += 1; - } + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); + add_v3_v3(anctd->area_cos[flip_index], 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); + mul_v3_fl(no, nfactor); + + add_v3_v3(anctd->area_nos[flip_index], no); + anctd->count_no[flip_index] += 1; } } } @@ -2051,49 +2077,51 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata, normal_test_r = sculpt_brush_normal_test_sq_fn(&normal_test, co); area_test_r = sculpt_brush_area_test_sq_fn(&area_test, co); - if (normal_test_r || area_test_r) { - float no[3]; - int flip_index; + if (!normal_test_r && !area_test_r) { + continue; + } + + float no[3]; + int flip_index; - data->any_vertex_sampled = true; + data->any_vertex_sampled = true; - if (use_original) { - normal_short_to_float_v3(no, no_s); + if (use_original) { + normal_short_to_float_v3(no, no_s); + } + else { + if (vd.no) { + normal_short_to_float_v3(no, vd.no); } else { - if (vd.no) { - normal_short_to_float_v3(no, vd.no); - } - else { - copy_v3_v3(no, vd.fno); - } + copy_v3_v3(no, vd.fno); } + } - flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <= - 0.0f); + flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, 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); + 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); - float disp[3]; - sub_v3_v3v3(disp, co, area_test.location); - mul_v3_fl(disp, 1.0f - afactor); - add_v3_v3v3(co, area_test.location, disp); + float disp[3]; + sub_v3_v3v3(disp, co, area_test.location); + mul_v3_fl(disp, 1.0f - afactor); + add_v3_v3v3(co, area_test.location, disp); - add_v3_v3(anctd->area_cos[flip_index], 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); - mul_v3_fl(no, nfactor); - - add_v3_v3(anctd->area_nos[flip_index], no); - anctd->count_no[flip_index] += 1; - } + add_v3_v3(anctd->area_cos[flip_index], 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); + mul_v3_fl(no, nfactor); + + add_v3_v3(anctd->area_nos[flip_index], no); + anctd->count_no[flip_index] += 1; } } BKE_pbvh_vertex_iter_end; @@ -2150,10 +2178,12 @@ static void calc_area_center( /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { - if (anctd.count_co[n] != 0) { - mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); - break; + if (anctd.count_co[n] == 0) { + continue; } + + mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); + break; } if (n == 2) { @@ -2249,10 +2279,12 @@ static void calc_area_normal_and_center( /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { - if (anctd.count_co[n] != 0) { - mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); - break; + if (anctd.count_co[n] == 0) { + continue; } + + mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]); + break; } if (n == 2) { @@ -2892,26 +2924,27 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = - bstrength * - SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * - ss->cache->pressure; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = + bstrength * + SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * + ss->cache->pressure; - float avg[3], val[3]; + float avg[3], val[3]; - SCULPT_bmesh_four_neighbor_average(avg, direction, vd.bm_vert); + SCULPT_bmesh_four_neighbor_average(avg, direction, vd.bm_vert); - sub_v3_v3v3(val, avg, vd.co); + sub_v3_v3v3(val, avg, vd.co); - madd_v3_v3v3fl(val, vd.co, val, fade); + madd_v3_v3v3fl(val, vd.co, val, fade); - SCULPT_clip(sd, ss, vd.co, val); + SCULPT_clip(sd, ss, vd.co, val); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -2964,21 +2997,23 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - if (bstrength > 0.0f) { - (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); - } - else { - (*vd.mask) += fade * bstrength * (*vd.mask); - } - *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f); + const float fade = SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (bstrength > 0.0f) { + (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); + } + else { + (*vd.mask) += fade * bstrength * (*vd.mask); + } + *vd.mask = clamp_f(*vd.mask, 0.0f, 1.0f); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } BKE_pbvh_vertex_iter_end; } @@ -3039,26 +3074,27 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata, PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - float limit_co[3]; - float disp[3]; - SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co); - sub_v3_v3v3(disp, limit_co, vd.co); - mul_v3_v3fl(proxy[vd.i], disp, fade); + float limit_co[3]; + float disp[3]; + SCULPT_vertex_limit_surface_get(ss, vd.index, limit_co); + sub_v3_v3v3(disp, limit_co, vd.co); + mul_v3_v3fl(proxy[vd.i], disp, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3151,12 +3187,15 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata, ss->cache->limit_surface_co[vd.index]); const float *neighbor_limit_surface_disp = ss->cache->prev_displacement[ni.index]; normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { - const float disp_interp = clamp_f( - -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); - madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp); - weights_accum += disp_interp; + + if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) { + continue; } + + const float disp_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + madd_v3_v3fl(interp_limit_surface_disp, neighbor_limit_surface_disp, disp_interp); + weights_accum += disp_interp; } SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); @@ -3246,23 +3285,24 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3325,23 +3365,24 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3407,52 +3448,53 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float current_disp[3]; - float current_disp_norm[3]; - float final_disp[3] = {0.0f, 0.0f, 0.0f}; + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float current_disp[3]; + float current_disp_norm[3]; + float final_disp[3] = {0.0f, 0.0f, 0.0f}; - switch (brush->slide_deform_type) { - case BRUSH_SLIDE_DEFORM_DRAG: - sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); - break; - case BRUSH_SLIDE_DEFORM_PINCH: - sub_v3_v3v3(current_disp, ss->cache->location, vd.co); - break; - case BRUSH_SLIDE_DEFORM_EXPAND: - sub_v3_v3v3(current_disp, vd.co, ss->cache->location); - break; - } + switch (brush->slide_deform_type) { + case BRUSH_SLIDE_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SLIDE_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SLIDE_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } - normalize_v3_v3(current_disp_norm, current_disp); - mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); - - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { - float vertex_disp[3]; - float vertex_disp_norm[3]; - sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); - normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) { - madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp)); - } + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) > 0.0f) { + madd_v3_v3fl(final_disp, vertex_disp_norm, dot_v3v3(current_disp, vertex_disp)); } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - mul_v3_v3fl(proxy[vd.i], final_disp, fade); + mul_v3_v3fl(proxy[vd.i], final_disp, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3482,16 +3524,17 @@ void SCULPT_relax_vertex(SculptSession *ss, /* When the vertex to relax is boundary, use only connected boundary vertices for the average * position. */ if (is_boundary) { - if (SCULPT_vertex_is_boundary(ss, ni.index)) { - add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); - avg_count++; - - /* Calculate a normal for the constraint plane using the edges of the boundary. */ - float to_neighbor[3]; - sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co); - normalize_v3(to_neighbor); - add_v3_v3(boundary_normal, to_neighbor); + if (!SCULPT_vertex_is_boundary(ss, ni.index)) { + continue; } + add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); + avg_count++; + + /* Calculate a normal for the constraint plane using the edges of the boundary. */ + float to_neighbor[3]; + sub_v3_v3v3(to_neighbor, SCULPT_vertex_co_get(ss, ni.index), vd->co); + normalize_v3(to_neighbor); + add_v3_v3(boundary_normal, to_neighbor); } else { add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index)); @@ -3563,21 +3606,22 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3728,38 +3772,39 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - /* Offset vertex. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float val1[3]; - float val2[3]; - - /* First we pinch. */ - sub_v3_v3v3(val1, test.location, vd.co); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(val1, val1, ss->cache->view_normal); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + /* Offset vertex. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float val1[3]; + float val2[3]; + + /* First we pinch. */ + sub_v3_v3v3(val1, test.location, vd.co); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(val1, val1, ss->cache->view_normal); + } - mul_v3_fl(val1, fade * flippedbstrength); + mul_v3_fl(val1, fade * flippedbstrength); - sculpt_project_v3(spvc, val1, val1); + sculpt_project_v3(spvc, val1, val1); - /* Then we draw. */ - mul_v3_v3fl(val2, offset, fade); + /* Then we draw. */ + mul_v3_v3fl(val2, offset, fade); - add_v3_v3v3(proxy[vd.i], val1, val2); + add_v3_v3v3(proxy[vd.i], val1, val2); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3845,40 +3890,41 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float disp_center[3]; - float x_disp[3]; - float z_disp[3]; - /* Calculate displacement from the vertex to the brush center. */ - sub_v3_v3v3(disp_center, test.location, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float disp_center[3]; + float x_disp[3]; + float z_disp[3]; + /* Calculate displacement from the vertex to the brush center. */ + sub_v3_v3v3(disp_center, test.location, vd.co); - /* Project the displacement into the X vector (aligned to the stroke). */ - mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); + /* Project the displacement into the X vector (aligned to the stroke). */ + mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); - /* Project the displacement into the Z vector (aligned to the surface normal). */ - mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); + /* Project the displacement into the Z vector (aligned to the surface normal). */ + mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); - /* Add the two projected vectors to calculate the final displacement. - * The Y component is removed. */ - add_v3_v3v3(disp_center, x_disp, z_disp); + /* Add the two projected vectors to calculate the final displacement. + * The Y component is removed. */ + add_v3_v3v3(disp_center, x_disp, z_disp); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal); - } - mul_v3_v3fl(proxy[vd.i], disp_center, fade); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal); + } + mul_v3_v3fl(proxy[vd.i], disp_center, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -3961,33 +4007,34 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (grab_silhouette) { - float silhouette_test_dir[3]; - normalize_v3_v3(silhouette_test_dir, grab_delta); - if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta_symmetry) < 0.0f) { - mul_v3_fl(silhouette_test_dir, -1.0f); - } - float vno[3]; - normal_short_to_float_v3(vno, orig_data.no); - fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (grab_silhouette) { + float silhouette_test_dir[3]; + normalize_v3_v3(silhouette_test_dir, grab_delta); + if (dot_v3v3(ss->cache->initial_normal, ss->cache->grab_delta_symmetry) < 0.0f) { + mul_v3_fl(silhouette_test_dir, -1.0f); } + float vno[3]; + normal_short_to_float_v3(vno, orig_data.no); + fade *= max_ff(dot_v3v3(vno, silhouette_test_dir), 0.0f); + } - mul_v3_v3fl(proxy[vd.i], grab_delta, fade); + mul_v3_v3fl(proxy[vd.i], grab_delta, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4149,13 +4196,14 @@ void SCULPT_flip_v3_by_symm_area(float v[3], { for (int i = 0; i < 3; i++) { ePaintSymmetryFlags symm_it = 1 << i; - if (symm & symm_it) { - if (symmarea & symm_it) { - flip_v3(v, symm_it); - } - if (pivot[i] < 0.0f) { - flip_v3(v, symm_it); - } + if (!(symm & symm_it)) { + continue; + } + if (symmarea & symm_it) { + flip_v3(v, symm_it); + } + if (pivot[i] < 0.0f) { + flip_v3(v, symm_it); } } } @@ -4167,13 +4215,14 @@ void SCULPT_flip_quat_by_symm_area(float quat[3], { for (int i = 0; i < 3; i++) { ePaintSymmetryFlags symm_it = 1 << i; - if (symm & symm_it) { - if (symmarea & symm_it) { - flip_qt(quat, symm_it); - } - if (pivot[i] < 0.0f) { - flip_qt(quat, symm_it); - } + if (!(symm & symm_it)) { + continue; + } + if (symmarea & symm_it) { + flip_qt(quat, symm_it); + } + if (pivot[i] < 0.0f) { + flip_qt(quat, symm_it); } } } @@ -4289,22 +4338,23 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], cono, fade); + mul_v3_v3fl(proxy[vd.i], cono, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4368,75 +4418,76 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (do_elastic || sculpt_brush_test_sq_fn(&test, vd.co)) { + if (!do_elastic && !sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - float fade; - if (do_elastic) { - fade = 1.0f; - } - else { - fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - } + float fade; + if (do_elastic) { + fade = 1.0f; + } + else { + fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + } - mul_v3_v3fl(proxy[vd.i], grab_delta, fade); + mul_v3_v3fl(proxy[vd.i], grab_delta, fade); - /* Negative pinch will inflate, helps maintain volume. */ - if (do_pinch) { - float delta_pinch_init[3], delta_pinch[3]; + /* Negative pinch will inflate, helps maintain volume. */ + if (do_pinch) { + float delta_pinch_init[3], delta_pinch[3]; - sub_v3_v3v3(delta_pinch, vd.co, test.location); - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal); - } + sub_v3_v3v3(delta_pinch, vd.co, test.location); + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(delta_pinch, delta_pinch, ss->cache->true_view_normal); + } - /* Important to calculate based on the grabbed location - * (intentionally ignore fade here). */ - add_v3_v3(delta_pinch, grab_delta); + /* Important to calculate based on the grabbed location + * (intentionally ignore fade here). */ + add_v3_v3(delta_pinch, grab_delta); - sculpt_project_v3(spvc, delta_pinch, delta_pinch); + sculpt_project_v3(spvc, delta_pinch, delta_pinch); - copy_v3_v3(delta_pinch_init, delta_pinch); + copy_v3_v3(delta_pinch_init, delta_pinch); - float pinch_fade = pinch * fade; - /* When reducing, scale reduction back by how close to the center we are, - * so we don't pinch into nothingness. */ - if (pinch > 0.0f) { - /* Square to have even less impact for close vertices. */ - pinch_fade *= pow2f(min_ff(1.0f, len_v3(delta_pinch) / ss->cache->radius)); - } - mul_v3_fl(delta_pinch, 1.0f + pinch_fade); - sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch); - add_v3_v3(proxy[vd.i], delta_pinch); + float pinch_fade = pinch * fade; + /* When reducing, scale reduction back by how close to the center we are, + * so we don't pinch into nothingness. */ + if (pinch > 0.0f) { + /* Square to have even less impact for close vertices. */ + pinch_fade *= pow2f(min_ff(1.0f, len_v3(delta_pinch) / ss->cache->radius)); } + mul_v3_fl(delta_pinch, 1.0f + pinch_fade); + sub_v3_v3v3(delta_pinch, delta_pinch_init, delta_pinch); + add_v3_v3(proxy[vd.i], delta_pinch); + } - if (do_rake_rotation) { - float delta_rotate[3]; - sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate); - add_v3_v3(proxy[vd.i], delta_rotate); - } + if (do_rake_rotation) { + float delta_rotate[3]; + sculpt_rake_rotate(ss, test.location, vd.co, fade, delta_rotate); + add_v3_v3(proxy[vd.i], delta_rotate); + } - if (do_elastic) { - float disp[3]; - BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); - mul_v3_fl(disp, bstrength * 20.0f); - if (vd.mask) { - mul_v3_fl(disp, 1.0f - *vd.mask); - } - mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); - copy_v3_v3(proxy[vd.i], disp); + if (do_elastic) { + float disp[3]; + BKE_kelvinlet_grab_triscale(disp, ¶ms, vd.co, ss->cache->location, proxy[vd.i]); + mul_v3_fl(disp, bstrength * 20.0f); + if (vd.mask) { + mul_v3_fl(disp, 1.0f - *vd.mask); } + mul_v3_fl(disp, SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index)); + copy_v3_v3(proxy[vd.i], disp); + } - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4507,22 +4558,23 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], cono, fade); + mul_v3_v3fl(proxy[vd.i], cono, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4580,27 +4632,28 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - float vec[3], rot[3][3]; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - orig_data.co, - sqrtf(test.dist), - orig_data.no, - NULL, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + float vec[3], rot[3][3]; + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + orig_data.co, + sqrtf(test.dist), + orig_data.no, + NULL, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - sub_v3_v3v3(vec, orig_data.co, ss->cache->location); - axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); - mul_v3_m3v3(proxy[vd.i], rot, vec); - add_v3_v3(proxy[vd.i], ss->cache->location); - sub_v3_v3(proxy[vd.i], orig_data.co); + sub_v3_v3v3(vec, orig_data.co, ss->cache->location); + axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); + mul_v3_m3v3(proxy[vd.i], rot, vec); + add_v3_v3(proxy[vd.i], ss->cache->location); + sub_v3_v3(proxy[vd.i], orig_data.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4652,70 +4705,71 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, orig_data.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - const int vi = vd.index; - float *disp_factor; - if (use_persistent_base) { - disp_factor = &ss->persistent_base[vi].disp; - } - else { - disp_factor = &ss->cache->layer_displacement_factor[vi]; - } + if (!sculpt_brush_test_sq_fn(&test, orig_data.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + const int vi = vd.index; + float *disp_factor; + if (use_persistent_base) { + disp_factor = &ss->persistent_base[vi].disp; + } + else { + disp_factor = &ss->cache->layer_displacement_factor[vi]; + } - /* When using persistent base, the layer brush (holding Control) invert mode resets the - * height of the layer to 0. This makes possible to clean edges of previously added layers - * on top of the base. */ - /* The main direction of the layers is inverted using the regular brush strength with the - * brush direction property. */ - if (use_persistent_base && ss->cache->invert) { - (*disp_factor) += fabsf(fade * bstrength * (*disp_factor)) * - ((*disp_factor) > 0.0f ? -1.0f : 1.0f); - } - else { - (*disp_factor) += fade * bstrength * (1.05f - fabsf(*disp_factor)); - } - if (vd.mask) { - const float clamp_mask = 1.0f - *vd.mask; - *disp_factor = clamp_f(*disp_factor, -clamp_mask, clamp_mask); - } - else { - *disp_factor = clamp_f(*disp_factor, -1.0f, 1.0f); - } + /* When using persistent base, the layer brush (holding Control) invert mode resets the + * height of the layer to 0. This makes possible to clean edges of previously added layers + * on top of the base. */ + /* The main direction of the layers is inverted using the regular brush strength with the + * brush direction property. */ + if (use_persistent_base && ss->cache->invert) { + (*disp_factor) += fabsf(fade * bstrength * (*disp_factor)) * + ((*disp_factor) > 0.0f ? -1.0f : 1.0f); + } + else { + (*disp_factor) += fade * bstrength * (1.05f - fabsf(*disp_factor)); + } + if (vd.mask) { + const float clamp_mask = 1.0f - *vd.mask; + *disp_factor = clamp_f(*disp_factor, -clamp_mask, clamp_mask); + } + else { + *disp_factor = clamp_f(*disp_factor, -1.0f, 1.0f); + } - float final_co[3]; - float normal[3]; + float final_co[3]; + float normal[3]; - if (use_persistent_base) { - SCULPT_vertex_persistent_normal_get(ss, vi, normal); - mul_v3_fl(normal, brush->height); - madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor); - } - else { - normal_short_to_float_v3(normal, orig_data.no); - mul_v3_fl(normal, brush->height); - madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor); - } + if (use_persistent_base) { + SCULPT_vertex_persistent_normal_get(ss, vi, normal); + mul_v3_fl(normal, brush->height); + madd_v3_v3v3fl(final_co, SCULPT_vertex_persistent_co_get(ss, vi), normal, *disp_factor); + } + else { + normal_short_to_float_v3(normal, orig_data.no); + mul_v3_fl(normal, brush->height); + madd_v3_v3v3fl(final_co, orig_data.co, normal, *disp_factor); + } - float vdisp[3]; - sub_v3_v3v3(vdisp, final_co, vd.co); - mul_v3_fl(vdisp, fabsf(fade)); - add_v3_v3v3(final_co, vd.co, vdisp); + float vdisp[3]; + sub_v3_v3v3(vdisp, final_co, vd.co); + mul_v3_fl(vdisp, fabsf(fade)); + add_v3_v3v3(final_co, vd.co, vdisp); - SCULPT_clip(sd, ss, vd.co, final_co); + SCULPT_clip(sd, ss, vd.co, final_co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4764,31 +4818,32 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - float val[3]; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + float val[3]; - if (vd.fno) { - copy_v3_v3(val, vd.fno); - } - else { - normal_short_to_float_v3(val, vd.no); - } + if (vd.fno) { + copy_v3_v3(val, vd.fno); + } + else { + normal_short_to_float_v3(val, vd.no); + } - mul_v3_fl(val, fade * ss->cache->radius); - mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); + mul_v3_fl(val, fade * ss->cache->radius); + mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -4869,30 +4924,31 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float intr[3]; - float val[3]; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float intr[3]; + float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - sub_v3_v3v3(val, intr, vd.co); + sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (SCULPT_plane_trim(ss->cache, brush, val)) { + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], val, fade); + mul_v3_v3fl(proxy[vd.i], val, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } } @@ -4975,16 +5031,17 @@ static void calc_clay_surface_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float plane_dist = dist_signed_to_plane_v3(vd.co, plane); - float plane_dist_abs = fabsf(plane_dist); - if (plane_dist > 0.0f) { - csd->plane_dist[0] = MIN2(csd->plane_dist[0], plane_dist_abs); - } - else { - csd->plane_dist[1] = MIN2(csd->plane_dist[1], plane_dist_abs); - } + float plane_dist = dist_signed_to_plane_v3(vd.co, plane); + float plane_dist_abs = fabsf(plane_dist); + if (plane_dist > 0.0f) { + csd->plane_dist[0] = MIN2(csd->plane_dist[0], plane_dist_abs); + } + else { + csd->plane_dist[1] = MIN2(csd->plane_dist[1], plane_dist_abs); } BKE_pbvh_vertex_iter_end; } @@ -5025,28 +5082,30 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float intr[3]; - float val[3]; - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } - sub_v3_v3v3(val, intr, vd.co); + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + sub_v3_v3v3(val, intr, vd.co); - mul_v3_v3fl(proxy[vd.i], val, fade); + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5143,35 +5202,37 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) { - if (plane_point_side_flip(vd.co, test.plane_tool, flip)) { - float intr[3]; - float val[3]; + if (!SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) { + continue; + } - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + if (!plane_point_side_flip(vd.co, test.plane_tool, flip)) { + continue; + } - sub_v3_v3v3(val, intr, vd.co); + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */ - const float fade = bstrength * - SCULPT_brush_strength_factor(ss, - brush, - vd.co, - ss->cache->radius * test.dist, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + /* The normal from the vertices is ignored, it causes glitch with planes, see: T44390. */ + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + ss->cache->radius * test.dist, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], val, fade); + mul_v3_v3fl(proxy[vd.i], val, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5295,33 +5356,37 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (SCULPT_plane_point_side(vd.co, test.plane_tool)) { - float intr[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - - sub_v3_v3v3(val, intr, vd.co); - - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + if (!SCULPT_plane_point_side(vd.co, test.plane_tool)) { + continue; + } + + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); + + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5390,33 +5455,37 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (!SCULPT_plane_point_side(vd.co, test.plane_tool)) { - float intr[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - - sub_v3_v3v3(val, intr, vd.co); - - if (SCULPT_plane_trim(ss->cache, brush, val)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + if (SCULPT_plane_point_side(vd.co, test.plane_tool)) { + continue; + } + + float intr[3]; + float val[3]; + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + sub_v3_v3v3(val, intr, vd.co); + + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5501,38 +5570,39 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - mul_v3_m4v3(local_co, mat, vd.co); - float intr[3], intr_tilt[3]; - float val[3]; - - closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); - closest_to_plane_normalized_v3(intr_tilt, plane_tilt, vd.co); - - /* Mix the deformation of the aligned and the tilted plane based on the brush space vertex - * coordinates. */ - /* We can also control the mix with a curve if it produces noticeable artifacts in the center - * of the brush. */ - const float tilt_mix = local_co[1] > 0.0f ? 0.0f : 1.0f; - interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix); - sub_v3_v3v3(val, intr_tilt, vd.co); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float local_co[3]; + mul_v3_m4v3(local_co, mat, vd.co); + float intr[3], intr_tilt[3]; + float val[3]; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + closest_to_plane_normalized_v3(intr, test.plane_tool, vd.co); + closest_to_plane_normalized_v3(intr_tilt, plane_tilt, vd.co); - mul_v3_v3fl(proxy[vd.i], val, fade); + /* Mix the deformation of the aligned and the tilted plane based on the brush space vertex + * coordinates. */ + /* We can also control the mix with a curve if it produces noticeable artifacts in the center + * of the brush. */ + const float tilt_mix = local_co[1] > 0.0f ? 0.0f : 1.0f; + interp_v3_v3v3(intr, intr, intr_tilt, tilt_mix); + sub_v3_v3v3(val, intr_tilt, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5656,22 +5726,23 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); - mul_v3_v3fl(proxy[vd.i], offset, fade); + mul_v3_v3fl(proxy[vd.i], offset, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -5766,49 +5837,51 @@ static void sculpt_topology_update(Sculpt *sd, ob, sd, brush, use_original, radius_scale, &totnode); /* Only act if some verts are inside the brush area. */ - if (totnode) { - PBVHTopologyUpdateMode mode = 0; - float location[3]; + if (totnode == 0) { + return; + } - if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) { - if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) { - mode |= PBVH_Subdivide; - } + PBVHTopologyUpdateMode mode = 0; + float location[3]; - if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) { - mode |= PBVH_Collapse; - } + if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) { + if (sd->flags & SCULPT_DYNTOPO_SUBDIVIDE) { + mode |= PBVH_Subdivide; } - for (n = 0; n < totnode; n++) { - SCULPT_undo_push_node(ob, - nodes[n], - brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : - SCULPT_UNDO_COORDS); - BKE_pbvh_node_mark_update(nodes[n]); - - if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_node_mark_topology_update(nodes[n]); - BKE_pbvh_bmesh_node_save_orig(ss->bm, nodes[n]); - } + if ((sd->flags & SCULPT_DYNTOPO_COLLAPSE) || (brush->sculpt_tool == SCULPT_TOOL_SIMPLIFY)) { + mode |= PBVH_Collapse; } + } + + for (n = 0; n < totnode; n++) { + SCULPT_undo_push_node(ob, + nodes[n], + brush->sculpt_tool == SCULPT_TOOL_MASK ? SCULPT_UNDO_MASK : + SCULPT_UNDO_COORDS); + BKE_pbvh_node_mark_update(nodes[n]); if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { - BKE_pbvh_bmesh_update_topology(ss->pbvh, - mode, - ss->cache->location, - ss->cache->view_normal, - ss->cache->radius, - (brush->flag & BRUSH_FRONTFACE) != 0, - (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE)); + BKE_pbvh_node_mark_topology_update(nodes[n]); + BKE_pbvh_bmesh_node_save_orig(ss->bm, nodes[n]); } + } - MEM_SAFE_FREE(nodes); - - /* Update average stroke position. */ - copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) { + BKE_pbvh_bmesh_update_topology(ss->pbvh, + mode, + ss->cache->location, + ss->cache->view_normal, + ss->cache->radius, + (brush->flag & BRUSH_FRONTFACE) != 0, + (brush->falloff_shape != PAINT_FALLOFF_SHAPE_SPHERE)); } + + MEM_SAFE_FREE(nodes); + + /* Update average stroke position. */ + copy_v3_v3(location, ss->cache->true_location); + mul_m4_v3(ob->obmat, location); } static void do_brush_action_task_cb(void *__restrict userdata, @@ -5914,202 +5987,199 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe } /* Only act if some verts are inside the brush area. */ - if (totnode) { - float location[3]; + if (totnode == 0) { + return; + } + float location[3]; - SculptThreadedTaskData task_data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; + SculptThreadedTaskData task_data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); - if (sculpt_brush_needs_normal(ss, brush)) { - update_sculpt_normal(sd, ob, nodes, totnode); - } + if (sculpt_brush_needs_normal(ss, brush)) { + update_sculpt_normal(sd, ob, nodes, totnode); + } - if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { - update_brush_local_mat(sd, ob); - } + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_AREA) { + update_brush_local_mat(sd, ob); + } - if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) { - SCULPT_pose_brush_init(sd, ob, ss, brush); - } + if (brush->sculpt_tool == SCULPT_TOOL_POSE && SCULPT_stroke_is_first_brush_step(ss->cache)) { + SCULPT_pose_brush_init(sd, ob, ss, brush); + } - if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { - if (!ss->cache->cloth_sim) { - ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create( - ss, 1.0f, 0.0f, 0.0f, false, true); - SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); - } - SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim); - SCULPT_cloth_brush_ensure_nodes_constraints( - sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX); + if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { + if (!ss->cache->cloth_sim) { + ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create( + ss, 1.0f, 0.0f, 0.0f, false, true); + SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim); } + SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim); + SCULPT_cloth_brush_ensure_nodes_constraints( + sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX); + } - bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN; + bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN; - /* Apply one type of brush action. */ - switch (brush->sculpt_tool) { - case SCULPT_TOOL_DRAW: - do_draw_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SMOOTH: - if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) { - SCULPT_do_smooth_brush(sd, ob, nodes, totnode); - } - else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { - SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_CREASE: - do_crease_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_BLOB: - do_crease_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_PINCH: - do_pinch_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_INFLATE: - do_inflate_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_GRAB: - do_grab_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_ROTATE: - do_rotate_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SNAKE_HOOK: - do_snake_hook_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_NUDGE: - do_nudge_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_THUMB: - do_thumb_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_LAYER: - do_layer_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_FLATTEN: - do_flatten_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY: - do_clay_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY_STRIPS: - do_clay_strips_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_MULTIPLANE_SCRAPE: - SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLAY_THUMB: - do_clay_thumb_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_FILL: - if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_scrape_brush(sd, ob, nodes, totnode); - } - else { - do_fill_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_SCRAPE: - if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { - do_fill_brush(sd, ob, nodes, totnode); - } - else { - do_scrape_brush(sd, ob, nodes, totnode); - } - break; - case SCULPT_TOOL_MASK: - do_mask_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_POSE: - SCULPT_do_pose_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DRAW_SHARP: - do_draw_sharp_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_ELASTIC_DEFORM: - do_elastic_deform_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SLIDE_RELAX: - do_slide_relax_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_BOUNDARY: - SCULPT_do_boundary_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_CLOTH: - SCULPT_do_cloth_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DRAW_FACE_SETS: - SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DISPLACEMENT_ERASER: - do_displacement_eraser_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_DISPLACEMENT_SMEAR: - do_displacement_smear_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_PAINT: - SCULPT_do_paint_brush(sd, ob, nodes, totnode); - break; - case SCULPT_TOOL_SMEAR: - SCULPT_do_smear_brush(sd, ob, nodes, totnode); - break; - } - - if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) && - brush->autosmooth_factor > 0) { - if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) { - SCULPT_smooth(sd, - ob, - nodes, - totnode, - brush->autosmooth_factor * (1.0f - ss->cache->pressure), - false); + /* Apply one type of brush action. */ + switch (brush->sculpt_tool) { + case SCULPT_TOOL_DRAW: + do_draw_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SMOOTH: + if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_LAPLACIAN) { + SCULPT_do_smooth_brush(sd, ob, nodes, totnode); + } + else if (brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE) { + SCULPT_do_surface_smooth_brush(sd, ob, nodes, totnode); + } + break; + case SCULPT_TOOL_CREASE: + do_crease_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_BLOB: + do_crease_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_PINCH: + do_pinch_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_INFLATE: + do_inflate_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_GRAB: + do_grab_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_ROTATE: + do_rotate_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SNAKE_HOOK: + do_snake_hook_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_NUDGE: + do_nudge_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_THUMB: + do_thumb_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_LAYER: + do_layer_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_FLATTEN: + do_flatten_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY: + do_clay_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY_STRIPS: + do_clay_strips_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_MULTIPLANE_SCRAPE: + SCULPT_do_multiplane_scrape_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLAY_THUMB: + do_clay_thumb_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_FILL: + if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { + do_scrape_brush(sd, ob, nodes, totnode); } else { - SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false); + do_fill_brush(sd, ob, nodes, totnode); } - } + break; + case SCULPT_TOOL_SCRAPE: + if (invert && brush->flag & BRUSH_INVERT_TO_SCRAPE_FILL) { + do_fill_brush(sd, ob, nodes, totnode); + } + else { + do_scrape_brush(sd, ob, nodes, totnode); + } + break; + case SCULPT_TOOL_MASK: + do_mask_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_POSE: + SCULPT_do_pose_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DRAW_SHARP: + do_draw_sharp_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_ELASTIC_DEFORM: + do_elastic_deform_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SLIDE_RELAX: + do_slide_relax_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_BOUNDARY: + SCULPT_do_boundary_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_CLOTH: + SCULPT_do_cloth_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DRAW_FACE_SETS: + SCULPT_do_draw_face_sets_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DISPLACEMENT_ERASER: + do_displacement_eraser_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_DISPLACEMENT_SMEAR: + do_displacement_smear_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_PAINT: + SCULPT_do_paint_brush(sd, ob, nodes, totnode); + break; + case SCULPT_TOOL_SMEAR: + SCULPT_do_smear_brush(sd, ob, nodes, totnode); + break; + } - if (sculpt_brush_use_topology_rake(ss, brush)) { - bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor); + if (!ELEM(brush->sculpt_tool, SCULPT_TOOL_SMOOTH, SCULPT_TOOL_MASK) && + brush->autosmooth_factor > 0) { + if (brush->flag & BRUSH_INVERSE_SMOOTH_PRESSURE) { + SCULPT_smooth( + sd, ob, nodes, totnode, brush->autosmooth_factor * (1.0f - ss->cache->pressure), false); } - - /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */ - if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool, - SCULPT_TOOL_CLOTH, - SCULPT_TOOL_DRAW_FACE_SETS, - SCULPT_TOOL_BOUNDARY)) { - do_gravity(sd, ob, nodes, totnode, sd->gravity_factor); + else { + SCULPT_smooth(sd, ob, nodes, totnode, brush->autosmooth_factor, false); } + } - if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { - if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) { - SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode); - SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); - } + if (sculpt_brush_use_topology_rake(ss, brush)) { + bmesh_topology_rake(sd, ob, nodes, totnode, brush->topology_rake_factor); + } + + /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */ + if (ss->cache->supports_gravity && !ELEM(brush->sculpt_tool, + SCULPT_TOOL_CLOTH, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_BOUNDARY)) { + do_gravity(sd, ob, nodes, totnode, sd->gravity_factor); + } + + if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) { + if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) { + SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode); + SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode); } + } - MEM_SAFE_FREE(nodes); + MEM_SAFE_FREE(nodes); - /* Update average stroke position. */ - copy_v3_v3(location, ss->cache->true_location); - mul_m4_v3(ob->obmat, location); + /* Update average stroke position. */ + copy_v3_v3(location, ss->cache->true_location); + mul_m4_v3(ob->obmat, location); - add_v3_v3(ups->average_stroke_accum, location); - ups->average_stroke_counter++; - /* Update last stroke position. */ - ups->last_stroke_valid = true; - } + add_v3_v3(ups->average_stroke_accum, location); + ups->average_stroke_counter++; + /* Update last stroke position. */ + ups->last_stroke_valid = true; } /* Flush displacement from deformed PBVH vertex to original mesh. */ @@ -6199,22 +6269,22 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) PBVHNode **nodes; int totnode; - BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); - - /* First line is tools that don't support proxies. */ - if (ss->cache->supports_gravity || (sculpt_tool_is_proxy_used(brush->sculpt_tool) == false)) { - SculptThreadedTaskData data = { - .sd = sd, - .ob = ob, - .brush = brush, - .nodes = nodes, - }; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); + if (!ss->cache->supports_gravity && sculpt_tool_is_proxy_used(brush->sculpt_tool)) { + /* First line is tools that don't support proxies. */ + return; } + BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode); + SculptThreadedTaskData data = { + .sd = sd, + .ob = ob, + .brush = brush, + .nodes = nodes, + }; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); MEM_SAFE_FREE(nodes); } @@ -6235,12 +6305,14 @@ static void sculpt_update_keyblock(Object *ob) vertCos = BKE_pbvh_vert_coords_alloc(ss->pbvh); } - if (vertCos) { - SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); + if (!vertCos) { + return; + } - if (vertCos != ss->orig_cos) { - MEM_freeN(vertCos); - } + SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); + + if (vertCos != ss->orig_cos) { + MEM_freeN(vertCos); } } @@ -6259,10 +6331,12 @@ static void SCULPT_flush_stroke_deform_task_cb(void *__restrict userdata, { sculpt_flush_pbvhvert_deform(ob, &vd); - if (vertCos) { - int index = vd.vert_indices[vd.i]; - copy_v3_v3(vertCos[index], ss->orig_cos[index]); + if (!vertCos) { + continue; } + + int index = vd.vert_indices[vd.i]; + copy_v3_v3(vertCos[index], ss->orig_cos[index]); } BKE_pbvh_vertex_iter_end; } @@ -6490,17 +6564,18 @@ static void do_symmetrical_brush_actions(Sculpt *sd, /* `symm` is a bit combination of XYZ - * 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */ for (int i = 0; i <= symm; i++) { - if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) { - cache->mirror_symmetry_pass = i; - cache->radial_symmetry_pass = 0; + if (!SCULPT_is_symmetry_iteration_valid(i, symm)) { + continue; + } + cache->mirror_symmetry_pass = i; + cache->radial_symmetry_pass = 0; - SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0); - do_tiled(sd, ob, brush, ups, action); + SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0); + do_tiled(sd, ob, brush, ups, action); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather); - do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather); - } + do_radial_symmetry(sd, ob, brush, ups, action, i, 'X', feather); + do_radial_symmetry(sd, ob, brush, ups, action, i, 'Y', feather); + do_radial_symmetry(sd, ob, brush, ups, action, i, 'Z', feather); } } @@ -6668,22 +6743,25 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss) ModifierData *md; for (md = ob->modifiers.first; md; md = md->next) { - if (md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime)) { - MirrorModifierData *mmd = (MirrorModifierData *)md; - - if (mmd->flag & MOD_MIR_CLIPPING) { - /* Check each axis for mirroring. */ - for (int i = 0; i < 3; i++) { - if (mmd->flag & (MOD_MIR_AXIS_X << i)) { - /* Enable sculpt clipping. */ - ss->cache->flag |= CLIP_X << i; - - /* Update the clip tolerance. */ - if (mmd->tolerance > ss->cache->clip_tolerance[i]) { - ss->cache->clip_tolerance[i] = mmd->tolerance; - } - } - } + if (!(md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime))) { + continue; + } + MirrorModifierData *mmd = (MirrorModifierData *)md; + + if (!(mmd->flag & MOD_MIR_CLIPPING)) { + continue; + } + /* Check each axis for mirroring. */ + for (int i = 0; i < 3; i++) { + if (!(mmd->flag & (MOD_MIR_AXIS_X << i))) { + continue; + } + /* Enable sculpt clipping. */ + ss->cache->flag |= CLIP_X << i; + + /* Update the clip tolerance. */ + if (mmd->tolerance > ss->cache->clip_tolerance[i]) { + ss->cache->clip_tolerance[i] = mmd->tolerance; } } } @@ -6926,150 +7004,151 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru }; int tool = brush->sculpt_tool; - if (ELEM(tool, - SCULPT_TOOL_PAINT, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ELASTIC_DEFORM, - SCULPT_TOOL_CLOTH, - SCULPT_TOOL_NUDGE, - SCULPT_TOOL_CLAY_STRIPS, - SCULPT_TOOL_PINCH, - SCULPT_TOOL_MULTIPLANE_SCRAPE, - SCULPT_TOOL_CLAY_THUMB, - SCULPT_TOOL_SNAKE_HOOK, - SCULPT_TOOL_POSE, - SCULPT_TOOL_BOUNDARY, - SCULPT_TOOL_THUMB) || - sculpt_brush_use_topology_rake(ss, brush)) { - float grab_location[3], imat[4][4], delta[3], loc[3]; + if (!ELEM(tool, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ELASTIC_DEFORM, + SCULPT_TOOL_CLOTH, + SCULPT_TOOL_NUDGE, + SCULPT_TOOL_CLAY_STRIPS, + SCULPT_TOOL_PINCH, + SCULPT_TOOL_MULTIPLANE_SCRAPE, + SCULPT_TOOL_CLAY_THUMB, + SCULPT_TOOL_SNAKE_HOOK, + SCULPT_TOOL_POSE, + SCULPT_TOOL_BOUNDARY, + SCULPT_TOOL_THUMB) && + !sculpt_brush_use_topology_rake(ss, brush)) { + return; + } + float grab_location[3], imat[4][4], delta[3], loc[3]; - if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { - copy_v3_v3(cache->orig_grab_location, - SCULPT_vertex_co_for_grab_active_get(ss, SCULPT_active_vertex_get(ss))); - } - else { - copy_v3_v3(cache->orig_grab_location, cache->true_location); - } + if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + if (tool == SCULPT_TOOL_GRAB && brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { + copy_v3_v3(cache->orig_grab_location, + SCULPT_vertex_co_for_grab_active_get(ss, SCULPT_active_vertex_get(ss))); } - else if (tool == SCULPT_TOOL_SNAKE_HOOK || - (tool == SCULPT_TOOL_CLOTH && - brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK)) { - add_v3_v3(cache->true_location, cache->grab_delta); + else { + copy_v3_v3(cache->orig_grab_location, cache->true_location); } + } + else if (tool == SCULPT_TOOL_SNAKE_HOOK || + (tool == SCULPT_TOOL_CLOTH && + brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_SNAKE_HOOK)) { + add_v3_v3(cache->true_location, cache->grab_delta); + } - /* Compute 3d coordinate at same z from original location + mouse. */ - mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); - ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location); + /* Compute 3d coordinate at same z from original location + mouse. */ + mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); + ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mouse, grab_location); - /* Compute delta to move verts by. */ - if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - if (sculpt_needs_delta_from_anchored_origin(brush)) { - sub_v3_v3v3(delta, grab_location, cache->old_grab_location); - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, delta); - add_v3_v3(cache->grab_delta, delta); - } - else if (sculpt_needs_delta_for_tip_orientation(brush)) { - if (brush->flag & BRUSH_ANCHORED) { - float orig[3]; - mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location); - sub_v3_v3v3(cache->grab_delta, grab_location, orig); - } - else { - sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); - } - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, cache->grab_delta); + /* Compute delta to move verts by. */ + if (!SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + if (sculpt_needs_delta_from_anchored_origin(brush)) { + sub_v3_v3v3(delta, grab_location, cache->old_grab_location); + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, delta); + add_v3_v3(cache->grab_delta, delta); + } + else if (sculpt_needs_delta_for_tip_orientation(brush)) { + if (brush->flag & BRUSH_ANCHORED) { + float orig[3]; + mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location); + sub_v3_v3v3(cache->grab_delta, grab_location, orig); } else { - /* Use for 'Brush.topology_rake_factor'. */ sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); } + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, cache->grab_delta); } else { - zero_v3(cache->grab_delta); + /* Use for 'Brush.topology_rake_factor'. */ + sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location); } + } + else { + zero_v3(cache->grab_delta); + } - if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { - project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal); - } + if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) { + project_plane_v3_v3v3(cache->grab_delta, cache->grab_delta, ss->cache->true_view_normal); + } - copy_v3_v3(cache->old_grab_location, grab_location); + copy_v3_v3(cache->old_grab_location, grab_location); - if (tool == SCULPT_TOOL_GRAB) { - if (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { - copy_v3_v3(cache->anchored_location, cache->orig_grab_location); - } - else { - copy_v3_v3(cache->anchored_location, cache->true_location); - } + if (tool == SCULPT_TOOL_GRAB) { + if (brush->flag & BRUSH_GRAB_ACTIVE_VERTEX) { + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); } - else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) { + else { copy_v3_v3(cache->anchored_location, cache->true_location); } - else if (tool == SCULPT_TOOL_THUMB) { - copy_v3_v3(cache->anchored_location, cache->orig_grab_location); - } + } + else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) { + copy_v3_v3(cache->anchored_location, cache->true_location); + } + else if (tool == SCULPT_TOOL_THUMB) { + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); + } - if (sculpt_needs_delta_from_anchored_origin(brush)) { - /* Location stays the same for finding vertices in brush radius. */ - copy_v3_v3(cache->true_location, cache->orig_grab_location); + if (sculpt_needs_delta_from_anchored_origin(brush)) { + /* Location stays the same for finding vertices in brush radius. */ + copy_v3_v3(cache->true_location, cache->orig_grab_location); - ups->draw_anchored = true; - copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - ups->anchored_size = ups->pixel_radius; - } + ups->draw_anchored = true; + copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); + ups->anchored_size = ups->pixel_radius; + } - /* Handle 'rake' */ - cache->is_rake_rotation_valid = false; + /* Handle 'rake' */ + cache->is_rake_rotation_valid = false; - invert_m4_m4(imat, ob->obmat); - mul_mat3_m4_v3(imat, grab_location); + invert_m4_m4(imat, ob->obmat); + mul_mat3_m4_v3(imat, grab_location); - if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { - copy_v3_v3(cache->rake_data.follow_co, grab_location); - } + if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) { + copy_v3_v3(cache->rake_data.follow_co, grab_location); + } - if (sculpt_brush_needs_rake_rotation(brush)) { - cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR; + if (!sculpt_brush_needs_rake_rotation(brush)) { + return; + } + cache->rake_data.follow_dist = cache->radius * SCULPT_RAKE_BRUSH_FACTOR; - if (!is_zero_v3(cache->grab_delta)) { - const float eps = 0.00001f; + if (!is_zero_v3(cache->grab_delta)) { + const float eps = 0.00001f; - float v1[3], v2[3]; + float v1[3], v2[3]; - copy_v3_v3(v1, cache->rake_data.follow_co); - copy_v3_v3(v2, cache->rake_data.follow_co); - sub_v3_v3(v2, cache->grab_delta); + copy_v3_v3(v1, cache->rake_data.follow_co); + copy_v3_v3(v2, cache->rake_data.follow_co); + sub_v3_v3(v2, cache->grab_delta); - sub_v3_v3(v1, grab_location); - sub_v3_v3(v2, grab_location); + sub_v3_v3(v1, grab_location); + sub_v3_v3(v2, grab_location); - if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) && - (len_squared_v3v3(v1, v2) > eps)) { - const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location); - const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ? - 1.0f : - sqrtf(rake_dist_sq) / cache->rake_data.follow_dist; + if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) && (len_squared_v3v3(v1, v2) > eps)) { + const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location); + const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ? + 1.0f : + sqrtf(rake_dist_sq) / cache->rake_data.follow_dist; - float axis[3], angle; - float tquat[4]; + float axis[3], angle; + float tquat[4]; - rotation_between_vecs_to_quat(tquat, v1, v2); + rotation_between_vecs_to_quat(tquat, v1, v2); - /* Use axis-angle to scale rotation since the factor may be above 1. */ - quat_to_axis_angle(axis, &angle, tquat); - normalize_v3(axis); + /* Use axis-angle to scale rotation since the factor may be above 1. */ + quat_to_axis_angle(axis, &angle, tquat); + normalize_v3(axis); - angle *= brush->rake_factor * rake_fade; - axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle); - cache->is_rake_rotation_valid = true; - } - } - sculpt_rake_data_update(&cache->rake_data, grab_location); + angle *= brush->rake_factor * rake_fade; + axis_angle_normalized_to_quat(cache->rake_rotation, axis, angle); + cache->is_rake_rotation_valid = true; } } + sculpt_rake_data_update(&cache->rake_data, grab_location); } static void sculpt_update_cache_paint_variants(StrokeCache *cache, const Brush *brush) @@ -7257,71 +7336,73 @@ void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *b static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin) { - if (BKE_pbvh_node_get_tmin(node) < *tmin) { - SculptRaycastData *srd = data_v; - float(*origco)[3] = NULL; - bool use_origco = false; + if (BKE_pbvh_node_get_tmin(node) >= *tmin) { + return; + } + SculptRaycastData *srd = data_v; + float(*origco)[3] = NULL; + bool use_origco = false; - if (srd->original && srd->ss->cache) { - if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { - use_origco = true; - } - else { - /* Intersect with coordinates from before we started stroke. */ - SculptUndoNode *unode = SCULPT_undo_get_node(node); - origco = (unode) ? unode->co : NULL; - use_origco = origco ? true : false; - } + if (srd->original && srd->ss->cache) { + if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { + use_origco = true; } - - if (BKE_pbvh_node_raycast(srd->ss->pbvh, - node, - origco, - use_origco, - srd->ray_start, - srd->ray_normal, - &srd->isect_precalc, - &srd->depth, - &srd->active_vertex_index, - &srd->active_face_grid_index, - srd->face_normal)) { - srd->hit = true; - *tmin = srd->depth; + else { + /* Intersect with coordinates from before we started stroke. */ + SculptUndoNode *unode = SCULPT_undo_get_node(node); + origco = (unode) ? unode->co : NULL; + use_origco = origco ? true : false; } } + + if (BKE_pbvh_node_raycast(srd->ss->pbvh, + node, + origco, + use_origco, + srd->ray_start, + srd->ray_normal, + &srd->isect_precalc, + &srd->depth, + &srd->active_vertex_index, + &srd->active_face_grid_index, + srd->face_normal)) { + srd->hit = true; + *tmin = srd->depth; + } } static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *tmin) { - if (BKE_pbvh_node_get_tmin(node) < *tmin) { - SculptFindNearestToRayData *srd = data_v; - float(*origco)[3] = NULL; - bool use_origco = false; + if (BKE_pbvh_node_get_tmin(node) >= *tmin) { + return; + } + SculptFindNearestToRayData *srd = data_v; + float(*origco)[3] = NULL; + bool use_origco = false; - if (srd->original && srd->ss->cache) { - if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { - use_origco = true; - } - else { - /* Intersect with coordinates from before we started stroke. */ - SculptUndoNode *unode = SCULPT_undo_get_node(node); - origco = (unode) ? unode->co : NULL; - use_origco = origco ? true : false; - } + if (srd->original && srd->ss->cache) { + if (BKE_pbvh_type(srd->ss->pbvh) == PBVH_BMESH) { + use_origco = true; } - - if (BKE_pbvh_node_find_nearest_to_ray(srd->ss->pbvh, - node, - origco, - use_origco, - srd->ray_start, - srd->ray_normal, - &srd->depth, - &srd->dist_sq_to_ray)) { - srd->hit = true; - *tmin = srd->dist_sq_to_ray; + else { + /* Intersect with coordinates from before we started stroke. */ + SculptUndoNode *unode = SCULPT_undo_get_node(node); + origco = (unode) ? unode->co : NULL; + use_origco = origco ? true : false; } } + + if (BKE_pbvh_node_find_nearest_to_ray(srd->ss->pbvh, + node, + origco, + use_origco, + srd->ray_start, + srd->ray_normal, + &srd->depth, + &srd->dist_sq_to_ray)) { + srd->hit = true; + *tmin = srd->dist_sq_to_ray; + } } float SCULPT_raycast_init(ViewContext *vc, @@ -7546,26 +7627,30 @@ bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mouse[2]) } } - if (!hit) { - if (ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) { - SculptFindNearestToRayData srd = { - .original = original, - .ss = ob->sculpt, - .hit = false, - .ray_start = ray_start, - .ray_normal = ray_normal, - .depth = FLT_MAX, - .dist_sq_to_ray = FLT_MAX, - }; - BKE_pbvh_find_nearest_to_ray( - ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original); - if (srd.hit) { - hit = true; - copy_v3_v3(out, ray_normal); - mul_v3_fl(out, srd.depth); - add_v3_v3(out, ray_start); - } - } + if (hit) { + return hit; + } + + if (!ELEM(brush->falloff_shape, PAINT_FALLOFF_SHAPE_TUBE)) { + return hit; + } + + SculptFindNearestToRayData srd = { + .original = original, + .ss = ob->sculpt, + .hit = false, + .ray_start = ray_start, + .ray_normal = ray_normal, + .depth = FLT_MAX, + .dist_sq_to_ray = FLT_MAX, + }; + BKE_pbvh_find_nearest_to_ray( + ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original); + if (srd.hit) { + hit = true; + copy_v3_v3(out, ray_normal); + mul_v3_fl(out, srd.depth); + add_v3_v3(out, ray_start); } return hit; @@ -7748,19 +7833,20 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up bScreen *screen = WM_window_get_active_screen(win); LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { SpaceLink *sl = area->spacedata.first; - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - if (v3d != current_v3d) { - need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d); - } + if (sl->spacetype != SPACE_VIEW3D) { + continue; + } + View3D *v3d = (View3D *)sl; + if (v3d != current_v3d) { + need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, v3d); + } - /* Tag all 3D viewports for redraw now that we are done. Others - * viewports did not get a full redraw, and anti-aliasing for the - * current viewport was deactivated. */ - LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { - if (region->regiontype == RGN_TYPE_WINDOW) { - ED_region_tag_redraw(region); - } + /* Tag all 3D viewports for redraw now that we are done. Others + * viewports did not get a full redraw, and anti-aliasing for the + * current viewport was deactivated. */ + LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { + if (region->regiontype == RGN_TYPE_WINDOW) { + ED_region_tag_redraw(region); } } } @@ -7920,55 +8006,56 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str Sculpt *sd = CTX_data_tool_settings(C)->sculpt; /* Finished. */ - if (ss->cache) { - UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; - Brush *brush = BKE_paint_brush(&sd->paint); - BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */ - ups->draw_inverted = false; + if (!ss->cache) { + sculpt_brush_exit_tex(sd); + return; + } + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; + Brush *brush = BKE_paint_brush(&sd->paint); + BLI_assert(brush == ss->cache->brush); /* const, so we shouldn't change. */ + ups->draw_inverted = false; - SCULPT_stroke_modifiers_check(C, ob, brush); + SCULPT_stroke_modifiers_check(C, ob, brush); - /* Alt-Smooth. */ - if (ss->cache->alt_smooth) { - if (brush->sculpt_tool == SCULPT_TOOL_MASK) { - brush->mask_tool = ss->cache->saved_mask_brush_tool; - } - else if (ELEM(brush->sculpt_tool, - SCULPT_TOOL_SLIDE_RELAX, - SCULPT_TOOL_DRAW_FACE_SETS, - SCULPT_TOOL_PAINT, - SCULPT_TOOL_SMEAR)) { - /* Do nothing. */ - } - else { - BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size); - brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name); - if (brush) { - BKE_paint_brush_set(&sd->paint, brush); - } - } + /* Alt-Smooth. */ + if (ss->cache->alt_smooth) { + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + brush->mask_tool = ss->cache->saved_mask_brush_tool; } - - if (SCULPT_is_automasking_enabled(sd, ss, brush)) { - SCULPT_automasking_cache_free(ss->cache->automasking); + else if (ELEM(brush->sculpt_tool, + SCULPT_TOOL_SLIDE_RELAX, + SCULPT_TOOL_DRAW_FACE_SETS, + SCULPT_TOOL_PAINT, + SCULPT_TOOL_SMEAR)) { + /* Do nothing. */ } + else { + BKE_brush_size_set(scene, brush, ss->cache->saved_smooth_size); + brush = (Brush *)BKE_libblock_find_name(bmain, ID_BR, ss->cache->saved_active_brush_name); + if (brush) { + BKE_paint_brush_set(&sd->paint, brush); + } + } + } - BKE_pbvh_node_color_buffer_free(ss->pbvh); - SCULPT_cache_free(ss->cache); - ss->cache = NULL; + if (SCULPT_is_automasking_enabled(sd, ss, brush)) { + SCULPT_automasking_cache_free(ss->cache->automasking); + } - SCULPT_undo_push_end(); + BKE_pbvh_node_color_buffer_free(ss->pbvh); + SCULPT_cache_free(ss->cache); + ss->cache = NULL; - if (brush->sculpt_tool == SCULPT_TOOL_MASK) { - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); - } - else { - SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); - } + SCULPT_undo_push_end(); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + if (brush->sculpt_tool == SCULPT_TOOL_MASK) { + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_MASK); + } + else { + SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS); } + WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); sculpt_brush_exit_tex(sd); } @@ -8090,21 +8177,22 @@ static int sculpt_set_persistent_base_exec(bContext *C, wmOperator *UNUSED(op)) Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; - if (ss) { - SCULPT_vertex_random_access_ensure(ss); - BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); + if (!ss) { + return OPERATOR_FINISHED; + } + SCULPT_vertex_random_access_ensure(ss); + BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); - MEM_SAFE_FREE(ss->persistent_base); + MEM_SAFE_FREE(ss->persistent_base); - const int totvert = SCULPT_vertex_count_get(ss); - ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, - "layer persistent base"); + const int totvert = SCULPT_vertex_count_get(ss); + ss->persistent_base = MEM_mallocN(sizeof(SculptPersistentBase) * totvert, + "layer persistent base"); - for (int i = 0; i < totvert; i++) { - copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i)); - SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no); - ss->persistent_base[i].disp = 0.0f; - } + for (int i = 0; i < totvert; i++) { + copy_v3_v3(ss->persistent_base[i].co, SCULPT_vertex_co_get(ss, i)); + SCULPT_vertex_normal_get(ss, i, ss->persistent_base[i].no); + ss->persistent_base[i].disp = 0.0f; } return OPERATOR_FINISHED; @@ -8564,12 +8652,13 @@ void SCULPT_geometry_preview_lines_update(bContext *C, SculptSession *ss, float totpoints++; ss->preview_vert_index_list[totpoints] = to_v; totpoints++; - if (!BLI_BITMAP_TEST(visited_vertices, to_v)) { - BLI_BITMAP_ENABLE(visited_vertices, to_v); - const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); - if (len_squared_v3v3(brush_co, co) < radius * radius) { - BLI_gsqueue_push(not_visited_vertices, &to_v); - } + if (BLI_BITMAP_TEST(visited_vertices, to_v)) { + continue; + } + BLI_BITMAP_ENABLE(visited_vertices, to_v); + const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); + if (len_squared_v3v3(brush_co, co) < radius * radius) { + BLI_gsqueue_push(not_visited_vertices, &to_v); } } } @@ -9099,11 +9188,12 @@ static void do_mask_by_color_contiguous_update_nodes_cb( const float current_mask = *vd.mask; const float new_mask = data->mask_by_color_floodfill[vd.index]; *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); - if (current_mask != *vd.mask) { - update_node = true; - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (current_mask == *vd.mask) { + continue; + } + update_node = true; + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -9206,11 +9296,12 @@ static void do_mask_by_color_task_cb(void *__restrict userdata, const float new_mask = sculpt_mask_by_color_delta_get(active_color, vd.col, threshold, invert); *vd.mask = sculpt_mask_by_color_final_mask_get(current_mask, new_mask, invert, preserve_mask); - if (current_mask != *vd.mask) { - update_node = true; - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (current_mask == *vd.mask) { + continue; + } + update_node = true; + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index bb68ec56b25..5f5fb51d75f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -298,24 +298,26 @@ float *SCULPT_boundary_automasking_init(Object *ob, for (int propagation_it = 0; propagation_it < propagation_steps; propagation_it++) { for (int i = 0; i < totvert; i++) { - if (edge_distance[i] == EDGE_DISTANCE_INF) { - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { - if (edge_distance[ni.index] == propagation_it) { - edge_distance[i] = propagation_it + 1; - } + if (edge_distance[i] != EDGE_DISTANCE_INF) { + continue; + } + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) { + if (edge_distance[ni.index] == propagation_it) { + edge_distance[i] = propagation_it + 1; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } } for (int i = 0; i < totvert; i++) { - if (edge_distance[i] != EDGE_DISTANCE_INF) { - const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps); - const float edge_boundary_automask = pow2f(p); - automask_factor[i] *= (1.0f - edge_boundary_automask); + if (edge_distance[i] == EDGE_DISTANCE_INF) { + continue; } + const float p = 1.0f - ((float)edge_distance[i] / (float)propagation_steps); + const float edge_boundary_automask = pow2f(p); + automask_factor[i] *= (1.0f - edge_boundary_automask); } MEM_SAFE_FREE(edge_distance); diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.c b/source/blender/editors/sculpt_paint/sculpt_boundary.c index 0cfb6f17adb..fca19c04b98 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.c +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.c @@ -227,19 +227,19 @@ static bool boundary_floodfill_cb( { BoundaryFloodFillData *data = userdata; SculptBoundary *boundary = data->boundary; - if (SCULPT_vertex_is_boundary(ss, to_v)) { - const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v), - SCULPT_vertex_co_get(ss, to_v)); - const float distance_boundary_to_dst = boundary->distance ? - boundary->distance[from_v] + edge_len : - 0.0f; - sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices); - if (!is_duplicate) { - sculpt_boundary_preview_edge_add(boundary, from_v, to_v); - } - return sculpt_boundary_is_vertex_in_editable_boundary(ss, to_v); + if (!SCULPT_vertex_is_boundary(ss, to_v)) { + return false; + } + const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v), + SCULPT_vertex_co_get(ss, to_v)); + const float distance_boundary_to_dst = boundary->distance ? + boundary->distance[from_v] + edge_len : + 0.0f; + sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices); + if (!is_duplicate) { + sculpt_boundary_preview_edge_add(boundary, from_v, to_v); } - return false; + return sculpt_boundary_is_vertex_in_editable_boundary(ss, to_v); } static void sculpt_boundary_indices_init(SculptSession *ss, @@ -360,49 +360,50 @@ static void sculpt_boundary_edit_data_init(SculptSession *ss, SculptVertexNeighborIter ni; SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { const bool is_visible = SCULPT_vertex_visible_get(ss, ni.index); - if (is_visible && - boundary->edit_info[ni.index].num_propagation_steps == BOUNDARY_STEPS_NONE) { - boundary->edit_info[ni.index].original_vertex = - boundary->edit_info[from_v].original_vertex; + if (!is_visible || + boundary->edit_info[ni.index].num_propagation_steps != BOUNDARY_STEPS_NONE) { + continue; + } + boundary->edit_info[ni.index].original_vertex = + boundary->edit_info[from_v].original_vertex; - BLI_BITMAP_ENABLE(visited_vertices, ni.index); + BLI_BITMAP_ENABLE(visited_vertices, ni.index); - if (ni.is_duplicate) { - /* Grids duplicates handling. */ - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps; - } - else { - boundary->edit_info[ni.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps + 1; - - BLI_gsqueue_push(next_iteration, &ni.index); - - /* When copying the data to the neighbor for the next iteration, it has to be copied to - * all its duplicates too. This is because it is not possible to know if the updated - * neighbor or one if its uninitialized duplicates is going to come first in order to - * copy the data in the from_v neighbor iterator. */ - if (has_duplicates) { - SculptVertexNeighborIter ni_duplis; - SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) { - if (ni_duplis.is_duplicate) { - boundary->edit_info[ni_duplis.index].original_vertex = - boundary->edit_info[from_v].original_vertex; - boundary->edit_info[ni_duplis.index].num_propagation_steps = - boundary->edit_info[from_v].num_propagation_steps + 1; - } + if (ni.is_duplicate) { + /* Grids duplicates handling. */ + boundary->edit_info[ni.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps; + } + else { + boundary->edit_info[ni.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps + 1; + + BLI_gsqueue_push(next_iteration, &ni.index); + + /* When copying the data to the neighbor for the next iteration, it has to be copied to + * all its duplicates too. This is because it is not possible to know if the updated + * neighbor or one if its uninitialized duplicates is going to come first in order to + * copy the data in the from_v neighbor iterator. */ + if (has_duplicates) { + SculptVertexNeighborIter ni_duplis; + SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, ni.index, ni_duplis) { + if (ni_duplis.is_duplicate) { + boundary->edit_info[ni_duplis.index].original_vertex = + boundary->edit_info[from_v].original_vertex; + boundary->edit_info[ni_duplis.index].num_propagation_steps = + boundary->edit_info[from_v].num_propagation_steps + 1; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni_duplis); + } - /* Check the distance using the vertex that was propagated from the initial vertex that - * was used to initialize the boundary. */ - if (boundary->edit_info[from_v].original_vertex == initial_vertex) { - boundary->pivot_vertex = ni.index; - copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index)); - accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), - SCULPT_vertex_co_get(ss, ni.index)); - } + /* Check the distance using the vertex that was propagated from the initial vertex that + * was used to initialize the boundary. */ + if (boundary->edit_info[from_v].original_vertex == initial_vertex) { + boundary->pivot_vertex = ni.index; + copy_v3_v3(boundary->initial_pivot_position, SCULPT_vertex_co_get(ss, ni.index)); + accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v), + SCULPT_vertex_co_get(ss, ni.index)); } } } @@ -552,28 +553,30 @@ static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *bo totvert, 3 * sizeof(float), "pivot positions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) { - float dir[3]; - float normal[3]; - SCULPT_vertex_normal_get(ss, i, normal); - sub_v3_v3v3(dir, - SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), - SCULPT_vertex_co_get(ss, i)); - cross_v3_v3v3( - boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal); - normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); - copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex], - SCULPT_vertex_co_get(ss, i)); + if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { + continue; } + float dir[3]; + float normal[3]; + SCULPT_vertex_normal_get(ss, i, normal); + sub_v3_v3v3(dir, + SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), + SCULPT_vertex_co_get(ss, i)); + cross_v3_v3v3( + boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal); + normalize_v3(boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); + copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex], + SCULPT_vertex_co_get(ss, i)); } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) { - copy_v3_v3(boundary->bend.pivot_positions[i], - boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]); - copy_v3_v3(boundary->bend.pivot_rotation_axis[i], - boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + continue; } + copy_v3_v3(boundary->bend.pivot_positions[i], + boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]); + copy_v3_v3(boundary->bend.pivot_rotation_axis[i], + boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]); } } @@ -583,19 +586,20 @@ static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *b boundary->slide.directions = MEM_calloc_arrayN(totvert, 3 * sizeof(float), "slide directions"); for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps == boundary->max_propagation_steps) { - sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex], - SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), - SCULPT_vertex_co_get(ss, i)); - normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) { } + sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex], + SCULPT_vertex_co_get(ss, boundary->edit_info[i].original_vertex), + SCULPT_vertex_co_get(ss, i)); + normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]); } for (int i = 0; i < totvert; i++) { - if (boundary->edit_info[i].num_propagation_steps != BOUNDARY_STEPS_NONE) { - copy_v3_v3(boundary->slide.directions[i], - boundary->slide.directions[boundary->edit_info[i].original_vertex]); + if (boundary->edit_info[i].num_propagation_steps == BOUNDARY_STEPS_NONE) { + continue; } + copy_v3_v3(boundary->slide.directions[i], + boundary->slide.directions[boundary->edit_info[i].original_vertex]); } } @@ -662,24 +666,27 @@ static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float t_orig_co[3]; - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]); - rotate_v3_v3v3fl(target_co, - t_orig_co, - boundary->bend.pivot_rotation_axis[vd.index], - angle * boundary->edit_info[vd.index].strength_factor * mask * automask); - add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float t_orig_co[3]; + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]); + rotate_v3_v3v3fl(target_co, + t_orig_co, + boundary->bend.pivot_rotation_axis[vd.index], + angle * boundary->edit_info[vd.index].strength_factor * mask * automask); + add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -708,22 +715,25 @@ static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - boundary->slide.directions[vd.index], - boundary->edit_info[vd.index].strength_factor * disp * mask * automask * - strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + boundary->slide.directions[vd.index], + boundary->edit_info[vd.index].strength_factor * disp * mask * automask * + strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -752,24 +762,27 @@ static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float normal[3]; - normal_short_to_float_v3(normal, orig_data.no); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - normal, - boundary->edit_info[vd.index].strength_factor * disp * mask * automask * - strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float normal[3]; + normal_short_to_float_v3(normal, orig_data.no); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + normal, + boundary->edit_info[vd.index].strength_factor * disp * mask * automask * + strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -796,21 +809,24 @@ static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - madd_v3_v3v3fl(target_co, - orig_data.co, - ss->cache->grab_delta_symmetry, - boundary->edit_info[vd.index].strength_factor * mask * automask * strength); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + madd_v3_v3v3fl(target_co, + orig_data.co, + ss->cache->grab_delta_symmetry, + boundary->edit_info[vd.index].strength_factor * mask * automask * strength); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } @@ -845,24 +861,27 @@ static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + if (boundary->edit_info[vd.index].num_propagation_steps == -1) { + continue; + } - if (boundary->edit_info[vd.index].num_propagation_steps != -1) { - SCULPT_orig_vert_data_update(&orig_data, &vd); - if (SCULPT_check_vertex_pivot_symmetry( - orig_data.co, boundary->initial_vertex_position, symm)) { - const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; - const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); - float t_orig_co[3]; - float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); - sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position); - rotate_v3_v3v3fl(target_co, - t_orig_co, - boundary->twist.rotation_axis, - angle * mask * automask * boundary->edit_info[vd.index].strength_factor); - add_v3_v3(target_co, boundary->twist.pivot_position); - } + SCULPT_orig_vert_data_update(&orig_data, &vd); + if (!SCULPT_check_vertex_pivot_symmetry( + orig_data.co, boundary->initial_vertex_position, symm)) { + continue; } + const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f; + const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index); + float t_orig_co[3]; + float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); + sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position); + rotate_v3_v3v3fl(target_co, + t_orig_co, + boundary->twist.rotation_axis, + angle * mask * automask * boundary->edit_info[vd.index].strength_factor); + add_v3_v3(target_co, boundary->twist.pivot_position); + if (vd.mvert) { vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index c97f31fa682..16d10f6d6bb 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -540,97 +540,98 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, vertex_gravity, vd.index); /* When using the plane falloff mode the falloff is not constrained by the brush radius. */ - if (sculpt_brush_test_sq_fn(&test, current_vertex_location) || use_falloff_plane) { - - float dist = sqrtf(test.dist); + if (!sculpt_brush_test_sq_fn(&test, current_vertex_location) && !use_falloff_plane) { + continue; + } - if (use_falloff_plane) { - dist = dist_to_plane_v3(current_vertex_location, deform_plane); - } + float dist = sqrtf(test.dist); - const float fade = sim_factor * bstrength * - SCULPT_brush_strength_factor(ss, - brush, - current_vertex_location, - dist, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float brush_disp[3]; - float normal[3]; - if (vd.no) { - normal_short_to_float_v3(normal, vd.no); - } - else { - copy_v3_v3(normal, vd.fno); - } + if (use_falloff_plane) { + dist = dist_to_plane_v3(current_vertex_location, deform_plane); + } - switch (brush->cloth_deform_type) { - case BRUSH_CLOTH_DEFORM_DRAG: - sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location); - normalize_v3(brush_disp); - mul_v3_v3fl(force, brush_disp, fade); - break; - case BRUSH_CLOTH_DEFORM_PUSH: - /* Invert the fade to push inwards. */ - mul_v3_v3fl(force, offset, -fade); - break; - case BRUSH_CLOTH_DEFORM_GRAB: - madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], - cloth_sim->init_pos[vd.index], - ss->cache->grab_delta_symmetry, - fade); - if (use_falloff_plane) { - cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); - } - else { - cloth_sim->deformation_strength[vd.index] = 1.0f; - } - zero_v3(force); - break; - case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: - copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]); - madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade); - cloth_sim->deformation_strength[vd.index] = fade; - zero_v3(force); - break; - case BRUSH_CLOTH_DEFORM_PINCH_POINT: - if (use_falloff_plane) { - float distance = dist_signed_to_plane_v3(vd.co, deform_plane); - copy_v3_v3(brush_disp, plane_normal); - mul_v3_fl(brush_disp, -distance); - } - else { - sub_v3_v3v3(brush_disp, ss->cache->location, vd.co); - } - normalize_v3(brush_disp); - mul_v3_v3fl(force, brush_disp, fade); - break; - case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: { - float disp_center[3]; - float x_disp[3]; - float z_disp[3]; - sub_v3_v3v3(disp_center, ss->cache->location, vd.co); - normalize_v3(disp_center); - mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); - mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); - add_v3_v3v3(disp_center, x_disp, z_disp); - mul_v3_v3fl(force, disp_center, fade); - } break; - case BRUSH_CLOTH_DEFORM_INFLATE: - mul_v3_v3fl(force, normal, fade); - break; - case BRUSH_CLOTH_DEFORM_EXPAND: - cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f; - zero_v3(force); - break; - } + const float fade = sim_factor * bstrength * + SCULPT_brush_strength_factor(ss, + brush, + current_vertex_location, + dist, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float brush_disp[3]; + float normal[3]; + if (vd.no) { + normal_short_to_float_v3(normal, vd.no); + } + else { + copy_v3_v3(normal, vd.fno); + } - cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); + switch (brush->cloth_deform_type) { + case BRUSH_CLOTH_DEFORM_DRAG: + sub_v3_v3v3(brush_disp, ss->cache->location, ss->cache->last_location); + normalize_v3(brush_disp); + mul_v3_v3fl(force, brush_disp, fade); + break; + case BRUSH_CLOTH_DEFORM_PUSH: + /* Invert the fade to push inwards. */ + mul_v3_v3fl(force, offset, -fade); + break; + case BRUSH_CLOTH_DEFORM_GRAB: + madd_v3_v3v3fl(cloth_sim->deformation_pos[vd.index], + cloth_sim->init_pos[vd.index], + ss->cache->grab_delta_symmetry, + fade); + if (use_falloff_plane) { + cloth_sim->deformation_strength[vd.index] = clamp_f(fade, 0.0f, 1.0f); + } + else { + cloth_sim->deformation_strength[vd.index] = 1.0f; + } + zero_v3(force); + break; + case BRUSH_CLOTH_DEFORM_SNAKE_HOOK: + copy_v3_v3(cloth_sim->deformation_pos[vd.index], cloth_sim->pos[vd.index]); + madd_v3_v3fl(cloth_sim->deformation_pos[vd.index], ss->cache->grab_delta_symmetry, fade); + cloth_sim->deformation_strength[vd.index] = fade; + zero_v3(force); + break; + case BRUSH_CLOTH_DEFORM_PINCH_POINT: + if (use_falloff_plane) { + float distance = dist_signed_to_plane_v3(vd.co, deform_plane); + copy_v3_v3(brush_disp, plane_normal); + mul_v3_fl(brush_disp, -distance); + } + else { + sub_v3_v3v3(brush_disp, ss->cache->location, vd.co); + } + normalize_v3(brush_disp); + mul_v3_v3fl(force, brush_disp, fade); + break; + case BRUSH_CLOTH_DEFORM_PINCH_PERPENDICULAR: { + float disp_center[3]; + float x_disp[3]; + float z_disp[3]; + sub_v3_v3v3(disp_center, ss->cache->location, vd.co); + normalize_v3(disp_center); + mul_v3_v3fl(x_disp, x_object_space, dot_v3v3(disp_center, x_object_space)); + mul_v3_v3fl(z_disp, z_object_space, dot_v3v3(disp_center, z_object_space)); + add_v3_v3v3(disp_center, x_disp, z_disp); + mul_v3_v3fl(force, disp_center, fade); + } break; + case BRUSH_CLOTH_DEFORM_INFLATE: + mul_v3_v3fl(force, normal, fade); + break; + case BRUSH_CLOTH_DEFORM_EXPAND: + cloth_sim->length_constraint_tweak[vd.index] += fade * 0.1f; + zero_v3(force); + break; } + + cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index); } BKE_pbvh_vertex_iter_end; } @@ -644,17 +645,22 @@ static ListBase *cloth_brush_collider_cache_create(Depsgraph *depsgraph) DEG_ITER_OBJECT_FLAG_DUPLI) { CollisionModifierData *cmd = (CollisionModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Collision); - if (cmd && cmd->bvhtree) { - if (cache == NULL) { - cache = MEM_callocN(sizeof(ListBase), "ColliderCache array"); - } + if (!cmd) { + continue; + } - ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); - col->ob = ob; - col->collmd = cmd; - collision_move_object(cmd, 1.0, 0.0, true); - BLI_addtail(cache, col); + if (!cmd->bvhtree) { + continue; } + if (cache == NULL) { + cache = MEM_callocN(sizeof(ListBase), "ColliderCache array"); + } + + ColliderCache *col = MEM_callocN(sizeof(ColliderCache), "ColliderCache"); + col->ob = ob; + col->collmd = cmd; + collision_move_object(cmd, 1.0, 0.0, true); + BLI_addtail(cache, col); } DEG_OBJECT_ITER_END; return cache; @@ -734,26 +740,27 @@ static void cloth_brush_solve_collision(Object *object, &col, raycast_flag); - if (hit.index != -1) { - - float collision_disp[3]; - float movement_disp[3]; - mul_v3_v3fl(collision_disp, hit.no, 0.005f); - sub_v3_v3v3(movement_disp, pos_world_space, prev_pos_world_space); - float friction_plane[4]; - float pos_on_friction_plane[3]; - plane_from_point_normal_v3(friction_plane, hit.co, hit.no); - closest_to_plane_v3(pos_on_friction_plane, friction_plane, pos_world_space); - sub_v3_v3v3(movement_disp, pos_on_friction_plane, hit.co); - - /* TODO(pablodp606): This can be exposed in a brush/filter property as friction. */ - mul_v3_fl(movement_disp, 0.35f); - - copy_v3_v3(cloth_sim->pos[i], hit.co); - add_v3_v3(cloth_sim->pos[i], movement_disp); - add_v3_v3(cloth_sim->pos[i], collision_disp); - mul_v3_m4v3(cloth_sim->pos[i], obmat_inv, cloth_sim->pos[i]); + if (hit.index == -1) { + continue; } + + float collision_disp[3]; + float movement_disp[3]; + mul_v3_v3fl(collision_disp, hit.no, 0.005f); + sub_v3_v3v3(movement_disp, pos_world_space, prev_pos_world_space); + float friction_plane[4]; + float pos_on_friction_plane[3]; + plane_from_point_normal_v3(friction_plane, hit.co, hit.no); + closest_to_plane_v3(pos_on_friction_plane, friction_plane, pos_world_space); + sub_v3_v3v3(movement_disp, pos_on_friction_plane, hit.co); + + /* TODO(pablodp606): This can be exposed in a brush/filter property as friction. */ + mul_v3_fl(movement_disp, 0.35f); + + copy_v3_v3(cloth_sim->pos[i], hit.co); + add_v3_v3(cloth_sim->pos[i], movement_disp); + add_v3_v3(cloth_sim->pos[i], collision_disp); + mul_v3_m4v3(cloth_sim->pos[i], obmat_inv, cloth_sim->pos[i]); } } @@ -784,38 +791,40 @@ static void do_cloth_brush_solve_simulation_task_cb_ex( ss->cache ? cloth_brush_simulation_falloff_get( brush, ss->cache->radius, sim_location, cloth_sim->init_pos[vd.index]) : 1.0f; - if (sim_factor > 0.0f) { - int i = vd.index; - float temp[3]; - copy_v3_v3(temp, cloth_sim->pos[i]); + if (sim_factor <= 0.0f) { + continue; + } - mul_v3_fl(cloth_sim->acceleration[i], time_step); + int i = vd.index; + float temp[3]; + copy_v3_v3(temp, cloth_sim->pos[i]); - float pos_diff[3]; - sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]); - mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor); + mul_v3_fl(cloth_sim->acceleration[i], time_step); - const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) * - SCULPT_automasking_factor_get(automasking, ss, vd.index); + float pos_diff[3]; + sub_v3_v3v3(pos_diff, cloth_sim->pos[i], cloth_sim->prev_pos[i]); + mul_v3_fl(pos_diff, (1.0f - cloth_sim->damping) * sim_factor); - madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v); - madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); + const float mask_v = (1.0f - (vd.mask ? *vd.mask : 0.0f)) * + SCULPT_automasking_factor_get(automasking, ss, vd.index); - if (cloth_sim->collider_list != NULL) { - cloth_brush_solve_collision(data->ob, cloth_sim, i); - } + madd_v3_v3fl(cloth_sim->pos[i], pos_diff, mask_v); + madd_v3_v3fl(cloth_sim->pos[i], cloth_sim->acceleration[i], mask_v); - copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); + if (cloth_sim->collider_list != NULL) { + cloth_brush_solve_collision(data->ob, cloth_sim, i); + } - copy_v3_v3(cloth_sim->prev_pos[i], temp); - copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); - copy_v3_fl(cloth_sim->acceleration[i], 0.0f); + copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); - copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); + copy_v3_v3(cloth_sim->prev_pos[i], temp); + copy_v3_v3(cloth_sim->last_iteration_pos[i], cloth_sim->pos[i]); + copy_v3_fl(cloth_sim->acceleration[i], 0.0f); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 20d8e136d12..df03d2adeaf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -148,40 +148,42 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, float poly_center[3]; BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], mvert, poly_center); - if (sculpt_brush_test_sq_fn(&test, poly_center)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { - ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); - } + if (!sculpt_brush_test_sq_fn(&test, poly_center)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { + ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); } } } else if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) { { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - if (fade > 0.05f) { - SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + if (fade > 0.05f) { + SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); } } } @@ -214,23 +216,26 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) { + continue; + } - SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -582,44 +587,49 @@ static void sculpt_face_sets_init_flood_fill(Object *ob, int next_face_set = 1; for (int i = 0; i < totfaces; i++) { - if (!BLI_BITMAP_TEST(visited_faces, i)) { - GSQueue *queue; - queue = BLI_gsqueue_new(sizeof(int)); - - face_sets[i] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, i); - BLI_gsqueue_push(queue, &i); - - while (!BLI_gsqueue_is_empty(queue)) { - int from_f; - BLI_gsqueue_pop(queue, &from_f); - - BMFace *f, *f_neighbor; - BMEdge *ed; - BMIter iter_a, iter_b; - - f = BM_face_at_index(bm, from_f); - - BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { - if (f_neighbor != f) { - int neighbor_face_index = BM_elem_index_get(f_neighbor); - if (!BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) { - if (test(bm, f, ed, f_neighbor, threshold)) { - face_sets[neighbor_face_index] = next_face_set; - BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index); - BLI_gsqueue_push(queue, &neighbor_face_index); - } - } - } + if (BLI_BITMAP_TEST(visited_faces, i)) { + continue; + } + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(int)); + + face_sets[i] = next_face_set; + BLI_BITMAP_ENABLE(visited_faces, i); + BLI_gsqueue_push(queue, &i); + + while (!BLI_gsqueue_is_empty(queue)) { + int from_f; + BLI_gsqueue_pop(queue, &from_f); + + BMFace *f, *f_neighbor; + BMEdge *ed; + BMIter iter_a, iter_b; + + f = BM_face_at_index(bm, from_f); + + BM_ITER_ELEM (ed, &iter_a, f, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f_neighbor, &iter_b, ed, BM_FACES_OF_EDGE) { + if (f_neighbor == f) { + continue; } + int neighbor_face_index = BM_elem_index_get(f_neighbor); + if (BLI_BITMAP_TEST(visited_faces, neighbor_face_index)) { + continue; + } + if (!test(bm, f, ed, f_neighbor, threshold)) { + continue; + } + + face_sets[neighbor_face_index] = next_face_set; + BLI_BITMAP_ENABLE(visited_faces, neighbor_face_index); + BLI_gsqueue_push(queue, &neighbor_face_index); } } + } - next_face_set += 1; + next_face_set += 1; - BLI_gsqueue_free(queue); - } + BLI_gsqueue_free(queue); } MEM_SAFE_FREE(visited_faces); diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c index e47a94dff90..cfc31e1dcdd 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c @@ -88,38 +88,39 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - float normal[3]; - if (vd.no) { - normal_short_to_float_v3(normal, vd.no); - } - else { - copy_v3_v3(normal, vd.fno); - } - mul_v3_m4v3(local_co, mat, vd.co); - /* Use the brush falloff to weight the sampled normals. */ - const float fade = SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - /* Sample the normal and area of the +X and -X axis individually. */ - if (local_co[0] > 0.0f) { - madd_v3_v3fl(mssd->area_nos[0], normal, fade); - add_v3_v3(mssd->area_cos[0], vd.co); - mssd->area_count[0]++; - } - else { - madd_v3_v3fl(mssd->area_nos[1], normal, fade); - add_v3_v3(mssd->area_cos[1], vd.co); - mssd->area_count[1]++; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + float local_co[3]; + float normal[3]; + if (vd.no) { + normal_short_to_float_v3(normal, vd.no); + } + else { + copy_v3_v3(normal, vd.fno); + } + mul_v3_m4v3(local_co, mat, vd.co); + /* Use the brush falloff to weight the sampled normals. */ + const float fade = SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + /* Sample the normal and area of the +X and -X axis individually. */ + if (local_co[0] > 0.0f) { + madd_v3_v3fl(mssd->area_nos[0], normal, fade); + add_v3_v3(mssd->area_cos[0], vd.co); + mssd->area_count[0]++; + } + else { + madd_v3_v3fl(mssd->area_nos[1], normal, fade); + add_v3_v3(mssd->area_cos[1], vd.co); + mssd->area_count[1]++; } BKE_pbvh_vertex_iter_end; } @@ -168,56 +169,61 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - float local_co[3]; - bool deform = false; - - mul_v3_m4v3(local_co, mat, vd.co); - - if (local_co[0] > 0.0f) { - deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]); - } - else { - deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]); - } - - if (angle < 0.0f) { - deform = true; - } - - if (deform) { - float intr[3]; - float val[3]; - - if (local_co[0] > 0.0f) { - closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co); - } - else { - closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co); - } - - sub_v3_v3v3(val, intr, vd.co); - if (SCULPT_plane_trim(ss->cache, brush, val)) { - /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */ - /* This produces a not round brush tip. */ - local_co[1] *= 2.0f; - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - len_v3(local_co), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } - } - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + float local_co[3]; + bool deform = false; + + mul_v3_m4v3(local_co, mat, vd.co); + + if (local_co[0] > 0.0f) { + deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]); + } + else { + deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]); + } + + if (angle < 0.0f) { + deform = true; + } + + if (!deform) { + continue; + } + + float intr[3]; + float val[3]; + + if (local_co[0] > 0.0f) { + closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co); + } + else { + closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co); + } + + sub_v3_v3v3(val, intr, vd.co); + if (!SCULPT_plane_trim(ss->cache, brush, val)) { + continue; + } + /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */ + /* This produces a not round brush tip. */ + local_co[1] *= 2.0f; + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + len_v3(local_co), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + mul_v3_v3fl(proxy[vd.i], val, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c index 39320f3f558..5fdf8415f28 100644 --- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c +++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c @@ -87,24 +87,25 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float smooth_color[4]; - SCULPT_neighbor_color_average(ss, smooth_color, vd.index); - blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float smooth_color[4]; + SCULPT_neighbor_color_average(ss, smooth_color, vd.index); + blend_color_interpolate_float(vd.col, vd.col, smooth_color, fade); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -153,46 +154,49 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata, distance_to_stroke_location = sqrtf(test.dist); } - if (affect_vertex) { - float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - distance_to_stroke_location, - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - /* Density. */ - float noise = 1.0f; - const float density = ss->cache->paint_brush.density; - if (density < 1.0f) { - const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index); - if (hash_noise > density) { - noise = density * hash_noise; - fade = fade * noise; - } + if (!affect_vertex) { + continue; + } + + float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + distance_to_stroke_location, + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + /* Density. */ + float noise = 1.0f; + const float density = ss->cache->paint_brush.density; + if (density < 1.0f) { + const float hash_noise = BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index); + if (hash_noise > density) { + noise = density * hash_noise; + fade = fade * noise; } + } - /* Brush paint color, brush test falloff and flow. */ - float paint_color[4]; - float wet_mix_color[4]; - float buffer_color[4]; + /* Brush paint color, brush test falloff and flow. */ + float paint_color[4]; + float wet_mix_color[4]; + float buffer_color[4]; - mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow); - mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); + mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow); + mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow); - /* Interpolate with the wet_mix color for wet paint mixing. */ - blend_color_interpolate_float( - paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix); - blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color); + /* Interpolate with the wet_mix color for wet paint mixing. */ + blend_color_interpolate_float( + paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix); + blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color); - /* Final mix over the original color using brush alpha. */ - mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); + /* Final mix over the original color using brush alpha. */ + mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha); + + IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); - IMB_blend_color_float(vd.col, orig_data.col, buffer_color, brush->blend); - } CLAMP4(vd.col, 0.0f, 1.0f); if (vd.mvert) { @@ -225,10 +229,12 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - add_v4_v4(swptd->color, vd.col); - swptd->tot_samples++; + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; } + + add_v4_v4(swptd->color, vd.col); + swptd->tot_samples++; } BKE_pbvh_vertex_iter_end; } @@ -380,59 +386,61 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float current_disp[3]; - float current_disp_norm[3]; - float interp_color[4]; - copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); - - switch (brush->smear_deform_type) { - case BRUSH_SMEAR_DEFORM_DRAG: - sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); - break; - case BRUSH_SMEAR_DEFORM_PINCH: - sub_v3_v3v3(current_disp, ss->cache->location, vd.co); - break; - case BRUSH_SMEAR_DEFORM_EXPAND: - sub_v3_v3v3(current_disp, vd.co, ss->cache->location); - break; - } - normalize_v3_v3(current_disp_norm, current_disp); - mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); - - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { - float vertex_disp[3]; - float vertex_disp_norm[3]; - sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); - const float *neighbor_color = ss->cache->prev_colors[ni.index]; - normalize_v3_v3(vertex_disp_norm, vertex_disp); - if (dot_v3v3(current_disp_norm, vertex_disp_norm) < 0.0f) { - const float color_interp = clamp_f( - -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); - float color_mix[4]; - copy_v4_v4(color_mix, neighbor_color); - mul_v4_fl(color_mix, color_interp * fade); - blend_color_mix_float(interp_color, interp_color, color_mix); - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float current_disp[3]; + float current_disp_norm[3]; + float interp_color[4]; + copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]); + + switch (brush->smear_deform_type) { + case BRUSH_SMEAR_DEFORM_DRAG: + sub_v3_v3v3(current_disp, ss->cache->location, ss->cache->last_location); + break; + case BRUSH_SMEAR_DEFORM_PINCH: + sub_v3_v3v3(current_disp, ss->cache->location, vd.co); + break; + case BRUSH_SMEAR_DEFORM_EXPAND: + sub_v3_v3v3(current_disp, vd.co, ss->cache->location); + break; + } + normalize_v3_v3(current_disp_norm, current_disp); + mul_v3_v3fl(current_disp, current_disp_norm, ss->cache->bstrength); + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd.index, ni) { + float vertex_disp[3]; + float vertex_disp_norm[3]; + sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co); + const float *neighbor_color = ss->cache->prev_colors[ni.index]; + normalize_v3_v3(vertex_disp_norm, vertex_disp); + if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) { + continue; } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + const float color_interp = clamp_f( + -dot_v3v3(current_disp_norm, vertex_disp_norm), 0.0f, 1.0f); + float color_mix[4]; + copy_v4_v4(color_mix, neighbor_color); + mul_v4_fl(color_mix, color_interp * fade); + blend_color_mix_float(interp_color, interp_color, color_mix); + } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); - blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); + blend_color_interpolate_float(vd.col, ss->cache->prev_colors[vd.index], interp_color, fade); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index f9ccbbb849c..a85f805894b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -490,50 +490,52 @@ static bool pose_face_sets_floodfill_cb( is_vertex_valid = SCULPT_vertex_has_face_set(ss, index, data->current_face_set); } - if (is_vertex_valid) { - - if (!BLI_BITMAP_TEST(data->is_weighted, index)) { - data->pose_factor[index] = 1.0f; - BLI_BITMAP_ENABLE(data->is_weighted, index); - visit_next = true; - } - - /* Fallback origin accumulation. */ - if (symmetry_check) { - add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index)); - data->fallback_count++; - } - - if (symmetry_check && !SCULPT_vertex_has_unique_face_set(ss, index)) { + if (!is_vertex_valid) { + return visit_next; + } - /* We only add coordinates for calculating the origin when it is possible to go from this - * vertex to another vertex in a valid face set for the next iteration. */ - bool count_as_boundary = false; + if (!BLI_BITMAP_TEST(data->is_weighted, index)) { + data->pose_factor[index] = 1.0f; + BLI_BITMAP_ENABLE(data->is_weighted, index); + visit_next = true; + } - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { - int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index); + /* Fallback origin accumulation. */ + if (symmetry_check) { + add_v3_v3(data->fallback_origin, SCULPT_vertex_co_get(ss, index)); + data->fallback_count++; + } - /* Check if we can get a valid face set for the next iteration from this neighbor. */ - if (SCULPT_vertex_has_unique_face_set(ss, ni.index) && - !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) { - if (!data->next_face_set_found) { - data->next_face_set = next_face_set_candidate; - data->next_vertex = ni.index; - data->next_face_set_found = true; - } - count_as_boundary = true; - } - } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + if (!symmetry_check || SCULPT_vertex_has_unique_face_set(ss, index)) { + return visit_next; + } - /* Origin accumulation. */ - if (count_as_boundary) { - add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index)); - data->tot_co++; + /* We only add coordinates for calculating the origin when it is possible to go from this + * vertex to another vertex in a valid face set for the next iteration. */ + bool count_as_boundary = false; + + SculptVertexNeighborIter ni; + SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) { + int next_face_set_candidate = SCULPT_vertex_face_set_get(ss, ni.index); + + /* Check if we can get a valid face set for the next iteration from this neighbor. */ + if (SCULPT_vertex_has_unique_face_set(ss, ni.index) && + !BLI_gset_haskey(data->visited_face_sets, POINTER_FROM_INT(next_face_set_candidate))) { + if (!data->next_face_set_found) { + data->next_face_set = next_face_set_candidate; + data->next_vertex = ni.index; + data->next_face_set_found = true; } + count_as_boundary = true; } } + SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); + + /* Origin accumulation. */ + if (count_as_boundary) { + add_v3_v3(data->pose_origin, SCULPT_vertex_co_get(ss, index)); + data->tot_co++; + } return visit_next; } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 87ee7480c92..4c0795eb0f7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -231,24 +231,26 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float disp[3]; - madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); - SCULPT_clip(sd, ss, vd.co, disp); - - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); + SCULPT_clip(sd, ss, vd.co, disp); + + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -312,33 +314,34 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata, BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor( - ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), - vd.index, - thread_id); - if (smooth_mask) { - float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; - val *= fade * bstrength; - *vd.mask += val; - CLAMP(*vd.mask, 0.0f, 1.0f); - } - else { - float avg[3], val[3]; - SCULPT_neighbor_coords_average_interior(ss, avg, vd.index); - sub_v3_v3v3(val, avg, vd.co); - madd_v3_v3v3fl(val, vd.co, val, fade); - SCULPT_clip(sd, ss, vd.co, val); - } - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor( + ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), + vd.index, + thread_id); + if (smooth_mask) { + float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; + val *= fade * bstrength; + *vd.mask += val; + CLAMP(*vd.mask, 0.0f, 1.0f); + } + else { + float avg[3], val[3]; + SCULPT_neighbor_coords_average_interior(ss, avg, vd.index); + sub_v3_v3v3(val, avg, vd.co); + madd_v3_v3v3fl(val, vd.co, val, fade); + SCULPT_clip(sd, ss, vd.co, val); + } + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } } BKE_pbvh_vertex_iter_end; @@ -473,32 +476,28 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_data, &vd); - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - - float disp[3]; - SCULPT_surface_smooth_laplacian_step(ss, - disp, - vd.co, - ss->cache->surface_smooth_laplacian_disp, - vd.index, - orig_data.co, - alpha); - madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); - if (vd.mvert) { - vd.mvert->flag |= ME_VERT_PBVH_UPDATE; - } + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; + } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + + float disp[3]; + SCULPT_surface_smooth_laplacian_step( + ss, disp, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, orig_data.co, alpha); + madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); + if (vd.mvert) { + vd.mvert->flag |= ME_VERT_PBVH_UPDATE; } - BKE_pbvh_vertex_iter_end; } + BKE_pbvh_vertex_iter_end; } static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( @@ -519,19 +518,20 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { - if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - vd.mask ? *vd.mask : 0.0f, - vd.index, - thread_id); - SCULPT_surface_smooth_displace_step( - ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); + if (!sculpt_brush_test_sq_fn(&test, vd.co)) { + continue; } + const float fade = bstrength * SCULPT_brush_strength_factor(ss, + brush, + vd.co, + sqrtf(test.dist), + vd.no, + vd.fno, + vd.mask ? *vd.mask : 0.0f, + vd.index, + thread_id); + SCULPT_surface_smooth_displace_step( + ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); } BKE_pbvh_vertex_iter_end; } |