Cleanup: Reduce usage of mesh data pointers in PBVH

Pointers to hide status layers and custom data are removed,
since they can be accessed from the mesh as necessary.
Usage of other arrays has been reduced, so the pointers
can eventually be removed.

The reasoning is the same as some other commits in this area:
the goal is less duplication of state, and a more focused design
of the responsibilities of the PBVH class.

Some of the changes are fairly noisy, since we need to add
arguments to functions in a few places. On the nicer side of
things, some functions for syncing the state can be removed.

Not retrieving hide layers with write access also has performance
implications in some cases, since it means the original arrays can
be reused without a copy when they're shared.
This commit is contained in:
Hans Goudey
2023-11-30 18:25:12 -05:00
parent a5e17dc607
commit 49f676e6c2
10 changed files with 247 additions and 237 deletions

View File

@@ -253,6 +253,8 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
blender::Span<int> corner_verts,
const bool *hide_poly,
const float ray_start[3],
const float ray_normal[3],
IsectRayPrecalc *isect_precalc,
@@ -291,6 +293,8 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
blender::Span<int> corner_verts,
const bool *hide_poly,
const float ray_start[3],
const float ray_normal[3],
float *depth,
@@ -398,10 +402,7 @@ void BKE_pbvh_node_num_verts(const PBVH *pbvh,
int BKE_pbvh_node_num_unique_verts(const PBVH &pbvh, const PBVHNode &node);
blender::Span<int> BKE_pbvh_node_get_vert_indices(const PBVHNode *node);
blender::Span<int> BKE_pbvh_node_get_unique_vert_indices(const PBVHNode *node);
void BKE_pbvh_node_get_loops(PBVH *pbvh,
PBVHNode *node,
const int **r_loop_indices,
const int **r_corner_verts);
void BKE_pbvh_node_get_loops(PBVHNode *node, const int **r_loop_indices);
blender::Vector<int> BKE_pbvh_node_calc_face_indices(const PBVH &pbvh, const PBVHNode &node);
/* Get number of faces in the mesh; for PBVH_GRIDS the
@@ -450,14 +451,6 @@ blender::IndexMask BKE_pbvh_get_grid_updates(const PBVH *pbvh,
void BKE_pbvh_grids_update(PBVH *pbvh, CCGKey *key);
void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg);
/**
* If an operation causes the hide status stored in the mesh to change, this must be called
* to update the references to those attributes, since they are only added when necessary.
*/
void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh);
/* Vertex Deformer. */
void BKE_pbvh_vert_coords_apply(PBVH *pbvh, blender::Span<blender::float3> vert_positions);
bool BKE_pbvh_is_deformed(PBVH *pbvh);
@@ -624,10 +617,6 @@ void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings,
blender::MutableSpan<blender::float3> BKE_pbvh_get_vert_positions(const PBVH *pbvh);
const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3];
const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh);
bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh);
const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh);
PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node);
void BKE_pbvh_node_color_buffer_free(PBVH *pbvh);

View File

