Refactor: Sculpt: Specialize expand face set and boundary access
Part of #118145.
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user