diff --git a/source/blender/blenkernel/BKE_paint.hh b/source/blender/blenkernel/BKE_paint.hh index bfc69cc8fd7..502da39d67f 100644 --- a/source/blender/blenkernel/BKE_paint.hh +++ b/source/blender/blenkernel/BKE_paint.hh @@ -423,7 +423,6 @@ struct SculptSession : blender::NonCopyable, blender::NonMovable { Depsgraph *depsgraph = nullptr; /* These are always assigned to base mesh data when using Type::Mesh. */ - blender::MutableSpan vert_positions; blender::OffsetIndices faces; blender::Span corner_verts; @@ -509,8 +508,7 @@ struct SculptSession : blender::NonCopyable, blender::NonMovable { Scene *scene = nullptr; /* Dynamic mesh preview */ - PBVHVertRef *preview_vert_list = nullptr; - int preview_vert_count = 0; + blender::Array preview_verts; /* Pose Brush Preview */ blender::float3 pose_origin; diff --git a/source/blender/blenkernel/intern/paint.cc b/source/blender/blenkernel/intern/paint.cc index 40f778fbe6d..6707b421286 100644 --- a/source/blender/blenkernel/intern/paint.cc +++ b/source/blender/blenkernel/intern/paint.cc @@ -1662,8 +1662,7 @@ static void sculptsession_free_pbvh(Object *object) ss->vert_to_edge_indices = {}; ss->vert_to_edge_map = {}; - MEM_SAFE_FREE(ss->preview_vert_list); - ss->preview_vert_count = 0; + ss->preview_verts = {}; ss->vertex_info.boundary.clear_and_shrink(); @@ -1945,7 +1944,6 @@ static void sculpt_update_object(Depsgraph *depsgraph, ss.totvert = mesh_orig->verts_num; ss.faces_num = mesh_orig->faces_num; ss.totfaces = mesh_orig->faces_num; - ss.vert_positions = mesh_orig->vert_positions_for_write(); ss.faces = mesh_orig->faces(); ss.corner_verts = mesh_orig->corner_verts(); ss.multires.active = false; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.cc b/source/blender/editors/sculpt_paint/paint_cursor.cc index f76daaba432..6c9202addd4 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.cc +++ b/source/blender/editors/sculpt_paint/paint_cursor.cc @@ -1147,17 +1147,13 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr, static void sculpt_geometry_preview_lines_draw(const uint gpuattr, const Brush &brush, - const bool is_multires, - const SculptSession &ss) + const Object &object) { if (!(brush.flag & BRUSH_GRAB_ACTIVE_VERTEX)) { return; } - if (is_multires) { - return; - } - + const SculptSession &ss = *object.sculpt; if (ss.pbvh->type() != bke::pbvh::Type::Mesh) { return; } @@ -1175,10 +1171,11 @@ static void sculpt_geometry_preview_lines_draw(const uint gpuattr, } GPU_line_width(1.0f); - if (ss.preview_vert_count > 0) { - immBegin(GPU_PRIM_LINES, ss.preview_vert_count); - for (int i = 0; i < ss.preview_vert_count; i++) { - immVertex3fv(gpuattr, SCULPT_vertex_co_for_grab_active_get(ss, ss.preview_vert_list[i])); + if (!ss.preview_verts.is_empty()) { + const Span positions = vert_positions_for_grab_active_get(object); + immBegin(GPU_PRIM_LINES, ss.preview_verts.size()); + for (const int vert : ss.preview_verts) { + immVertex3fv(gpuattr, positions[vert]); } immEnd(); } @@ -1258,7 +1255,6 @@ struct PaintCursorContext { bool is_stroke_active; bool is_cursor_over_mesh; - bool is_multires; float radius; /* 3D view cursor position and normal. */ @@ -1434,8 +1430,6 @@ static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext *pcon paint_cursor_update_unprojected_radius(ups, brush, vc, pcontext->scene_space_location); } - pcontext->is_multires = ss.pbvh != nullptr && ss.pbvh->type() == bke::pbvh::Type::Grids; - pcontext->sd = CTX_data_tool_settings(pcontext->C)->sculpt; } @@ -1769,7 +1763,14 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext * const float *active_vertex_co; if (brush.sculpt_tool == SCULPT_TOOL_GRAB && brush.flag & BRUSH_GRAB_ACTIVE_VERTEX) { - active_vertex_co = SCULPT_vertex_co_for_grab_active_get(*pcontext->ss, active_vert); + SculptSession &ss = *pcontext->ss; + if (ss.pbvh->type() == bke::pbvh::Type::Mesh) { + const Span positions = vert_positions_for_grab_active_get(*pcontext->vc.obact); + active_vertex_co = positions[active_vert.i]; + } + else { + active_vertex_co = SCULPT_vertex_co_get(*pcontext->ss, active_vert); + } } else { active_vertex_co = SCULPT_vertex_co_get(*pcontext->ss, active_vert); @@ -1846,8 +1847,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext * (brush.flag & BRUSH_GRAB_ACTIVE_VERTEX)) { geometry_preview_lines_update(pcontext->C, *pcontext->ss, pcontext->radius); - sculpt_geometry_preview_lines_draw( - pcontext->pos, *pcontext->brush, pcontext->is_multires, *pcontext->ss); + sculpt_geometry_preview_lines_draw(pcontext->pos, *pcontext->brush, *pcontext->vc.obact); } if (is_brush_tool && brush.sculpt_tool == SCULPT_TOOL_POSE) { @@ -1937,7 +1937,7 @@ static void paint_cursor_cursor_draw_3d_view_brush_cursor_active(PaintCursorCont /* Draw the special active cursors different tools may have. */ if (brush.sculpt_tool == SCULPT_TOOL_GRAB) { - sculpt_geometry_preview_lines_draw(pcontext->pos, brush, pcontext->is_multires, ss); + sculpt_geometry_preview_lines_draw(pcontext->pos, brush, *pcontext->vc.obact); } if (brush.sculpt_tool == SCULPT_TOOL_MULTIPLANE_SCRAPE) { diff --git a/source/blender/editors/sculpt_paint/sculpt.cc b/source/blender/editors/sculpt_paint/sculpt.cc index 450c09af271..9113c719787 100644 --- a/source/blender/editors/sculpt_paint/sculpt.cc +++ b/source/blender/editors/sculpt_paint/sculpt.cc @@ -203,23 +203,23 @@ const blender::float3 SCULPT_vertex_normal_get(const SculptSession &ss, PBVHVert return {}; } -const float *SCULPT_vertex_co_for_grab_active_get(const SculptSession &ss, PBVHVertRef vertex) +namespace blender::ed::sculpt_paint { + +Span vert_positions_for_grab_active_get(const Object &object) { - if (ss.pbvh->type() == blender::bke::pbvh::Type::Mesh) { + const SculptSession &ss = *object.sculpt; + BLI_assert(ss.pbvh->type() == bke::pbvh::Type::Mesh); + if (ss.shapekey_active) { /* Always grab active shape key if the sculpt happens on shapekey. */ - if (ss.shapekey_active) { - const Span positions = BKE_pbvh_get_vert_positions(*ss.pbvh); - return positions[vertex.i]; - } - - /* Sculpting on the base mesh. */ - return ss.vert_positions[vertex.i]; + return BKE_pbvh_get_vert_positions(*ss.pbvh); } - - /* Everything else, such as sculpting on multires. */ - return SCULPT_vertex_co_get(ss, vertex); + /* Otherwise use the base mesh positions. */ + const Mesh &mesh = *static_cast(object.data); + return mesh.vert_positions(); } +} // namespace blender::ed::sculpt_paint + float *SCULPT_brush_deform_target_vertex_co_get(SculptSession &ss, const int deform_target, PBVHVertexIter *iter) @@ -4612,7 +4612,9 @@ static bool sculpt_needs_delta_for_tip_orientation(const Brush &brush) SCULPT_TOOL_SNAKE_HOOK); } -static void sculpt_update_brush_delta(UnifiedPaintSettings &ups, Object &ob, const Brush &brush) +static void sculpt_update_brush_delta(UnifiedPaintSettings &ups, + const Object &ob, + const Brush &brush) { SculptSession &ss = *ob.sculpt; StrokeCache *cache = ss.cache; @@ -4645,8 +4647,13 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings &ups, Object &ob, con 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, ss.active_vert_ref())); + if (ss.pbvh->type() == bke::pbvh::Type::Mesh) { + const Span positions = vert_positions_for_grab_active_get(ob); + cache->orig_grab_location = positions[ss.active_vert_ref().i]; + } + else { + cache->orig_grab_location = SCULPT_vertex_co_get(ss, ss.active_vert_ref()); + } } else { copy_v3_v3(cache->orig_grab_location, cache->true_location); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.hh b/source/blender/editors/sculpt_paint/sculpt_intern.hh index e17a169011d..63b17600147 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.hh +++ b/source/blender/editors/sculpt_paint/sculpt_intern.hh @@ -902,10 +902,14 @@ const blender::float3 SCULPT_vertex_normal_get(const SculptSession &ss, PBVHVert bool SCULPT_vertex_is_occluded(SculptSession &ss, PBVHVertRef vertex, bool original); +namespace blender::ed::sculpt_paint { + /** * Coordinates used for manipulating the base mesh when Grab Active Vertex is enabled. */ -const float *SCULPT_vertex_co_for_grab_active_get(const SculptSession &ss, PBVHVertRef vertex); +Span vert_positions_for_grab_active_get(const Object &object); + +} /** * Returns the pointer to the coordinates that should be edited from a brush tool iterator diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.cc b/source/blender/editors/sculpt_paint/sculpt_ops.cc index 481f812ff16..4a26af87b82 100644 --- a/source/blender/editors/sculpt_paint/sculpt_ops.cc +++ b/source/blender/editors/sculpt_paint/sculpt_ops.cc @@ -581,8 +581,7 @@ void geometry_preview_lines_update(bContext *C, SculptSession &ss, float radius) Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Object *ob = CTX_data_active_object(C); - ss.preview_vert_count = 0; - int totpoints = 0; + ss.preview_verts = {}; /* This function is called from the cursor drawing code, so the tree may not be build yet. */ if (!ss.pbvh) { @@ -593,54 +592,52 @@ void geometry_preview_lines_update(bContext *C, SculptSession &ss, float radius) return; } - if (ss.pbvh->type() == bke::pbvh::Type::Grids) { + if (ss.pbvh->type() != bke::pbvh::Type::Mesh) { return; } BKE_sculpt_update_object_for_edit(depsgraph, ob, false); - float brush_co[3]; - copy_v3_v3(brush_co, SCULPT_vertex_co_get(ss, ss.active_vert_ref())); + const Mesh &mesh = *static_cast(ob->data); + /* Always grab active shape key if the sculpt happens on shapekey. */ + const Span positions = ss.shapekey_active ? BKE_pbvh_get_vert_positions(*ss.pbvh) : + mesh.vert_positions(); + const OffsetIndices faces = mesh.faces(); + const Span corner_verts = mesh.corner_verts(); + const GroupedSpan vert_to_face_map = mesh.vert_to_face_map(); + const bke::AttributeAccessor attributes = mesh.attributes(); + const VArraySpan hide_poly = *attributes.lookup(".hide_poly", bke::AttrDomain::Face); - BitVector<> visited_verts(SCULPT_vertex_count_get(ss)); + const int active_vert = ss.active_vert_ref().i; + const float3 brush_co = positions[active_vert]; + const float radius_sq = radius * radius; - /* Assuming an average of 6 edges per vertex in a triangulated mesh. */ - const int max_preview_verts = SCULPT_vertex_count_get(ss) * 3 * 2; + Vector preview_verts; + Vector neighbors; + BitVector<> visited_verts(positions.size()); + std::queue queue; + queue.push(active_vert); + while (!queue.empty()) { + const int from_vert = queue.front(); + queue.pop(); - if (ss.preview_vert_list == nullptr) { - ss.preview_vert_list = MEM_cnew_array(max_preview_verts, __func__); - } - - std::queue non_visited_verts; - non_visited_verts.push(ss.active_vert_ref()); - - while (!non_visited_verts.empty()) { - PBVHVertRef from_v = non_visited_verts.front(); - non_visited_verts.pop(); - - SculptVertexNeighborIter ni; - SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, from_v, ni) { - if (totpoints + (ni.neighbors.size() * 2) < max_preview_verts) { - PBVHVertRef to_v = ni.vertex; - int to_v_i = ni.index; - ss.preview_vert_list[totpoints] = from_v; - totpoints++; - ss.preview_vert_list[totpoints] = to_v; - totpoints++; - if (visited_verts[to_v_i]) { - continue; - } - visited_verts[to_v_i].set(); - const float *co = SCULPT_vertex_co_for_grab_active_get(ss, to_v); - if (len_squared_v3v3(brush_co, co) < radius * radius) { - non_visited_verts.push(to_v); - } + neighbors.clear(); + for (const int neighbor : vert_neighbors_get_mesh( + from_vert, faces, corner_verts, vert_to_face_map, hide_poly, neighbors)) + { + preview_verts.append(from_vert); + preview_verts.append(neighbor); + if (visited_verts[neighbor]) { + continue; + } + visited_verts[neighbor].set(); + if (math::distance_squared(brush_co, positions[neighbor]) < radius_sq) { + queue.push(neighbor); } } - SCULPT_VERTEX_NEIGHBORS_ITER_END(ni); } - ss.preview_vert_count = totpoints; + ss.preview_verts = preview_verts.as_span(); } static int sculpt_sample_color_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)