Refactor: Sculpt: Specialize expand face set and boundary access

Part of #118145.
This commit is contained in:
Hans Goudey
2024-09-18 16:54:39 -04:00
parent 9562056f50
commit dcb3391e10

View File

@@ -1240,14 +1240,71 @@ static void init_from_face_set_boundary(const Depsgraph &depsgraph,
const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
const int totvert = SCULPT_vertex_count_get(ob);
Array<bool> vert_has_face_set(totvert);
Array<bool> vert_has_unique_face_set(totvert);
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
bke::AttrDomain::Face);
threading::parallel_for(IndexRange(totvert), 1024, [&](const IndexRange range) {
for (const int vert : range) {
vert_has_face_set[vert] = face_set::vert_has_face_set(
vert_to_face_map, face_sets, vert, active_face_set);
vert_has_unique_face_set[vert] = face_set::vert_has_unique_face_set(
vert_to_face_map, face_sets, vert);
}
});
break;
}
case bke::pbvh::Type::Grids: {
const Mesh &base_mesh = *static_cast<const Mesh *>(ob.data);
const OffsetIndices<int> faces = base_mesh.faces();
const Span<int> corner_verts = base_mesh.corner_verts();
const GroupedSpan<int> vert_to_face_map = base_mesh.vert_to_face_map();
const bke::AttributeAccessor attributes = base_mesh.attributes();
const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set",
bke::AttrDomain::Face);
const SubdivCCG &subdiv_ccg = *ob.sculpt->subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
threading::parallel_for(IndexRange(totvert), 1024, [&](const IndexRange range) {
for (const int vert : range) {
vert_has_face_set[vert] = face_set::vert_has_face_set(
subdiv_ccg, face_sets, vert, active_face_set);
vert_has_unique_face_set[vert] = face_set::vert_has_unique_face_set(
faces,
corner_verts,
vert_to_face_map,
face_sets,
subdiv_ccg,
SubdivCCGCoord::from_index(key, vert));
}
});
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ob.sculpt->bm;
const int offset = CustomData_get_offset_named(&bm.pdata, CD_PROP_INT32, ".sculpt_face_set");
BM_mesh_elem_table_ensure(&bm, BM_FACE);
threading::parallel_for(IndexRange(totvert), 1024, [&](const IndexRange range) {
for (const int vert : range) {
const BMVert *bm_vert = BM_vert_at_index(&bm, vert);
vert_has_face_set[vert] = face_set::vert_has_face_set(offset, *bm_vert, active_face_set);
vert_has_unique_face_set[vert] = face_set::vert_has_unique_face_set(offset, *bm_vert);
}
});
break;
}
}
BitVector<> enabled_verts(totvert);
for (int i = 0; i < totvert; i++) {
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ob, i);
if (!face_set::vert_has_unique_face_set(ob, vertex)) {
if (!vert_has_unique_face_set[i]) {
continue;
}
if (!face_set::vert_has_face_set(ob, vertex, active_face_set)) {
if (!vert_has_face_set[i]) {
continue;
}
enabled_verts[i].set();
@@ -1262,11 +1319,7 @@ static void init_from_face_set_boundary(const Depsgraph &depsgraph,
if (internal_falloff) {
for (int i = 0; i < totvert; i++) {
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ob, i);
if (!(face_set::vert_has_face_set(ob, vertex, active_face_set) &&
face_set::vert_has_unique_face_set(ob, vertex)))
{
if (!(vert_has_face_set[i] && vert_has_unique_face_set[i])) {
continue;
}
expand_cache.vert_falloff[i] *= -1.0f;
@@ -1284,9 +1337,7 @@ static void init_from_face_set_boundary(const Depsgraph &depsgraph,
}
else {
for (int i = 0; i < totvert; i++) {
PBVHVertRef vertex = BKE_pbvh_index_to_vertex(ob, i);
if (!face_set::vert_has_face_set(ob, vertex, active_face_set)) {
if (!vert_has_face_set[i]) {
continue;
}
expand_cache.vert_falloff[i] = 0.0f;
@@ -2638,23 +2689,61 @@ static int sculpt_expand_invoke(bContext *C, wmOperator *op, const wmEvent *even
ss.expand_cache->next_face_set);
}
const int initial_vert = ss.expand_cache->initial_active_vert;
/* Initialize the falloff. */
FalloffType falloff_type = FalloffType(RNA_enum_get(op->ptr, "falloff_type"));
/* When starting from a boundary vertex, set the initial falloff to boundary. */
if (boundary::vert_is_boundary(
ob, BKE_pbvh_index_to_vertex(ob, ss.expand_cache->initial_active_vert)))
{
falloff_type = FalloffType::BoundaryTopology;
switch (pbvh.type()) {
case bke::pbvh::Type::Mesh: {
const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
const bke::AttributeAccessor attributes = mesh.attributes();
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
if (boundary::vert_is_boundary(
vert_to_face_map, hide_poly, ss.vertex_info.boundary, initial_vert))
{
falloff_type = FalloffType::BoundaryTopology;
}
break;
}
case bke::pbvh::Type::Grids: {
const Mesh &base_mesh = *static_cast<const Mesh *>(ob.data);
const OffsetIndices<int> faces = base_mesh.faces();
const Span<int> corner_verts = base_mesh.corner_verts();
const bke::AttributeAccessor attributes = base_mesh.attributes();
const VArraySpan face_sets = *attributes.lookup_or_default<int>(
".sculpt_face_set", bke::AttrDomain::Face, 0);
const SubdivCCG &subdiv_ccg = *ob.sculpt->subdiv_ccg;
const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
if (boundary::vert_is_boundary(faces,
corner_verts,
ss.vertex_info.boundary,
subdiv_ccg,
SubdivCCGCoord::from_index(key, initial_vert)))
{
falloff_type = FalloffType::BoundaryTopology;
}
break;
}
case bke::pbvh::Type::BMesh: {
BMesh &bm = *ob.sculpt->bm;
BM_mesh_elem_table_ensure(&bm, BM_VERT);
if (boundary::vert_is_boundary(BM_vert_at_index(&bm, initial_vert))) {
falloff_type = FalloffType::BoundaryTopology;
}
break;
}
}
calc_falloff_from_vert_and_symmetry(
*depsgraph, *ss.expand_cache, ob, ss.expand_cache->initial_active_vert, falloff_type);
*depsgraph, *ss.expand_cache, ob, initial_vert, falloff_type);
check_topology_islands(ob, falloff_type);
/* Initial mesh data update, resets all target data in the sculpt mesh. */
update_for_vert(C, ob, ss.expand_cache->initial_active_vert);
update_for_vert(C, ob, initial_vert);
WM_event_add_modal_handler(C, op);
return OPERATOR_RUNNING_MODAL;