@@ -1750,7 +1750,6 @@ static void sculpt_update_object(
UNUSED_VARS_NDEBUG(pbvh);
BKE_pbvh_subdiv_cgg_set(ss->pbvh, ss->subdiv_ccg);
BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
sculpt_attribute_update_refs(ob);
sculpt_update_persistent_base(ob);

View File

@@ -250,16 +250,19 @@ static int partition_indices_grids(blender::MutableSpan<int> prim_indices,
}
/* Returns the index of the first element on the right of the partition */
static int partition_indices_material(
PBVH *pbvh, const int *material_indices, const bool *sharp_faces, int lo, int hi)
static int partition_indices_material(PBVH *pbvh,
const Span<int> looptri_faces,
const int *material_indices,
const bool *sharp_faces,
int lo,
int hi)
{
const Span<int> looptri_faces = pbvh->looptri_faces;
const Span<DMFlagMat> flagmats = pbvh->subdiv_ccg->grid_flag_mats;
MutableSpan<int> indices = pbvh->prim_indices;
int i = lo, j = hi;
for (;;) {
if (!pbvh->looptri_faces.is_empty()) {
if (!looptri_faces.is_empty()) {
const int first = looptri_faces[pbvh->prim_indices[lo]];
for (; face_materials_match(material_indices, sharp_faces, first, looptri_faces[indices[i]]);
i++) {
@@ -297,13 +300,16 @@ void pbvh_grow_nodes(PBVH *pbvh, int totnode)
/* Add a vertex to the map, with a positive value for unique vertices and
* a negative value for additional vertices */
static int map_insert_vert(
PBVH *pbvh, blender::Map<int, int> &map, int *face_verts, int *uniq_verts, int vertex)
static int map_insert_vert(blender::Map<int, int> &map,
MutableSpan<bool> vert_bitmap,
int *face_verts,
int *uniq_verts,
int vertex)
{
return map.lookup_or_add_cb(vertex, [&]() {
int value;
if (!pbvh->vert_bitmap[vertex]) {
pbvh->vert_bitmap[vertex] = true;
if (!vert_bitmap[vertex]) {
vert_bitmap[vertex] = true;
value = *uniq_verts;
(*uniq_verts)++;
}
@@ -316,7 +322,12 @@ static int map_insert_vert(
}
/* Find vertices used by the faces in this node and update the draw buffers */
static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
static void build_mesh_leaf_node(const Span<int> corner_verts,
const Span<MLoopTri> looptris,
const Span<int> looptri_faces,
const bool *hide_poly,
MutableSpan<bool> vert_bitmap,
PBVHNode *node)
{
node->uniq_verts = node->face_verts = 0;
const Span<int> prim_indices = node->prim_indices;
@@ -328,10 +339,10 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
node->face_vert_indices.reinitialize(prim_indices.size());
for (const int i : prim_indices.index_range()) {
const MLoopTri &tri = pbvh->looptri[prim_indices[i]];
const MLoopTri &tri = looptris[prim_indices[i]];
for (int j = 0; j < 3; j++) {
node->face_vert_indices[i][j] = map_insert_vert(
pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->corner_verts[tri.tri[j]]);
map, vert_bitmap, &node->face_verts, &node->uniq_verts, corner_verts[tri.tri[j]]);
}
}
@@ -355,12 +366,11 @@ static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
}
}
const bool fully_hidden = pbvh->hide_poly &&
std::all_of(
prim_indices.begin(), prim_indices.end(), [&](const int tri) {
const int face = pbvh->looptri_faces[tri];
return pbvh->hide_poly[face];
});
const bool fully_hidden = hide_poly && std::all_of(prim_indices.begin(),
prim_indices.end(),
[&](const int tri) {
return hide_poly[looptri_faces[tri]];
});
BKE_pbvh_node_fully_hidden_set(node, fully_hidden);
BKE_pbvh_node_mark_rebuild_draw(node);
}
@@ -423,37 +433,51 @@ static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node)
BKE_pbvh_node_mark_rebuild_draw(node);
}
static void build_leaf(PBVH *pbvh, int node_index, const Span<BBC> prim_bbc, int offset, int count)
static void build_leaf(PBVH *pbvh,
const Span<int> corner_verts,
const Span<MLoopTri> looptris,
const Span<int> looptri_faces,
const bool *hide_poly,
int node_index,
const Span<BBC> prim_bbc,
int offset,
int count)
{
pbvh->nodes[node_index].flag |= PBVH_Leaf;
PBVHNode &node = pbvh->nodes[node_index];
node.flag |= PBVH_Leaf;
pbvh->nodes[node_index].prim_indices = pbvh->prim_indices.as_span().slice(offset, count);
node.prim_indices = pbvh->prim_indices.as_span().slice(offset, count);
/* Still need vb for searches */
update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count);
update_vb(pbvh, &node, prim_bbc, offset, count);
if (!pbvh->looptri.is_empty()) {
build_mesh_leaf_node(pbvh, &pbvh->nodes[node_index]);
build_mesh_leaf_node(
corner_verts, looptris, looptri_faces, hide_poly, pbvh->vert_bitmap, &node);
}
else {
build_grid_leaf_node(pbvh, &pbvh->nodes[node_index]);
build_grid_leaf_node(pbvh, &node);
}
}
/* Return zero if all primitives in the node can be drawn with the
* same material (including flat/smooth shading), non-zero otherwise */
static bool leaf_needs_material_split(
PBVH *pbvh, const int *material_indices, const bool *sharp_faces, int offset, int count)
static bool leaf_needs_material_split(PBVH *pbvh,
const Span<int> looptri_faces,
const int *material_indices,
const bool *sharp_faces,
int offset,
int count)
{
if (count <= 1) {
return false;
}
if (!pbvh->looptri.is_empty()) {
const int first = pbvh->looptri_faces[pbvh->prim_indices[offset]];
const int first = looptri_faces[pbvh->prim_indices[offset]];
for (int i = offset + count - 1; i > offset; i--) {
int prim = pbvh->prim_indices[i];
if (!face_materials_match(material_indices, sharp_faces, first, pbvh->looptri_faces[prim])) {
if (!face_materials_match(material_indices, sharp_faces, first, looptri_faces[prim])) {
return true;
}
}
@@ -491,7 +515,7 @@ static void test_face_boundaries(PBVH *pbvh)
switch (BKE_pbvh_type(pbvh)) {
case PBVH_FACES: {
for (int j = 0; j < node->totprim; j++) {
int face_i = pbvh->looptri_faces[node->prim_indices[j]];
int face_i = looptri_faces[node->prim_indices[j]];
if (node_map[face_i] >= 0 && node_map[face_i] != i) {
int old_i = node_map[face_i];
@@ -532,6 +556,10 @@ static void test_face_boundaries(PBVH *pbvh)
*/
static void build_sub(PBVH *pbvh,
const Span<int> corner_verts,
const Span<MLoopTri> looptris,
const Span<int> looptri_faces,
const bool *hide_poly,
const int *material_indices,
const bool *sharp_faces,
int node_index,
@@ -552,8 +580,17 @@ static void build_sub(PBVH *pbvh,
/* Decide whether this is a leaf or not */
const bool below_leaf_limit = count <= pbvh->leaf_limit || depth >= STACK_FIXED_DEPTH - 1;
if (below_leaf_limit) {
if (!leaf_needs_material_split(pbvh, material_indices, sharp_faces, offset, count)) {
build_leaf(pbvh, node_index, prim_bbc, offset, count);
if (!leaf_needs_material_split(
pbvh, looptri_faces, material_indices, sharp_faces, offset, count)) {
build_leaf(pbvh,
corner_verts,
looptris,
looptri_faces,
hide_poly,
node_index,
prim_bbc,
offset,
count);
if (node_index == 0) {
MEM_SAFE_FREE(prim_scratch);
@@ -590,7 +627,7 @@ static void build_sub(PBVH *pbvh,
axis,
(cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
prim_bbc,
pbvh->looptri_faces);
looptri_faces);
}
else {
end = partition_indices_grids(pbvh->prim_indices,
@@ -606,11 +643,15 @@ static void build_sub(PBVH *pbvh,
else {
/* Partition primitives by material */
end = partition_indices_material(
pbvh, material_indices, sharp_faces, offset, offset + count - 1);
pbvh, looptri_faces, material_indices, sharp_faces, offset, offset + count - 1);
}
/* Build children */
build_sub(pbvh,
corner_verts,
looptris,
looptri_faces,
hide_poly,
material_indices,
sharp_faces,
pbvh->nodes[node_index].children_offset,
@@ -621,6 +662,10 @@ static void build_sub(PBVH *pbvh,
prim_scratch,
depth + 1);
build_sub(pbvh,
corner_verts,
looptris,
looptri_faces,
hide_poly,
material_indices,
sharp_faces,
pbvh->nodes[node_index].children_offset + 1,
@@ -637,6 +682,10 @@ static void build_sub(PBVH *pbvh,
}
static void pbvh_build(PBVH *pbvh,
const Span<int> corner_verts,
const Span<MLoopTri> looptris,
const Span<int> looptri_faces,
const bool *hide_poly,
const int *material_indices,
const bool *sharp_faces,
BB *cb,
@@ -653,7 +702,20 @@ static void pbvh_build(PBVH *pbvh,
pbvh->nodes.resize(1);
build_sub(pbvh, material_indices, sharp_faces, 0, cb, prim_bbc, 0, totprim, nullptr, 0);
build_sub(pbvh,
corner_verts,
looptris,
looptri_faces,
hide_poly,
material_indices,
sharp_faces,
0,
cb,
prim_bbc,
0,
totprim,
nullptr,
0);
}
static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *args, PBVHNode *node)
@@ -663,54 +725,42 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
args->pbvh_type = pbvh->header.type;
args->node = node;
args->grid_hidden = pbvh->subdiv_ccg->grid_hidden;
args->face_sets_color_default = mesh.face_sets_color_default;
args->face_sets_color_seed = mesh.face_sets_color_seed;
args->vert_positions = pbvh->vert_positions;
if (pbvh->mesh) {
args->corner_verts = pbvh->corner_verts;
args->corner_edges = pbvh->mesh->corner_edges();
}
args->faces = pbvh->faces;
args->mlooptri = pbvh->looptri;
if (ELEM(pbvh->header.type, PBVH_FACES, PBVH_GRIDS)) {
args->hide_poly = pbvh->face_data ? static_cast<const bool *>(CustomData_get_layer_named(
pbvh->face_data, CD_PROP_BOOL, ".hide_poly")) :
nullptr;
}
args->active_color = mesh.active_color_attribute;
args->render_color = mesh.default_color_attribute;
switch (pbvh->header.type) {
case PBVH_FACES:
args->vert_data = pbvh->vert_data;
args->loop_data = pbvh->loop_data;
args->face_data = pbvh->face_data;
args->vert_data = &mesh.vert_data;
args->loop_data = &mesh.loop_data;
args->face_data = &mesh.face_data;
args->me = pbvh->mesh;
args->faces = pbvh->faces;
args->vert_positions = pbvh->vert_positions;
args->corner_verts = mesh.corner_verts();
args->corner_edges = mesh.corner_edges();
args->mlooptri = pbvh->looptri;
args->vert_normals = pbvh->vert_normals;
args->face_normals = pbvh->face_normals;
args->hide_poly = static_cast<const bool *>(
CustomData_get_layer_named(&mesh.face_data, CD_PROP_BOOL, ".hide_poly"));
args->prim_indices = node->prim_indices;
args->looptri_faces = pbvh->looptri_faces;
args->looptri_faces = mesh.looptri_faces();
break;
case PBVH_GRIDS:
args->vert_data = pbvh->vert_data;
args->loop_data = pbvh->loop_data;
args->face_data = pbvh->face_data;
args->vert_data = &mesh.vert_data;
args->loop_data = &mesh.loop_data;
args->face_data = &mesh.face_data;
args->ccg_key = pbvh->gridkey;
args->me = pbvh->mesh;
args->grid_indices = node->prim_indices;
args->subdiv_ccg = pbvh->subdiv_ccg;
args->faces = pbvh->faces;
args->grids = pbvh->subdiv_ccg->grids;
args->grid_hidden = pbvh->subdiv_ccg->grid_hidden;
args->grid_flag_mats = pbvh->subdiv_ccg->grid_flag_mats;
args->vert_normals = pbvh->vert_normals;
args->looptri_faces = pbvh->looptri_faces;
break;
case PBVH_BMESH:
args->bm = pbvh->header.bm;
@@ -726,7 +776,7 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
}
#ifdef VALIDATE_UNIQUE_NODE_FACES
static void pbvh_validate_node_prims(PBVH *pbvh)
static void pbvh_validate_node_prims(PBVH *pbvh, const Span<int> looptri_faces)
{
int totface = 0;
@@ -745,7 +795,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
int face_i;
if (pbvh->header.type == PBVH_FACES) {
face_i = pbvh->looptri_faces[node->prim_indices[j]];
face_i = looptri_faces[node->prim_indices[j]];
}
else {
face_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
@@ -772,7 +822,7 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
int face_i;
if (pbvh->header.type == PBVH_FACES) {
face_i = pbvh->looptri_faces[node->prim_indices[j]];
face_i = looptri_faces[node->prim_indices[j]];
}
else {
face_i = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, node->prim_indices[j]);
@@ -795,11 +845,9 @@ static void pbvh_validate_node_prims(PBVH *pbvh)
void BKE_pbvh_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->looptri_faces = mesh->looptri_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. */
@@ -807,12 +855,6 @@ void BKE_pbvh_update_mesh_pointers(PBVH *pbvh, Mesh *mesh)
pbvh->vert_normals = mesh->vert_normals();
pbvh->face_normals = mesh->face_normals();
}
BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
pbvh->vert_data = &mesh->vert_data;
pbvh->loop_data = &mesh->loop_data;
pbvh->face_data = &mesh->face_data;
}
void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
@@ -824,13 +866,14 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
const Span<int> corner_verts = mesh->corner_verts();
pbvh->looptri.reinitialize(looptri_num);
blender::bke::mesh::looptris_calc(vert_positions, faces, corner_verts, pbvh->looptri);
const Span<MLoopTri> looptris = pbvh->looptri;
pbvh->mesh = mesh;
pbvh->header.type = PBVH_FACES;
BKE_pbvh_update_mesh_pointers(pbvh, mesh);
const Span<int> looptri_faces = pbvh->looptri_faces;
/* Those are not set in #BKE_pbvh_update_mesh_pointers because they are owned by the #PBVH. */
pbvh->vert_bitmap = blender::Array<bool>(totvert, false);
@@ -852,17 +895,17 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
BB cb;
BB_reset(&cb);
cb = blender::threading::parallel_reduce(
pbvh->looptri.index_range(),
looptris.index_range(),
1024,
cb,
[&](const blender::IndexRange range, const BB &init) {
BB current = init;
for (const int i : range) {
const MLoopTri &lt = pbvh->looptri[i];
const MLoopTri &lt = looptris[i];
BBC *bbc = &prim_bbc[i];
BB_reset((BB *)bbc);
for (int j = 0; j < 3; j++) {
BB_expand((BB *)bbc, vert_positions[pbvh->corner_verts[lt.tri[j]]]);
BB_expand((BB *)bbc, vert_positions[corner_verts[lt.tri[j]]]);
}
BBC_update_centroid(bbc);
BB_expand(&current, bbc->bcentroid);
@@ -876,14 +919,25 @@ void BKE_pbvh_build_mesh(PBVH *pbvh, Mesh *mesh)
});
if (looptri_num) {
const bool *hide_poly = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->face_data, CD_PROP_BOOL, ".hide_poly"));
const int *material_indices = static_cast<const int *>(
CustomData_get_layer_named(&mesh->face_data, CD_PROP_INT32, "material_index"));
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
&mesh->face_data, CD_PROP_BOOL, "sharp_face");
pbvh_build(pbvh, material_indices, sharp_faces, &cb, prim_bbc, looptri_num);
pbvh_build(pbvh,
corner_verts,
looptris,
looptri_faces,
hide_poly,
material_indices,
sharp_faces,
&cb,
prim_bbc,
looptri_num);
#ifdef TEST_PBVH_FACE_SPLIT
test_face_boundaries(pbvh);
test_face_boundaries(pbvh, looptri_faces);
#endif
}
@@ -920,14 +974,6 @@ void BKE_pbvh_build_grids(PBVH *pbvh, CCGKey *key, Mesh *me, SubdivCCG *subdiv_c
*/
pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), max_grids);
/* We need the base mesh attribute layout for PBVH draw. */
pbvh->vert_data = &me->vert_data;
pbvh->loop_data = &me->loop_data;
pbvh->face_data = &me->face_data;
pbvh->faces = faces;
pbvh->corner_verts = me->corner_verts();
/* We also need the base mesh for PBVH draw. */
pbvh->mesh = me;
@@ -964,7 +1010,8 @@ void BKE_pbvh_build_grids(PBVH *pbvh, CCGKey *key, Mesh *me, SubdivCCG *subdiv_c
CustomData_get_layer_named(&me->face_data, CD_PROP_INT32, "material_index"));
const bool *sharp_faces = (const bool *)CustomData_get_layer_named(
&me->face_data, CD_PROP_BOOL, "sharp_face");
pbvh_build(pbvh, material_indices, sharp_faces, &cb, prim_bbc, grids.size());
pbvh_build(
pbvh, {}, {}, {}, nullptr, material_indices, sharp_faces, &cb, prim_bbc, grids.size());
#ifdef TEST_PBVH_FACE_SPLIT
test_face_boundaries(pbvh);
@@ -1292,8 +1339,8 @@ static void pbvh_faces_update_normals(PBVH *pbvh, Span<PBVHNode *> nodes, Mesh &
using namespace blender;
using namespace blender::bke;
const Span<float3> positions = pbvh->vert_positions;
const OffsetIndices faces = pbvh->faces;
const Span<int> corner_verts = pbvh->corner_verts;
const OffsetIndices faces = mesh.faces();
const Span<int> corner_verts = mesh.corner_verts();
MutableSpan<bool> update_tags = pbvh->vert_bitmap;
@@ -1578,11 +1625,11 @@ static void pbvh_faces_node_visibility_update(const Mesh &mesh, const Span<PBVHN
const VArraySpan<bool> hide_vert = *attributes.lookup<bool>(".hide_vert", ATTR_DOMAIN_POINT);
if (hide_vert.is_empty()) {
for (PBVHNode *node : nodes) {
BKE_pbvh_node_fully_hidden_set(node, false);
BKE_pbvh_node_fully_hidden_set(node, false);
node->flag &= ~PBVH_UpdateVisibility;
}
return;
}
return;
}
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.slice(range)) {
@@ -1600,33 +1647,33 @@ static void pbvh_grids_node_visibility_update(PBVH *pbvh, const Span<PBVHNode *>
using namespace blender;
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.slice(range)) {
CCGElem *const *grids;
const int *grid_indices;
int totgrid, i;
CCGElem *const *grids;
const int *grid_indices;
int totgrid, i;
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, nullptr, &grids);
const Span<const BLI_bitmap *> grid_hidden = pbvh->subdiv_ccg->grid_hidden;
CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, nullptr, nullptr, &grids);
const Span<const BLI_bitmap *> grid_hidden = pbvh->subdiv_ccg->grid_hidden;
CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
for (i = 0; i < totgrid; i++) {
int g = grid_indices[i], x, y;
const BLI_bitmap *gh = grid_hidden[g];
for (i = 0; i < totgrid; i++) {
int g = grid_indices[i], x, y;
const BLI_bitmap *gh = grid_hidden[g];
if (!gh) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
for (y = 0; y < key.grid_size; y++) {
for (x = 0; x < key.grid_size; x++) {
if (!BLI_BITMAP_TEST(gh, y * key.grid_size + x)) {
if (!gh) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
for (y = 0; y < key.grid_size; y++) {
for (x = 0; x < key.grid_size; x++) {
if (!BLI_BITMAP_TEST(gh, y * key.grid_size + x)) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
}
}
}
}
}
BKE_pbvh_node_fully_hidden_set(node, true);
BKE_pbvh_node_fully_hidden_set(node, true);
node->flag &= ~PBVH_UpdateVisibility;
}
});
@@ -1638,20 +1685,20 @@ static void pbvh_bmesh_node_visibility_update(const Span<PBVHNode *> nodes)
threading::parallel_for(nodes.index_range(), 1, [&](const IndexRange range) {
for (PBVHNode *node : nodes.slice(range)) {
for (const BMVert *v : node->bm_unique_verts) {
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
}
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
}
for (const BMVert *v : node->bm_other_verts) {
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
}
if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
BKE_pbvh_node_fully_hidden_set(node, false);
return;
}
}
BKE_pbvh_node_fully_hidden_set(node, true);
BKE_pbvh_node_fully_hidden_set(node, true);
node->flag &= ~PBVH_UpdateVisibility;
}
});
@@ -1872,20 +1919,11 @@ void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, PBVHVertRef vertex)
pbvh->vert_bitmap[vertex.i] = true;
}
void BKE_pbvh_node_get_loops(PBVH *pbvh,
PBVHNode *node,
const int **r_loop_indices,
const int **r_corner_verts)
void BKE_pbvh_node_get_loops(PBVHNode *node, const int **r_loop_indices)
{
BLI_assert(BKE_pbvh_type(pbvh) == PBVH_FACES);
if (r_loop_indices) {
*r_loop_indices = node->loop_indices.data();
}
if (r_corner_verts) {
*r_corner_verts = pbvh->corner_verts.data();
}
}
int BKE_pbvh_num_faces(const PBVH *pbvh)
@@ -2249,6 +2287,8 @@ bool ray_face_nearest_tri(const float ray_start[3],
static bool pbvh_faces_node_raycast(PBVH *pbvh,
const PBVHNode *node,
float (*origco)[3],
const Span<int> corner_verts,
const bool *hide_poly,
const float ray_start[3],
const float ray_normal[3],
IsectRayPrecalc *isect_precalc,
@@ -2258,7 +2298,6 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
float *r_face_normal)
{
const Span<float3> positions = pbvh->vert_positions;
const Span<int> corner_verts = pbvh->corner_verts;
bool hit = false;
float nearest_vertex_co[3] = {0.0f};
@@ -2267,7 +2306,7 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
const MLoopTri *lt = &pbvh->looptri[looptri_i];
const blender::int3 face_verts = node->face_vert_indices[i];
if (pbvh->hide_poly && pbvh->hide_poly[pbvh->looptri_faces[looptri_i]]) {
if (hide_poly && hide_poly[pbvh->looptri_faces[looptri_i]]) {
continue;
}
@@ -2411,6 +2450,8 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
const Span<int> corner_verts,
const bool *hide_poly,
const float ray_start[3],
const float ray_normal[3],
IsectRayPrecalc *isect_precalc,
@@ -2430,6 +2471,8 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
hit |= pbvh_faces_node_raycast(pbvh,
node,
origco,
corner_verts,
hide_poly,
ray_start,
ray_normal,
isect_precalc,
@@ -2600,13 +2643,14 @@ void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh,
static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
const PBVHNode *node,
float (*origco)[3],
const Span<int> corner_verts,
const bool *hide_poly,
const float ray_start[3],
const float ray_normal[3],
float *depth,
float *dist_sq)
{
const Span<float3> positions = pbvh->vert_positions;
const Span<int> corner_verts = pbvh->corner_verts;
bool hit = false;
for (const int i : node->prim_indices.index_range()) {
@@ -2614,7 +2658,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
const MLoopTri *lt = &pbvh->looptri[looptri_i];
const blender::int3 face_verts = node->face_vert_indices[i];
if (pbvh->hide_poly && pbvh->hide_poly[pbvh->looptri_faces[looptri_i]]) {
if (hide_poly && hide_poly[pbvh->looptri_faces[looptri_i]]) {
continue;
}
@@ -2709,6 +2753,8 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
const Span<int> corner_verts,
const bool *hide_poly,
const float ray_start[3],
const float ray_normal[3],
float *depth,
@@ -2723,7 +2769,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
switch (pbvh->header.type) {
case PBVH_FACES:
hit |= pbvh_faces_node_nearest_to_ray(
pbvh, node, origco, ray_start, ray_normal, depth, dist_sq);
pbvh, node, origco, corner_verts, hide_poly, ray_start, ray_normal, depth, dist_sq);
break;
case PBVH_GRIDS:
hit |= pbvh_grids_node_nearest_to_ray(
@@ -3078,10 +3124,10 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
vi->mask = 0.0f;
if (pbvh->header.type == PBVH_FACES) {
vi->vert_normals = pbvh->vert_normals;
vi->hide_vert = pbvh->hide_vert;
vi->hide_vert = static_cast<const bool *>(
CustomData_get_layer_named(&pbvh->mesh->vert_data, CD_PROP_BOOL, ".hide_vert"));
vi->vmask = static_cast<const float *>(
CustomData_get_layer_named(pbvh->vert_data, CD_PROP_FLOAT, ".sculpt_mask"));
CustomData_get_layer_named(&pbvh->mesh->vert_data, CD_PROP_FLOAT, ".sculpt_mask"));
}
}
@@ -3154,49 +3200,11 @@ const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]
return reinterpret_cast<const float(*)[3]>(pbvh->vert_normals.data());
}
const bool *BKE_pbvh_get_vert_hide(const PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_FACES);
return pbvh->hide_vert;
}
const bool *BKE_pbvh_get_poly_hide(const PBVH *pbvh)
{
BLI_assert(ELEM(pbvh->header.type, PBVH_FACES, PBVH_GRIDS));
return pbvh->hide_poly;
}
bool *BKE_pbvh_get_vert_hide_for_write(PBVH *pbvh)
{
BLI_assert(pbvh->header.type == PBVH_FACES);
if (pbvh->hide_vert) {
return pbvh->hide_vert;
}
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
&pbvh->mesh->vert_data, CD_PROP_BOOL, ".hide_vert", pbvh->mesh->totvert));
if (pbvh->hide_vert) {
return pbvh->hide_vert;
}
pbvh->hide_vert = static_cast<bool *>(CustomData_add_layer_named(
&pbvh->mesh->vert_data, CD_PROP_BOOL, CD_SET_DEFAULT, pbvh->mesh->totvert, ".hide_vert"));
return pbvh->hide_vert;
}
void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
pbvh->subdiv_ccg = subdiv_ccg;
}
void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh)
{
if (pbvh->header.type == PBVH_FACES) {
pbvh->hide_vert = static_cast<bool *>(CustomData_get_layer_named_for_write(
&pbvh->mesh->vert_data, CD_PROP_BOOL, ".hide_vert", pbvh->mesh->totvert));
pbvh->hide_poly = static_cast<bool *>(CustomData_get_layer_named_for_write(
&pbvh->mesh->face_data, CD_PROP_BOOL, ".hide_poly", pbvh->mesh->faces_num));
}
}
bool BKE_pbvh_is_drawing(const PBVH *pbvh)
{
return pbvh->is_drawing;
@@ -3292,7 +3300,6 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
switch (pbvh->header.type) {
case PBVH_FACES: {
BKE_mesh_flush_hidden_from_verts(mesh);
BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
break;
}
case PBVH_BMESH: {
@@ -3353,7 +3360,6 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
}
BKE_mesh_flush_hidden_from_faces(mesh);
BKE_pbvh_update_hide_attributes_from_mesh(pbvh);
break;
}
}

View File

@@ -164,17 +164,12 @@ struct PBVH {
blender::Span<blender::float3> vert_normals;
blender::Span<blender::float3> face_normals;
blender::OffsetIndices<int> faces;
bool *hide_vert;
bool *hide_poly;
/** Only valid for polygon meshes. */
blender::OffsetIndices<int> faces;
blender::Span<int> corner_verts;
/* Owned by the #PBVH, because after deformations they have to be recomputed. */
blender::Array<MLoopTri> looptri;
blender::Span<int> looptri_faces;
CustomData *vert_data;
CustomData *loop_data;
CustomData *face_data;
/* Grid Data */
CCGKey gridkey;

View File

@@ -667,7 +667,8 @@ static bool update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
const AttributeAccessor attributes = mesh->attributes();
const VArraySpan uv_map = *attributes.lookup<float2>(active_uv_name, ATTR_DOMAIN_CORNER);
uv_islands::MeshData mesh_data(pbvh->looptri, pbvh->corner_verts, uv_map, pbvh->vert_positions);
uv_islands::MeshData mesh_data(
pbvh->looptri, mesh->corner_verts(), uv_map, pbvh->vert_positions);
uv_islands::UVIslands islands(mesh_data);
uv_islands::UVIslandsMask uv_masks;

View File

@@ -38,7 +38,6 @@ struct PBVH_GPU_Args {
BMesh *bm;
const Mesh *me;
blender::MutableSpan<blender::float3> vert_positions;
blender::OffsetIndices<int> faces;
blender::Span<int> corner_verts;
blender::Span<int> corner_edges;
const CustomData *vert_data;

View File

@@ -211,7 +211,6 @@ static void partialvis_update_mesh(Object &object,
}
BKE_mesh_flush_hidden_from_verts(&mesh);
BKE_pbvh_update_hide_attributes_from_mesh(&pbvh);
}
/* Hide or show elements in multires grids with a special GridFlags

View File

@@ -406,7 +406,9 @@ bool SCULPT_vertex_visible_get(const SculptSession *ss, PBVHVertRef vertex)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
const bool *hide_vert = BKE_pbvh_get_vert_hide(ss->pbvh);
const Mesh *mesh = BKE_pbvh_get_mesh(ss->pbvh);
const bool *hide_vert = static_cast<const bool *>(
CustomData_get_layer_named(&mesh->vert_data, CD_PROP_BOOL, ".hide_vert"));
return hide_vert == nullptr || !hide_vert[vertex.i];
}
case PBVH_BMESH:
@@ -659,7 +661,6 @@ void SCULPT_visibility_sync_all_from_faces(Object *ob)
/* We may have adjusted the ".hide_poly" attribute, now make the hide status attributes for
* vertices and edges consistent. */
BKE_mesh_flush_hidden_from_faces(mesh);
BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
break;
}
case PBVH_GRIDS: {
@@ -3103,6 +3104,8 @@ struct SculptRaycastData {
bool hit;
float depth;
bool original;
Span<int> corner_verts;
const bool *hide_poly;
PBVHVertRef active_vertex;
float *face_normal;
@@ -3119,6 +3122,8 @@ struct SculptFindNearestToRayData {
float depth;
float dist_sq_to_ray;
bool original;
Span<int> corner_verts;
const bool *hide_poly;
};
ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3])
@@ -4978,6 +4983,8 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
node,
origco,
use_origco,
srd->corner_verts,
srd->hide_poly,
srd->ray_start,
srd->ray_normal,
&srd->isect_precalc,
@@ -5016,6 +5023,8 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
node,
origco,
use_origco,
srd->corner_verts,
srd->hide_poly,
srd->ray_start,
srd->ray_normal,
&srd->depth,
@@ -5104,6 +5113,12 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
srd.original = original;
srd.ss = ob->sculpt;
srd.hit = false;
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
srd.corner_verts = mesh.corner_verts();
srd.hide_poly = static_cast<const bool *>(
CustomData_get_layer_named(&mesh.face_data, CD_PROP_BOOL, ".hide_poly"));
}
srd.ray_start = ray_start;
srd.ray_normal = ray_normal;
srd.depth = depth;
@@ -5244,6 +5259,12 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
srd.ray_start = ray_start;
srd.ray_normal = ray_normal;
srd.hit = false;
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
srd.corner_verts = mesh.corner_verts();
srd.hide_poly = static_cast<const bool *>(
CustomData_get_layer_named(&mesh.face_data, CD_PROP_BOOL, ".hide_poly"));
}
srd.depth = depth;
srd.original = original;
srd.face_normal = face_normal;
@@ -5266,6 +5287,12 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
srd.original = original;
srd.ss = ob->sculpt;
srd.hit = false;
if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES) {
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
srd.corner_verts = mesh.corner_verts();
srd.hide_poly = static_cast<const bool *>(
CustomData_get_layer_named(&mesh.face_data, CD_PROP_BOOL, ".hide_poly"));
}
srd.ray_start = ray_start;
srd.ray_normal = ray_normal;
srd.depth = FLT_MAX;

View File

@@ -1325,15 +1325,6 @@ static int sculpt_reveal_all_exec(bContext *C, wmOperator *op)
}
SCULPT_visibility_sync_all_from_faces(ob);
/* NOTE: #SCULPT_visibility_sync_all_from_faces may have deleted
* `pbvh->hide_vert` if hide_poly did not exist, which is why
* we call #BKE_pbvh_update_hide_attributes_from_mesh here instead of
* after #CustomData_free_layer_named above. */
if (!with_bmesh) {
BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
}
BKE_pbvh_update_visibility(ss->pbvh);
SCULPT_undo_push_end(ob);

View File

@@ -494,6 +494,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool *modified_vertices)
{
using namespace blender;
const Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
BKE_view_layer_synced_ensure(scene, view_layer);
@@ -501,17 +502,20 @@ static bool sculpt_undo_restore_hidden(bContext *C, SculptUndoNode *unode, bool
SculptSession *ss = ob->sculpt;
SubdivCCG *subdiv_ccg = ss->subdiv_ccg;
bool *hide_vert = BKE_pbvh_get_vert_hide_for_write(ss->pbvh);
if (unode->maxvert) {
for (int i = 0; i < unode->totvert; i++) {
const int vert_index = unode->index[i];
if (unode->vert_hidden[i].test() != hide_vert[vert_index]) {
Mesh &mesh = *static_cast<Mesh *>(ob->data);
bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
".hide_vert", ATTR_DOMAIN_POINT);
for (const int i : unode->index.index_range()) {
const int vert = unode->index[i];
if (unode->vert_hidden[i].test() != hide_vert.span[vert]) {
unode->vert_hidden[i].set(!unode->vert_hidden[i].test());
hide_vert[vert_index] = !hide_vert[vert_index];
modified_vertices[vert_index] = true;
hide_vert.span[vert] = !hide_vert.span[vert];
modified_vertices[vert] = true;
}
}
hide_vert.finish();
}
else if (unode->maxgrid && subdiv_ccg != nullptr) {
blender::MutableSpan<BLI_bitmap *> grid_hidden = subdiv_ccg->grid_hidden;
@@ -1366,22 +1370,23 @@ static void sculpt_undo_store_coords(Object *ob, SculptUndoNode *unode)
static void sculpt_undo_store_hidden(Object *ob, SculptUndoNode *unode)
{
PBVH *pbvh = ob->sculpt->pbvh;
PBVHNode *node = static_cast<PBVHNode *>(unode->node);
const bool *hide_vert = BKE_pbvh_get_vert_hide(pbvh);
if (hide_vert == nullptr) {
return;
}
using namespace blender;
using namespace blender::bke;
if (!unode->grids.is_empty()) {
/* Already stored during allocation. */
}
else {
const blender::Span<int> verts = BKE_pbvh_node_get_vert_indices(node);
for (const int i : verts.index_range())
unode->vert_hidden[i].set(hide_vert[verts[i]]);
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
const AttributeAccessor attributes = mesh.attributes();
const VArraySpan<bool> hide_vert = *attributes.lookup<bool>(".hide_vert", ATTR_DOMAIN_POINT);
if (hide_vert.is_empty()) {
return;
}
PBVHNode *node = static_cast<PBVHNode *>(unode->node);
const blender::Span<int> verts = BKE_pbvh_node_get_vert_indices(node);
for (const int i : verts.index_range())
unode->vert_hidden[i].set(hide_vert[verts[i]]);
}
static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode)
@@ -1563,8 +1568,7 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
const int *loop_indices;
int allloop;
BKE_pbvh_node_num_loops(ss->pbvh, static_cast<PBVHNode *>(unode->node), &allloop);
BKE_pbvh_node_get_loops(
ss->pbvh, static_cast<PBVHNode *>(unode->node), &loop_indices, nullptr);
BKE_pbvh_node_get_loops(static_cast<PBVHNode *>(unode->node), &loop_indices);
if (allloop) {
unode->loop_index.as_mutable_span().copy_from({loop_indices, allloop});