Sculpt: Specialize a few vertex neighbor iteration cases for BMesh

The start of a transition to remove this API more generally.
This commit is contained in:
Hans Goudey
2024-05-29 10:41:36 -04:00
parent 32259aa0b6
commit 96415bc42a
5 changed files with 51 additions and 43 deletions

View File

@@ -365,7 +365,7 @@ static void grid_hide_update(Depsgraph &depsgraph,
static void partialvis_update_bmesh_verts(const Set<BMVert *, 0> &verts,
const VisAction action,
const FunctionRef<bool(const BMVert *v)> should_update,
const FunctionRef<bool(BMVert *v)> should_update,
bool *any_changed,
bool *any_visible)
{
@@ -401,7 +401,7 @@ static void partialvis_update_bmesh_faces(const Set<BMFace *, 0> &faces)
static void partialvis_update_bmesh_nodes(Object &ob,
const Span<PBVHNode *> nodes,
const VisAction action,
const FunctionRef<bool(const BMVert *v)> vert_test_fn)
const FunctionRef<bool(BMVert *v)> vert_test_fn)
{
for (PBVHNode *node : nodes) {
bool any_changed = false;
@@ -1024,8 +1024,7 @@ static void grow_shrink_visibility_grid(Depsgraph &depsgraph,
SubdivCCGNeighbors neighbors;
BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors);
for (const int j : neighbors.coords.index_range()) {
const SubdivCCGCoord neighbor = neighbors.coords[j];
for (const SubdivCCGCoord neighbor : neighbors.coords) {
const int neighbor_grid_elem_idx = elem_xy_to_index(
neighbor.x, neighbor.y, key.grid_size);
@@ -1078,32 +1077,21 @@ static Array<bool> duplicate_visibility_bmesh(const Object &object)
}
static void grow_shrink_visibility_bmesh(Object &object,
PBVH &pbvh,
const Span<PBVHNode *> nodes,
const VisAction action,
const int iterations)
{
SculptSession &ss = *object.sculpt;
for (const int i : IndexRange(iterations)) {
UNUSED_VARS(i);
const Array<bool> prev_visibility = duplicate_visibility_bmesh(object);
partialvis_update_bmesh_nodes(object, nodes, action, [&](const BMVert *vert) {
int vi = BM_elem_index_get(vert);
PBVHVertRef vref = BKE_pbvh_index_to_vertex(pbvh, vi);
SculptVertexNeighborIter ni;
bool should_change = false;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vref, ni) {
if (prev_visibility[ni.index] == action_to_hide(action)) {
/* Not returning instantly to avoid leaking memory. */
should_change = true;
break;
partialvis_update_bmesh_nodes(object, nodes, action, [&](BMVert *vert) {
Vector<BMVert *, 64> neighbors;
for (BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
if (prev_visibility[BM_elem_index_get(neighbor)] == action_to_hide(action)) {
return true;
}
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
return should_change;
return false;
});
}
}
@@ -1140,7 +1128,7 @@ static int visibility_filter_exec(bContext *C, wmOperator *op)
grow_shrink_visibility_grid(depsgraph, object, pbvh, nodes, mode, iterations);
break;
case PBVH_BMESH:
grow_shrink_visibility_bmesh(object, pbvh, nodes, mode, iterations);
grow_shrink_visibility_bmesh(object, nodes, mode, iterations);
break;
}
undo::push_end(object);

View File

@@ -690,6 +690,20 @@ static void sculpt_vertex_neighbors_get_bmesh(PBVHVertRef vertex, SculptVertexNe
}
}
Span<BMVert *> vert_neighbors_get_bmesh(BMVert &vert, Vector<BMVert *, 64> &neighbors)
{
BMIter liter;
BMLoop *l;
BM_ITER_ELEM (l, &liter, &vert, BM_LOOPS_OF_VERT) {
for (BMVert *other_vert : {l->prev->v, l->next->v}) {
if (other_vert != &vert) {
neighbors.append(other_vert);
}
}
}
return neighbors;
}
static void sculpt_vertex_neighbors_get_faces(const SculptSession &ss,
PBVHVertRef vertex,
SculptVertexNeighborIter *iter)

View File

@@ -586,17 +586,14 @@ static void dyntopo_detail_size_sample_from_surface(Object &ob,
DyntopoDetailSizeEditCustomData *cd)
{
SculptSession &ss = *ob.sculpt;
const PBVHVertRef active_vertex = SCULPT_active_vertex_get(ss);
BMVert *active_vertex = reinterpret_cast<BMVert *>(SCULPT_active_vertex_get(ss).i);
float len_accum = 0;
int num_neighbors = 0;
SculptVertexNeighborIter ni;
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, active_vertex, ni) {
len_accum += len_v3v3(SCULPT_vertex_co_get(ss, active_vertex),
SCULPT_vertex_co_get(ss, ni.vertex));
num_neighbors++;
Vector<BMVert *, 64> neighbors;
for (BMVert *neighbor : vert_neighbors_get_bmesh(*active_vertex, neighbors)) {
len_accum += len_v3v3(active_vertex->co, neighbor->co);
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
const int num_neighbors = neighbors.size();
if (num_neighbors > 0) {
const float avg_edge_len = len_accum / num_neighbors;

View File

@@ -913,6 +913,12 @@ void SCULPT_vertex_neighbors_get(const SculptSession &ss,
} \
((void)0)
namespace blender::ed::sculpt_paint {
Span<BMVert *> vert_neighbors_get_bmesh(BMVert &vert, Vector<BMVert *, 64> &neighbors);
}
PBVHVertRef SCULPT_active_vertex_get(const SculptSession &ss);
const float *SCULPT_active_vertex_co_get(const SculptSession &ss);

View File

@@ -136,32 +136,35 @@ float neighbor_mask_average(SculptSession &ss,
int total = 0;
SculptVertexNeighborIter ni;
switch (BKE_pbvh_type(*ss.pbvh)) {
case PBVH_FACES:
case PBVH_FACES: {
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
avg += write_info.layer[ni.vertex.i];
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
break;
case PBVH_GRIDS:
return avg / total;
}
case PBVH_GRIDS: {
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
avg += SCULPT_mask_get_at_grids_vert_index(
*ss.subdiv_ccg, *BKE_pbvh_get_grid_key(*ss.pbvh), ni.vertex.i);
total++;
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
break;
case PBVH_BMESH:
SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vertex, ni) {
BMVert *vert = reinterpret_cast<BMVert *>(ni.vertex.i);
avg += BM_ELEM_CD_GET_FLOAT(vert, write_info.bm_offset);
total++;
return avg / total;
}
case PBVH_BMESH: {
Vector<BMVert *, 64> neighbors;
for (BMVert *neighbor :
vert_neighbors_get_bmesh(*reinterpret_cast<BMVert *>(vertex.i), neighbors))
{
avg += BM_ELEM_CD_GET_FLOAT(neighbor, write_info.bm_offset);
}
SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
break;
return avg / neighbors.size();
}
}
BLI_assert(total > 0);
return avg / total;
BLI_assert_unreachable();
return 0.0f;
}
float4 neighbor_color_average(SculptSession &ss, PBVHVertRef vertex)