diff --git a/source/blender/blenkernel/BKE_pbvh_api.hh b/source/blender/blenkernel/BKE_pbvh_api.hh index 6695b3c73c3..7f2f4fbef9b 100644 --- a/source/blender/blenkernel/BKE_pbvh_api.hh +++ b/source/blender/blenkernel/BKE_pbvh_api.hh @@ -295,7 +295,6 @@ void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked); bool BKE_pbvh_node_fully_unmasked_get(const PBVHNode *node); void BKE_pbvh_mark_rebuild_pixels(PBVH *pbvh); -void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, PBVHVertRef vertex); blender::Span BKE_pbvh_node_get_grid_indices(const PBVHNode &node); @@ -515,13 +514,6 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node, float (**r_orco_coords)[3], BMVert ***r_orco_verts); -/** - * \note doing a full search on all vertices here seems expensive, - * however this is important to avoid having to recalculate bound-box & sync the buffers to the - * GPU (which is far more expensive!) See: #47232. - */ -bool BKE_pbvh_node_has_vert_with_normal_update_tag(PBVH *pbvh, PBVHNode *node); - bool pbvh_has_mask(const PBVH *pbvh); bool pbvh_has_face_sets(PBVH *pbvh); diff --git a/source/blender/blenkernel/intern/pbvh.cc b/source/blender/blenkernel/intern/pbvh.cc index 0c211bb088a..76dab77f315 100644 --- a/source/blender/blenkernel/intern/pbvh.cc +++ b/source/blender/blenkernel/intern/pbvh.cc @@ -14,6 +14,7 @@ #include "BLI_bit_span_ops.hh" #include "BLI_bitmap.h" #include "BLI_bounds.hh" +#include "BLI_enumerable_thread_specific.hh" #include "BLI_math_geom.h" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" @@ -723,7 +724,7 @@ PBVH *build_mesh(Mesh *mesh) update_mesh_pointers(pbvh.get(), mesh); const Span tri_faces = pbvh->corner_tri_faces; - pbvh->vert_bitmap = blender::Array(totvert, false); + Array vert_bitmap(totvert, false); pbvh->totvert = totvert; #ifdef TEST_PBVH_FACE_SPLIT @@ -768,7 +769,7 @@ PBVH *build_mesh(Mesh *mesh) hide_poly, material_index, sharp_face, - pbvh->vert_bitmap, + vert_bitmap, &cb, prim_bounds, corner_tris_num); @@ -778,9 +779,6 @@ PBVH *build_mesh(Mesh *mesh) #endif } - /* Clear the bitmap so it can be used as an update tag later on. */ - pbvh->vert_bitmap.fill(false); - BKE_pbvh_update_active_vcol(pbvh.get(), mesh); #ifdef VALIDATE_UNIQUE_NODE_FACES @@ -1130,65 +1128,124 @@ static bool update_search(PBVHNode *node, const int flag) } static void normals_calc_faces(const Span positions, - const blender::OffsetIndices faces, + const OffsetIndices faces, const Span corner_verts, - const Span mask, + const Span face_indices, MutableSpan face_normals) { - threading::parallel_for(mask.index_range(), 512, [&](const IndexRange range) { - for (const int i : mask.slice(range)) { - face_normals[i] = mesh::face_normal_calc(positions, corner_verts.slice(faces[i])); + for (const int i : face_indices) { + face_normals[i] = mesh::face_normal_calc(positions, corner_verts.slice(faces[i])); + } +} + +static void calc_boundary_face_normals(const Span positions, + const OffsetIndices faces, + const Span corner_verts, + const Span face_indices, + MutableSpan face_normals) +{ + threading::parallel_for(face_indices.index_range(), 512, [&](const IndexRange range) { + normals_calc_faces(positions, faces, corner_verts, face_indices.slice(range), face_normals); + }); +} + +static void calc_node_face_normals(const Span positions, + const OffsetIndices faces, + const Span corner_verts, + const PBVH &pbvh, + const Span nodes, + MutableSpan face_normals) +{ + threading::EnumerableThreadSpecific> all_index_data; + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + Vector &node_faces = all_index_data.local(); + for (const PBVHNode *node : nodes.slice(range)) { + normals_calc_faces(positions, + faces, + corner_verts, + node_face_indices_calc_mesh(pbvh, *node, node_faces), + face_normals); } }); } -static void normals_calc_verts_simple(const blender::GroupedSpan vert_to_face_map, +static void normals_calc_verts_simple(const GroupedSpan vert_to_face_map, const Span face_normals, - const Span mask, + const Span verts, MutableSpan vert_normals) { - threading::parallel_for(mask.index_range(), 1024, [&](const IndexRange range) { - for (const int vert : mask.slice(range)) { - float3 normal(0.0f); - for (const int face : vert_to_face_map[vert]) { - normal += face_normals[face]; - } - vert_normals[vert] = math::normalize(normal); + for (const int vert : verts) { + float3 normal(0.0f); + for (const int face : vert_to_face_map[vert]) { + normal += face_normals[face]; + } + vert_normals[vert] = math::normalize(normal); + } +} + +static void calc_boundary_vert_normals(const GroupedSpan vert_to_face_map, + const Span face_normals, + const Span verts, + MutableSpan vert_normals) +{ + threading::parallel_for(verts.index_range(), 1024, [&](const IndexRange range) { + normals_calc_verts_simple(vert_to_face_map, face_normals, verts.slice(range), vert_normals); + }); +} + +static void calc_node_vert_normals(const GroupedSpan vert_to_face_map, + const Span face_normals, + const Span nodes, + MutableSpan vert_normals) +{ + threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) { + for (const PBVHNode *node : nodes.slice(range)) { + normals_calc_verts_simple(vert_to_face_map, + face_normals, + node->vert_indices.as_span().take_front(node->uniq_verts), + vert_normals); } }); } -static void pbvh_faces_update_normals(PBVH &pbvh, Span nodes, Mesh &mesh) +static void update_normals_faces(PBVH &pbvh, Span nodes, Mesh &mesh) { + /* Position changes are tracked on a per-node level, so all the vertex and face normals for every + * affected node are recalculated. However, the additional complexity comes from the fact that + * changing vertex normals also changes surrounding face normals. Those changed face normals then + * change the normals of all connected vertices, which can be in other nodes. So the set of + * vertices that need recalculated normals can propagate into unchanged/untagged PBVH nodes. + * + * Currently we have no good way of finding neighboring PBVH nodes, so we use the vertex to + * face topology map to find the neighboring vertices that need normal recalculation. + * + * Those boundary face and vertex indices are deduplicated with #VectorSet in order to avoid + * duplicate work recalculation for the same vertex, and to make parallel storage for vertices + * during reclculation thread-safe. */ const Span positions = pbvh.vert_positions; const OffsetIndices faces = mesh.faces(); const Span corner_verts = mesh.corner_verts(); - MutableSpan update_tags = pbvh.vert_bitmap; - - VectorSet faces_to_update; + VectorSet boundary_faces; for (const PBVHNode *node : nodes) { - for (const int vert : node->vert_indices.as_span().take_front(node->uniq_verts)) { - if (update_tags[vert]) { - faces_to_update.add_multiple(pbvh.vert_to_face_map[vert]); - } + for (const int vert : node->vert_indices.as_span().drop_front(node->uniq_verts)) { + boundary_faces.add_multiple(pbvh.vert_to_face_map[vert]); } } - if (faces_to_update.is_empty()) { - return; - } - - VectorSet verts_to_update; + VectorSet boundary_verts; threading::parallel_invoke( [&]() { if (pbvh.deformed) { - normals_calc_faces( - positions, faces, corner_verts, faces_to_update, pbvh.face_normals_deformed); + calc_node_face_normals( + positions, faces, corner_verts, pbvh, nodes, pbvh.face_normals_deformed); + calc_boundary_face_normals( + positions, faces, corner_verts, boundary_faces, pbvh.face_normals_deformed); } else { mesh.runtime->face_normals_cache.update([&](Vector &r_data) { - normals_calc_faces(positions, faces, corner_verts, faces_to_update, r_data); + calc_node_face_normals(positions, faces, corner_verts, pbvh, nodes, r_data); + calc_boundary_face_normals(positions, faces, corner_verts, boundary_faces, r_data); }); /* #SharedCache::update() reallocates cached vectors if they were shared initially. */ pbvh.face_normals = mesh.runtime->face_normals_cache.data(); @@ -1196,29 +1253,29 @@ static void pbvh_faces_update_normals(PBVH &pbvh, Span nodes, Mesh & }, [&]() { /* Update all normals connected to affected faces, even if not explicitly tagged. */ - verts_to_update.reserve(faces_to_update.size()); - for (const int face : faces_to_update) { - verts_to_update.add_multiple(corner_verts.slice(faces[face])); - } - - for (const int vert : verts_to_update) { - update_tags[vert] = false; - } - for (PBVHNode *node : nodes) { - node->flag &= ~PBVH_UpdateNormals; + boundary_verts.reserve(boundary_faces.size()); + for (const int face : boundary_faces) { + boundary_verts.add_multiple(corner_verts.slice(faces[face])); } }); if (pbvh.deformed) { - normals_calc_verts_simple( - pbvh.vert_to_face_map, pbvh.face_normals, verts_to_update, pbvh.vert_normals_deformed); + calc_node_vert_normals( + pbvh.vert_to_face_map, pbvh.face_normals, nodes, pbvh.vert_normals_deformed); + calc_boundary_vert_normals( + pbvh.vert_to_face_map, pbvh.face_normals, boundary_verts, pbvh.vert_normals_deformed); } else { mesh.runtime->vert_normals_cache.update([&](Vector &r_data) { - normals_calc_verts_simple(pbvh.vert_to_face_map, pbvh.face_normals, verts_to_update, r_data); + calc_node_vert_normals(pbvh.vert_to_face_map, pbvh.face_normals, nodes, r_data); + calc_boundary_vert_normals(pbvh.vert_to_face_map, pbvh.face_normals, boundary_verts, r_data); }); pbvh.vert_normals = mesh.runtime->vert_normals_cache.data(); } + + for (PBVHNode *node : nodes) { + node->flag &= ~PBVH_UpdateNormals; + } } void update_normals(PBVH &pbvh, SubdivCCG *subdiv_ccg) @@ -1230,7 +1287,7 @@ void update_normals(PBVH &pbvh, SubdivCCG *subdiv_ccg) bmesh_normals_update(nodes); } else if (pbvh.header.type == PBVH_FACES) { - pbvh_faces_update_normals(pbvh, nodes, *pbvh.mesh); + update_normals_faces(pbvh, nodes, *pbvh.mesh); } else if (pbvh.header.type == PBVH_GRIDS) { IndexMaskMemory memory; @@ -1729,12 +1786,6 @@ bool BKE_pbvh_node_fully_unmasked_get(const PBVHNode *node) return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyUnmasked); } -void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, PBVHVertRef vertex) -{ - BLI_assert(pbvh->header.type == PBVH_FACES); - pbvh->vert_bitmap[vertex.i] = true; -} - blender::Span BKE_pbvh_node_get_loops(const PBVHNode *node) { return node->loop_indices; @@ -1853,17 +1904,6 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node, } } -bool BKE_pbvh_node_has_vert_with_normal_update_tag(PBVH *pbvh, PBVHNode *node) -{ - BLI_assert(pbvh->header.type == PBVH_FACES); - for (const int vert : node->vert_indices) { - if (pbvh->vert_bitmap[vert]) { - return true; - } - } - return false; -} - /********************************* Ray-cast ***********************************/ namespace blender::bke::pbvh { @@ -2817,7 +2857,6 @@ void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const Span vert_positions) /* no need for float comparison here (memory is exactly equal or not) */ if (memcmp(positions[a], vert_positions[a], sizeof(float[3])) != 0) { positions[a] = vert_positions[a]; - BKE_pbvh_vert_tag_update_normal(pbvh, BKE_pbvh_make_vref(a)); } } diff --git a/source/blender/blenkernel/intern/pbvh_intern.hh b/source/blender/blenkernel/intern/pbvh_intern.hh index a21fad24de5..76884c11ed5 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.hh +++ b/source/blender/blenkernel/intern/pbvh_intern.hh @@ -161,10 +161,6 @@ struct PBVH { CCGKey gridkey; SubdivCCG *subdiv_ccg; - /* Used during BVH build and later to mark that a vertex needs to update - * (its normal must be recalculated). */ - blender::Array vert_bitmap; - #ifdef PERFCNTRS int perf_modified; #endif diff --git a/source/blender/editors/sculpt_paint/paint_mask.cc b/source/blender/editors/sculpt_paint/paint_mask.cc index b0334495bf6..0079c3e939e 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.cc +++ b/source/blender/editors/sculpt_paint/paint_mask.cc @@ -1930,9 +1930,6 @@ static void project_line_gesture_apply_task(SculptGestureContext *sgcontext, PBV continue; } add_v3_v3(vd.co, disp); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(sgcontext->ss->pbvh, vd.vertex); - } any_updated = true; } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index d7327f88273..8331f1fd7f3 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -1370,9 +1370,6 @@ static void paint_mesh_restore_node(Object *ob, const undo::Type type, PBVHNode BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { SCULPT_orig_vert_data_update(&orig_vert_data, &vd); copy_v3_v3(vd.co, orig_vert_data.co); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; BKE_pbvh_node_mark_update(node); @@ -3113,10 +3110,6 @@ static void do_gravity_task(SculptSession *ss, ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, vd.mask, vd.vertex, thread_id, nullptr); mul_v3_v3fl(proxy[vd.i], offset, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_boundary.cc b/source/blender/editors/sculpt_paint/sculpt_boundary.cc index 84e9684b80f..48b0258dfb6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_boundary.cc +++ b/source/blender/editors/sculpt_paint/sculpt_boundary.cc @@ -684,10 +684,6 @@ static void do_boundary_brush_bend_task(Object *ob, const Brush *brush, PBVHNode boundary->bend.pivot_rotation_axis[vd.index], angle * boundary->edit_info[vd.index].strength_factor * mask * automask); add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -729,10 +725,6 @@ static void do_boundary_brush_slide_task(Object *ob, const Brush *brush, PBVHNod boundary->slide.directions[vd.index], boundary->edit_info[vd.index].strength_factor * disp * mask * automask * strength); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -774,10 +766,6 @@ static void do_boundary_brush_inflate_task(Object *ob, const Brush *brush, PBVHN orig_data.no, boundary->edit_info[vd.index].strength_factor * disp * mask * automask * strength); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -816,10 +804,6 @@ static void do_boundary_brush_grab_task(Object *ob, const Brush *brush, PBVHNode orig_data.co, ss->cache->grab_delta_symmetry, boundary->edit_info[vd.index].strength_factor * mask * automask * strength); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -869,10 +853,6 @@ static void do_boundary_brush_twist_task(Object *ob, const Brush *brush, PBVHNod boundary->twist.rotation_axis, angle * mask * automask * boundary->edit_info[vd.index].strength_factor); add_v3_v3(target_co, boundary->twist.pivot_position); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -924,10 +904,6 @@ static void do_boundary_brush_smooth_task(Object *ob, const Brush *brush, PBVHNo float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); madd_v3_v3v3fl( target_co, vd.co, disp, boundary->edit_info[vd.index].strength_factor * mask * strength); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc index 3d01fd522e2..4d5af686764 100644 --- a/source/blender/editors/sculpt_paint/sculpt_brush_types.cc +++ b/source/blender/editors/sculpt_paint/sculpt_brush_types.cc @@ -297,10 +297,6 @@ static void do_draw_brush_task(Object *ob, const Brush *brush, const float *offs &automask_data); mul_v3_v3fl(proxy[vd.i], offset, fade); } - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -388,10 +384,6 @@ static void do_fill_brush_task( &automask_data); mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -479,10 +471,6 @@ static void do_scrape_brush_task( &automask_data); mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -593,10 +581,6 @@ static void do_clay_thumb_brush_task(Object *ob, &automask_data); mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -729,10 +713,6 @@ static void do_flatten_brush_task( &automask_data); mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } } BKE_pbvh_vertex_iter_end; @@ -867,10 +847,6 @@ static void do_clay_brush_task( &automask_data); mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -984,10 +960,6 @@ static void do_clay_strips_brush_task(Object *ob, &automask_data); mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1174,10 +1146,6 @@ static void do_snake_hook_brush_task(Object *ob, auto_mask::factor_get(ss->cache->automasking, ss, vd.vertex, &automask_data)); copy_v3_v3(proxy[vd.i], disp); } - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1253,10 +1221,6 @@ static void do_thumb_brush_task(Object *ob, const Brush *brush, const float *con &automask_data); mul_v3_v3fl(proxy[vd.i], cono, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1326,10 +1290,6 @@ static void do_rotate_brush_task(Object *ob, const Brush *brush, const float ang 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.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1434,10 +1394,6 @@ static void do_layer_brush_task(Object *ob, Sculpt *sd, const Brush *brush, PBVH add_v3_v3v3(final_co, vd.co, vdisp); SCULPT_clip(sd, ss, vd.co, final_co); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1503,10 +1459,6 @@ static void do_inflate_brush_task(Object *ob, const Brush *brush, PBVHNode *node mul_v3_fl(val, fade * ss->cache->radius); mul_v3_v3v3(proxy[vd.i], val, ss->cache->scale); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1557,10 +1509,6 @@ static void do_nudge_brush_task(Object *ob, const Brush *brush, const float *con &automask_data); mul_v3_v3fl(proxy[vd.i], cono, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1648,10 +1596,6 @@ static void do_crease_brush_task(Object *ob, mul_v3_v3fl(val2, offset, fade); add_v3_v3v3(proxy[vd.i], val1, val2); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1761,10 +1705,6 @@ static void do_pinch_brush_task(Object *ob, project_plane_v3_v3v3(disp_center, disp_center, ss->cache->view_normal); } mul_v3_v3fl(proxy[vd.i], disp_center, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1867,10 +1807,6 @@ static void do_grab_brush_task(Object *ob, } mul_v3_v3fl(proxy[vd.i], grab_delta, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1969,10 +1905,6 @@ static void do_elastic_deform_brush_task(Object *ob, auto_mask::factor_get(ss->cache->automasking, ss, vd.vertex, &automask_data)); copy_v3_v3(proxy[vd.i], final_disp); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -2044,10 +1976,6 @@ static void do_draw_sharp_brush_task(Object *ob, &automask_data); mul_v3_v3fl(proxy[vd.i], offset, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -2151,10 +2079,6 @@ static void do_topology_slide_task(Object *ob, const Brush *brush, PBVHNode *nod SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); mul_v3_v3fl(proxy[vd.i], final_disp, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -2288,9 +2212,6 @@ static void do_topology_relax_task(Object *ob, const Brush *brush, PBVHNode *nod &automask_data); smooth::relax_vertex(ss, &vd, fade * bstrength, false, vd.co); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -2370,10 +2291,6 @@ static void do_displacement_eraser_brush_task(Object *ob, const Brush *brush, PB SCULPT_vertex_limit_surface_get(ss, vd.vertex, limit_co); sub_v3_v3v3(disp, limit_co, vd.co); mul_v3_v3fl(proxy[vd.i], disp, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -2479,10 +2396,6 @@ static void do_displacement_smear_brush_task(Object *ob, const Brush *brush, PBV float new_co[3]; add_v3_v3v3(new_co, ss->cache->limit_surface_co[vd.index], interp_limit_surface_disp); interp_v3_v3v3(vd.co, vd.co, new_co, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -2598,10 +2511,6 @@ static void do_topology_rake_bmesh_task( madd_v3_v3v3fl(val, vd.co, val, fade); SCULPT_clip(sd, ss, vd.co, val); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.cc b/source/blender/editors/sculpt_paint/sculpt_cloth.cc index 5341c60ced3..3465248ff2a 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.cc @@ -783,10 +783,6 @@ static void do_cloth_brush_solve_simulation_task(Object *ob, copy_v3_fl(cloth_sim->acceleration[i], 0.0f); copy_v3_v3(vd.co, cloth_sim->pos[vd.index]); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.cc b/source/blender/editors/sculpt_paint/sculpt_face_set.cc index 855bc76dda3..cb0f2cd97e4 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.cc +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.cc @@ -438,9 +438,6 @@ static void do_relax_face_sets_brush_task(Object *ob, &automask_data); smooth::relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -1388,7 +1385,6 @@ static void sculpt_face_set_edit_fair_face_set(Object *ob, for (int i = 0; i < totvert; i++) { if (fair_verts[i]) { interp_v3_v3v3(positions[i], orig_positions[i], positions[i], strength); - BKE_pbvh_vert_tag_update_normal(ss->pbvh, BKE_pbvh_index_to_vertex(ss->pbvh, i)); } } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc index e692cea2b98..617094969d4 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.cc @@ -529,9 +529,6 @@ static void mesh_filter_task(Object *ob, add_v3_v3v3(final_pos, orig_co, disp); } copy_v3_v3(vd.co, final_pos); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc index 3a3d1cf4c46..05a4d5e0711 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.cc @@ -180,10 +180,6 @@ static void do_multiplane_scrape_brush_task(Object *ob, &automask_data); mul_v3_v3fl(proxy[vd.i], val, fade); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.cc b/source/blender/editors/sculpt_paint/sculpt_pose.cc index 485115a59bd..6266876ca5b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.cc +++ b/source/blender/editors/sculpt_paint/sculpt_pose.cc @@ -190,10 +190,6 @@ static void do_pose_brush_task(Object *ob, const Brush *brush, PBVHNode *node) float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd); copy_v3_v3(target_co, final_pos); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.cc b/source/blender/editors/sculpt_paint/sculpt_smooth.cc index bed4cb6b1a1..0637f97f6b7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.cc +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.cc @@ -234,10 +234,6 @@ static void do_enhance_details_brush_task(Object *ob, float disp[3]; madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade); SCULPT_clip(sd, ss, vd.co, disp); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -384,9 +380,6 @@ static void smooth_position_node( sub_v3_v3v3(val, avg, vd.co); madd_v3_v3v3fl(val, vd.co, val, fade); SCULPT_clip(sd, ss, vd.co, val); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } @@ -527,9 +520,6 @@ static void do_surface_smooth_brush_laplacian_task(Object *ob, const Brush *brus surface_smooth_laplacian_step( ss, disp, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.vertex, orig_data.co, alpha); madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f)); - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; } diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.cc b/source/blender/editors/sculpt_paint/sculpt_transform.cc index 6d11e75d7b4..3eab4dba818 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.cc +++ b/source/blender/editors/sculpt_paint/sculpt_transform.cc @@ -173,10 +173,6 @@ static void sculpt_transform_task(Object *ob, const float transform_mats[8][4][4 sub_v3_v3v3(disp, transformed_co, start_co); mul_v3_fl(disp, 1.0f - fade); add_v3_v3v3(vd.co, start_co, disp); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; @@ -243,10 +239,6 @@ static void sculpt_elastic_transform_task(Object *ob, mul_v3_fl(final_disp, 20.0f * (1.0f - fade)); copy_v3_v3(proxy[vd.i], final_disp); - - if (vd.is_mesh) { - BKE_pbvh_vert_tag_update_normal(ss->pbvh, vd.vertex); - } } BKE_pbvh_vertex_iter_end; diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.cc b/source/blender/editors/sculpt_paint/sculpt_undo.cc index b14d5716216..968b5bc3a9d 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.cc +++ b/source/blender/editors/sculpt_paint/sculpt_undo.cc @@ -281,6 +281,7 @@ struct PartialUpdateData { bool changed_hide_vert; bool changed_mask; Span modified_grids; + Span modified_position_verts; Span modified_hidden_verts; Span modified_hidden_faces; Span modified_mask_verts; @@ -290,10 +291,15 @@ struct PartialUpdateData { static void update_modified_node_mesh(PBVHNode &node, PartialUpdateData &data) { - if (BKE_pbvh_node_has_vert_with_normal_update_tag(data.pbvh, &node)) { - BKE_pbvh_node_mark_update(&node); - } const Span verts = BKE_pbvh_node_get_vert_indices(&node); + if (!data.modified_position_verts.is_empty()) { + for (const int vert : verts) { + if (data.modified_position_verts[vert]) { + BKE_pbvh_node_mark_normals_update(&node); + break; + } + } + } if (!data.modified_mask_verts.is_empty()) { for (const int vert : verts) { if (data.modified_mask_verts[vert]) { @@ -407,7 +413,8 @@ static bool restore_deformed( return false; } -static bool restore_coords(bContext *C, Object *ob, Depsgraph *depsgraph, Node &unode) +static bool restore_coords( + bContext *C, Object *ob, Depsgraph *depsgraph, Node &unode, MutableSpan modified_verts) { SculptSession *ss = ob->sculpt; SubdivCCG *subdiv_ccg = ss->subdiv_ccg; @@ -471,20 +478,20 @@ static bool restore_coords(bContext *C, Object *ob, Depsgraph *depsgraph, Node & if (ss->deform_modifiers_active) { for (const int i : index.index_range()) { restore_deformed(ss, unode, i, index[i], positions[index[i]]); - BKE_pbvh_vert_tag_update_normal(ss->pbvh, BKE_pbvh_make_vref(index[i])); + modified_verts[index[i]] = true; } } else { for (const int i : index.index_range()) { swap_v3_v3(positions[index[i]], unode.orig_position[i]); - BKE_pbvh_vert_tag_update_normal(ss->pbvh, BKE_pbvh_make_vref(index[i])); + modified_verts[index[i]] = true; } } } else { for (const int i : index.index_range()) { swap_v3_v3(positions[index[i]], unode.position[i]); - BKE_pbvh_vert_tag_update_normal(ss->pbvh, BKE_pbvh_make_vref(index[i])); + modified_verts[index[i]] = true; } } } @@ -916,6 +923,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt) /* The PBVH already keeps track of which vertices need updated normals, but it doesn't keep * track of other updates. In order to tell the corresponding PBVH nodes to update, keep track * of which elements were updated for specific layers. */ + Vector modified_verts_position; Vector modified_verts_hide; Vector modified_faces_hide; Vector modified_verts_mask; @@ -945,7 +953,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt) switch (unode->type) { case Type::Position: - if (restore_coords(C, ob, depsgraph, *unode)) { + if (restore_coords(C, ob, depsgraph, *unode, modified_verts_position)) { changed_position = true; } break; @@ -1024,6 +1032,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt) data.changed_mask = changed_mask; data.pbvh = ss->pbvh; data.modified_grids = modified_grids; + data.modified_hidden_verts = modified_verts_position; data.modified_hidden_verts = modified_verts_hide; data.modified_hidden_faces = modified_faces_hide; data.modified_mask_verts = modified_verts_mask;