Refactor: Sculpt: Specialize grab active vertex preview
The preview is only supported with deform modifiers which are only supported for Mesh sculpting, so just write that implementation. Also remove SculptSession::vert_positions which is now unnecessary.
This commit is contained in:
@@ -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<blender::float3> vert_positions;
|
||||
blender::OffsetIndices<int> faces;
|
||||
blender::Span<int> 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<int> preview_verts;
|
||||
|
||||
/* Pose Brush Preview */
|
||||
blender::float3 pose_origin;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<float3> 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<float3> 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) {
|
||||
|
||||
@@ -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<float3> 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<float3> 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<const Mesh *>(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<float3> 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);
|
||||
|
||||
@@ -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<float3> vert_positions_for_grab_active_get(const Object &object);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the pointer to the coordinates that should be edited from a brush tool iterator
|
||||
|
||||
@@ -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<const Mesh *>(ob->data);
|
||||
/* Always grab active shape key if the sculpt happens on shapekey. */
|
||||
const Span<float3> positions = ss.shapekey_active ? BKE_pbvh_get_vert_positions(*ss.pbvh) :
|
||||
mesh.vert_positions();
|
||||
const OffsetIndices faces = mesh.faces();
|
||||
const Span<int> corner_verts = mesh.corner_verts();
|
||||
const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
|
||||
const bke::AttributeAccessor attributes = mesh.attributes();
|
||||
const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".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<int> preview_verts;
|
||||
Vector<int> neighbors;
|
||||
BitVector<> visited_verts(positions.size());
|
||||
std::queue<int> 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<PBVHVertRef>(max_preview_verts, __func__);
|
||||
}
|
||||
|
||||
std::queue<PBVHVertRef> 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*/)
|
||||
|
||||
Reference in New Issue
Block a user