diff options
Diffstat (limited to 'source/blender/editors/sculpt_paint/sculpt.c')
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 2711 |
1 files changed, 1401 insertions, 1310 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; |