Refactor: Remove corner triangle faces from PBVH storage

Part of an effort to reduce redundancy of storage for data used
by sculpt mode. See #118145.

Pull Request: https://projects.blender.org/blender/blender/pulls/121238
This commit is contained in:
Hans Goudey
2024-04-29 17:20:55 -04:00
committed by Gitea
parent 75e424563c
commit 2ac6321e88
7 changed files with 64 additions and 28 deletions

View File

@@ -167,6 +167,7 @@ bool raycast_node(PBVH &pbvh,
float (*origco)[3],
bool use_origco,
Span<int> corner_verts,
Span<int> corner_tri_faces,
Span<bool> hide_poly,
const float ray_start[3],
const float ray_normal[3],
@@ -206,6 +207,7 @@ bool find_nearest_to_ray_node(PBVH &pbvh,
float (*origco)[3],
bool use_origco,
Span<int> corner_verts,
Span<int> corner_tri_faces,
Span<bool> hide_poly,
const float ray_start[3],
const float ray_normal[3],
@@ -310,7 +312,9 @@ Span<int> node_corners(const PBVHNode &node);
* Gather the indices of all faces (not triangles) used by the node.
* For convenience, pass a reference to the data in the result.
*/
Span<int> node_face_indices_calc_mesh(const PBVH &pbvh, const PBVHNode &node, Vector<int> &faces);
Span<int> node_face_indices_calc_mesh(Span<int> corner_tri_faces,
const PBVHNode &node,
Vector<int> &faces);
/**
* Gather the indices of all base mesh faces in the node.

View File

@@ -693,7 +693,6 @@ void update_mesh_pointers(PBVH &pbvh, Mesh *mesh)
BLI_assert(pbvh.header.type == PBVH_FACES);
pbvh.faces = mesh->faces();
pbvh.corner_verts = mesh->corner_verts();
pbvh.corner_tri_faces = mesh->corner_tri_faces();
if (!pbvh.deformed) {
/* Deformed data not matching the original mesh are owned directly by the PBVH, and are
* set separately by #BKE_pbvh_vert_coords_apply. */
@@ -721,7 +720,7 @@ std::unique_ptr<PBVH> build_mesh(Mesh *mesh)
pbvh->mesh = mesh;
update_mesh_pointers(*pbvh, mesh);
const Span<int> tri_faces = pbvh->corner_tri_faces;
const Span<int> tri_faces = mesh->corner_tri_faces();
Array<bool> vert_bitmap(totvert, false);
pbvh->totvert = totvert;
@@ -1149,7 +1148,7 @@ static void calc_boundary_face_normals(const Span<float3> positions,
static void calc_node_face_normals(const Span<float3> positions,
const OffsetIndices<int> faces,
const Span<int> corner_verts,
const PBVH &pbvh,
const Span<int> corner_tri_faces,
const Span<const PBVHNode *> nodes,
MutableSpan<float3> face_normals)
{
@@ -1160,7 +1159,7 @@ static void calc_node_face_normals(const Span<float3> positions,
normals_calc_faces(positions,
faces,
corner_verts,
node_face_indices_calc_mesh(pbvh, *node, node_faces),
node_face_indices_calc_mesh(corner_tri_faces, *node, node_faces),
face_normals);
}
});
@@ -1222,6 +1221,7 @@ static void update_normals_faces(PBVH &pbvh, Span<PBVHNode *> nodes, Mesh &mesh)
const Span<float3> positions = pbvh.vert_positions;
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
const Span<int> tri_faces = mesh.corner_tri_faces();
const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
VectorSet<int> boundary_faces;
@@ -1236,13 +1236,13 @@ static void update_normals_faces(PBVH &pbvh, Span<PBVHNode *> nodes, Mesh &mesh)
[&]() {
if (pbvh.deformed) {
calc_node_face_normals(
positions, faces, corner_verts, pbvh, nodes, pbvh.face_normals_deformed);
positions, faces, corner_verts, tri_faces, nodes, pbvh.face_normals_deformed);
calc_boundary_face_normals(
positions, faces, corner_verts, boundary_faces, pbvh.face_normals_deformed);
}
else {
mesh.runtime->face_normals_cache.update([&](Vector<float3> &r_data) {
calc_node_face_normals(positions, faces, corner_verts, pbvh, nodes, r_data);
calc_node_face_normals(positions, faces, corner_verts, tri_faces, nodes, r_data);
calc_boundary_face_normals(positions, faces, corner_verts, boundary_faces, r_data);
});
/* #SharedCache::update() reallocates cached vectors if they were shared initially. */
@@ -1807,13 +1807,14 @@ Span<int> node_unique_verts(const PBVHNode &node)
return node.vert_indices.as_span().take_front(node.uniq_verts);
}
Span<int> node_face_indices_calc_mesh(const PBVH &pbvh, const PBVHNode &node, Vector<int> &faces)
Span<int> node_face_indices_calc_mesh(const Span<int> corner_tri_faces,
const PBVHNode &node,
Vector<int> &faces)
{
faces.clear();
const Span<int> tri_faces = pbvh.corner_tri_faces;
int prev_face = -1;
for (const int tri : node.prim_indices) {
const int face = tri_faces[tri];
const int face = corner_tri_faces[tri];
if (face != prev_face) {
faces.append(face);
prev_face = face;
@@ -2030,6 +2031,7 @@ static bool pbvh_faces_node_raycast(PBVH &pbvh,
const PBVHNode *node,
float (*origco)[3],
const Span<int> corner_verts,
const Span<int> corner_tri_faces,
const Span<bool> hide_poly,
const float ray_start[3],
const float ray_normal[3],
@@ -2049,7 +2051,7 @@ static bool pbvh_faces_node_raycast(PBVH &pbvh,
const int3 &tri = pbvh.corner_tris[tri_i];
const int3 face_verts = node->face_vert_indices[i];
if (!hide_poly.is_empty() && hide_poly[pbvh.corner_tri_faces[tri_i]]) {
if (!hide_poly.is_empty() && hide_poly[corner_tri_faces[tri_i]]) {
continue;
}
@@ -2086,7 +2088,7 @@ static bool pbvh_faces_node_raycast(PBVH &pbvh,
{
copy_v3_v3(nearest_vertex_co, co[j]);
r_active_vertex->i = corner_verts[tri[j]];
*r_active_face_index = pbvh.corner_tri_faces[tri_i];
*r_active_face_index = corner_tri_faces[tri_i];
}
}
}
@@ -2195,6 +2197,7 @@ bool raycast_node(PBVH &pbvh,
float (*origco)[3],
bool use_origco,
const Span<int> corner_verts,
const Span<int> corner_tri_faces,
const Span<bool> hide_poly,
const float ray_start[3],
const float ray_normal[3],
@@ -2216,6 +2219,7 @@ bool raycast_node(PBVH &pbvh,
node,
origco,
corner_verts,
corner_tri_faces,
hide_poly,
ray_start,
ray_normal,
@@ -2386,6 +2390,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH &pbvh,
const PBVHNode *node,
float (*origco)[3],
const Span<int> corner_verts,
const Span<int> corner_tri_faces,
const Span<bool> hide_poly,
const float ray_start[3],
const float ray_normal[3],
@@ -2401,7 +2406,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH &pbvh,
const int3 &corner_tri = pbvh.corner_tris[tri_i];
const int3 face_verts = node->face_vert_indices[i];
if (!hide_poly.is_empty() && hide_poly[pbvh.corner_tri_faces[tri_i]]) {
if (!hide_poly.is_empty() && hide_poly[corner_tri_faces[tri_i]]) {
continue;
}
@@ -2495,6 +2500,7 @@ bool find_nearest_to_ray_node(PBVH &pbvh,
float (*origco)[3],
bool use_origco,
const Span<int> corner_verts,
const Span<int> corner_tri_faces,
const Span<bool> hide_poly,
const float ray_start[3],
const float ray_normal[3],
@@ -2509,8 +2515,16 @@ bool find_nearest_to_ray_node(PBVH &pbvh,
switch (pbvh.header.type) {
case PBVH_FACES:
hit |= pbvh_faces_node_nearest_to_ray(
pbvh, node, origco, corner_verts, hide_poly, ray_start, ray_normal, depth, dist_sq);
hit |= pbvh_faces_node_nearest_to_ray(pbvh,
node,
origco,
corner_verts,
corner_tri_faces,
hide_poly,
ray_start,
ray_normal,
depth,
dist_sq);
break;
case PBVH_GRIDS:
hit |= pbvh_grids_node_nearest_to_ray(

View File

@@ -155,7 +155,6 @@ struct PBVH {
blender::Span<int> corner_verts;
/* Owned by the #PBVH, because after deformations they have to be recomputed. */
blender::Array<blender::int3> corner_tris;
blender::Span<int> corner_tri_faces;
/* Grid Data */
CCGKey gridkey;

View File

@@ -609,8 +609,8 @@ void PAINT_OT_hide_show_all(wmOperatorType *ot)
static void invert_visibility_mesh(Object &object, const Span<PBVHNode *> nodes)
{
PBVH &pbvh = *object.sculpt->pbvh;
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> tri_faces = mesh.corner_tri_faces();
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
".hide_poly", bke::AttrDomain::Face);
@@ -620,7 +620,7 @@ static void invert_visibility_mesh(Object &object, const Span<PBVHNode *> nodes)
Vector<int> &faces = all_index_data.local();
for (PBVHNode *node : nodes.slice(range)) {
undo::push_node(object, node, undo::Type::HideFace);
bke::pbvh::node_face_indices_calc_mesh(pbvh, *node, faces);
bke::pbvh::node_face_indices_calc_mesh(tri_faces, *node, faces);
for (const int face : faces) {
hide_poly.span[face] = !hide_poly.span[face];
}

View File

@@ -2937,6 +2937,7 @@ struct SculptRaycastData {
float depth;
bool original;
Span<int> corner_verts;
Span<int> corner_tri_faces;
blender::VArraySpan<bool> hide_poly;
PBVHVertRef active_vertex;
@@ -2955,6 +2956,7 @@ struct SculptFindNearestToRayData {
float dist_sq_to_ray;
bool original;
Span<int> corner_verts;
Span<int> corner_tri_faces;
blender::VArraySpan<bool> hide_poly;
};
@@ -4858,6 +4860,7 @@ static void sculpt_raycast_cb(PBVHNode &node, SculptRaycastData &srd, float *tmi
origco,
use_origco,
srd.corner_verts,
srd.corner_tri_faces,
srd.hide_poly,
srd.ray_start,
srd.ray_normal,
@@ -4901,6 +4904,7 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode &node,
origco,
use_origco,
srd.corner_verts,
srd.corner_tri_faces,
srd.hide_poly,
srd.ray_start,
srd.ray_normal,
@@ -4997,6 +5001,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
if (BKE_pbvh_type(*ss->pbvh) == PBVH_FACES) {
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
srd.corner_verts = mesh.corner_verts();
srd.corner_tri_faces = mesh.corner_tri_faces();
const bke::AttributeAccessor attributes = mesh.attributes();
srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
}
@@ -5151,6 +5156,7 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
if (BKE_pbvh_type(*ss->pbvh) == PBVH_FACES) {
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
srd.corner_verts = mesh.corner_verts();
srd.corner_tri_faces = mesh.corner_tri_faces();
const bke::AttributeAccessor attributes = mesh.attributes();
srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
}
@@ -5184,6 +5190,7 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
if (BKE_pbvh_type(*ss->pbvh) == PBVH_FACES) {
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
srd.corner_verts = mesh.corner_verts();
srd.corner_tri_faces = mesh.corner_tri_faces();
const bke::AttributeAccessor attributes = mesh.attributes();
srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
}
@@ -6138,6 +6145,9 @@ bool SCULPT_vertex_is_occluded(SculptSession *ss, PBVHVertRef vertex, bool origi
srd.depth = depth;
srd.face_normal = face_normal;
srd.corner_verts = ss->corner_verts;
if (BKE_pbvh_type(*ss->pbvh) == PBVH_FACES) {
srd.corner_tri_faces = BKE_pbvh_get_mesh(*ss->pbvh)->corner_tri_faces();
}
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
bke::pbvh::raycast(

View File

@@ -497,6 +497,9 @@ static void face_sets_update(Object &object,
const FunctionRef<void(Span<int>, MutableSpan<int>)> calc_face_sets)
{
PBVH &pbvh = *object.sculpt->pbvh;
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> tri_faces = mesh.corner_tri_faces();
bke::SpanAttributeWriter<int> face_sets = ensure_face_sets_mesh(object);
struct TLS {
@@ -510,7 +513,7 @@ static void face_sets_update(Object &object,
for (PBVHNode *node : nodes.slice(range)) {
const Span<int> faces =
BKE_pbvh_type(pbvh) == PBVH_FACES ?
bke::pbvh::node_face_indices_calc_mesh(pbvh, *node, tls.face_indices) :
bke::pbvh::node_face_indices_calc_mesh(tri_faces, *node, tls.face_indices) :
bke::pbvh::node_face_indices_calc_grids(pbvh, *node, tls.face_indices);
tls.new_face_sets.reinitialize(faces.size());
@@ -545,6 +548,7 @@ static void clear_face_sets(Object &object, const Span<PBVHNode *> nodes)
return;
}
const PBVH &pbvh = *object.sculpt->pbvh;
const Span<int> tri_faces = mesh.corner_tri_faces();
const int default_face_set = mesh.face_sets_color_default;
const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
threading::EnumerableThreadSpecific<Vector<int>> all_face_indices;
@@ -553,7 +557,7 @@ static void clear_face_sets(Object &object, const Span<PBVHNode *> nodes)
for (PBVHNode *node : nodes.slice(range)) {
const Span<int> faces =
BKE_pbvh_type(pbvh) == PBVH_FACES ?
bke::pbvh::node_face_indices_calc_mesh(pbvh, *node, face_indices) :
bke::pbvh::node_face_indices_calc_mesh(tri_faces, *node, face_indices) :
bke::pbvh::node_face_indices_calc_grids(pbvh, *node, face_indices);
if (std::any_of(faces.begin(), faces.end(), [&](const int face) {
return face_sets[face] != default_face_set;
@@ -998,6 +1002,7 @@ static void face_hide_update(Object &object,
{
PBVH &pbvh = *object.sculpt->pbvh;
Mesh &mesh = *static_cast<Mesh *>(object.data);
const Span<int> tri_faces = mesh.corner_tri_faces();
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
".hide_poly", bke::AttrDomain::Face);
@@ -1014,7 +1019,7 @@ static void face_hide_update(Object &object,
for (PBVHNode *node : nodes.slice(range)) {
const Span<int> faces =
BKE_pbvh_type(pbvh) == PBVH_FACES ?
bke::pbvh::node_face_indices_calc_mesh(pbvh, *node, tls.face_indices) :
bke::pbvh::node_face_indices_calc_mesh(tri_faces, *node, tls.face_indices) :
bke::pbvh::node_face_indices_calc_grids(pbvh, *node, tls.face_indices);
tls.new_hide.reinitialize(faces.size());
@@ -1699,6 +1704,7 @@ static void face_set_gesture_apply_mesh(gesture::GestureData &gesture_data,
const Span<float3> positions = ss.vert_positions;
const OffsetIndices<int> faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
const Span<int> tri_faces = mesh.corner_tri_faces();
const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
bke::SpanAttributeWriter<int> face_sets = face_set::ensure_face_sets_mesh(object);
@@ -1713,7 +1719,7 @@ static void face_set_gesture_apply_mesh(gesture::GestureData &gesture_data,
undo::push_node(*gesture_data.vc.obact, node, undo::Type::FaceSet);
const Span<int> node_faces =
BKE_pbvh_type(pbvh) == PBVH_FACES ?
bke::pbvh::node_face_indices_calc_mesh(pbvh, *node, tls.face_indices) :
bke::pbvh::node_face_indices_calc_mesh(tri_faces, *node, tls.face_indices) :
bke::pbvh::node_face_indices_calc_grids(pbvh, *node, tls.face_indices);
bool any_updated = false;

View File

@@ -289,7 +289,7 @@ struct PartialUpdateData {
Span<bool> modified_face_set_faces;
};
static void update_modified_node_mesh(PBVHNode &node, PartialUpdateData &data)
static void update_modified_node_mesh(const Mesh &mesh, PBVHNode &node, PartialUpdateData &data)
{
const Span<int> verts = bke::pbvh::node_verts(node);
if (!data.modified_position_verts.is_empty()) {
@@ -328,7 +328,7 @@ static void update_modified_node_mesh(PBVHNode &node, PartialUpdateData &data)
Vector<int> faces;
if (!data.modified_face_set_faces.is_empty()) {
if (faces.is_empty()) {
bke::pbvh::node_face_indices_calc_mesh(*data.pbvh, node, faces);
bke::pbvh::node_face_indices_calc_mesh(mesh.corner_tri_faces(), node, faces);
}
for (const int face : faces) {
if (data.modified_face_set_faces[face]) {
@@ -339,7 +339,7 @@ static void update_modified_node_mesh(PBVHNode &node, PartialUpdateData &data)
}
if (!data.modified_hidden_faces.is_empty()) {
if (faces.is_empty()) {
bke::pbvh::node_face_indices_calc_mesh(*data.pbvh, node, faces);
bke::pbvh::node_face_indices_calc_mesh(mesh.corner_tri_faces(), node, faces);
}
for (const int face : faces) {
if (data.modified_hidden_faces[face]) {
@@ -889,6 +889,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt)
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BKE_view_layer_synced_ensure(scene, view_layer);
Object &object = *BKE_view_layer_active_object_get(view_layer);
Mesh &mesh = *static_cast<Mesh *>(object.data);
SculptSession *ss = object.sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
@@ -1056,7 +1057,7 @@ static void restore_list(bContext *C, Depsgraph *depsgraph, UndoSculpt &usculpt)
}
else {
bke::pbvh::search_callback(
*ss->pbvh, {}, [&](PBVHNode &node) { update_modified_node_mesh(node, data); });
*ss->pbvh, {}, [&](PBVHNode &node) { update_modified_node_mesh(mesh, node, data); });
}
if (changed_position) {
@@ -1190,6 +1191,8 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
Node *unode = alloc_node_type(object, type);
unode->node = node;
const Mesh &mesh = *static_cast<Mesh *>(object.data);
int verts_num;
if (BKE_pbvh_type(*ss->pbvh) == PBVH_GRIDS) {
unode->mesh_grids_num = ss->subdiv_ccg->grids.size();
@@ -1217,14 +1220,14 @@ static Node *alloc_node(const Object &object, const PBVHNode *node, const Type t
if (need_loops) {
unode->corner_indices = bke::pbvh::node_corners(*node);
unode->mesh_corners_num = static_cast<Mesh *>(object.data)->corners_num;
unode->mesh_corners_num = mesh.corners_num;
usculpt->undo_size += unode->corner_indices.as_span().size_in_bytes();
}
if (need_faces) {
if (BKE_pbvh_type(*ss->pbvh) == PBVH_FACES) {
bke::pbvh::node_face_indices_calc_mesh(*ss->pbvh, *node, unode->face_indices);
bke::pbvh::node_face_indices_calc_mesh(mesh.corner_tri_faces(), *node, unode->face_indices);
}
else {
bke::pbvh::node_face_indices_calc_grids(*ss->pbvh, *node, unode->face_indices);