[Bf-blender-cvs] [df788ecfd95] blender-v3.4-release: Sculpt: Standardize face set undo steps, optimize memory usage
Joseph Eagar
noreply at git.blender.org
Tue Nov 22 21:14:21 CET 2022
Commit: df788ecfd95f6c741249923e45a7a00fe62cc9ec
Author: Joseph Eagar
Date: Tue Nov 22 11:37:20 2022 -0800
Branches: blender-v3.4-release
https://developer.blender.org/rBdf788ecfd95f6c741249923e45a7a00fe62cc9ec
Sculpt: Standardize face set undo steps, optimize memory usage
Currently the face set of every single face is saved for every sculpt undo step.
When only changing the face sets of a small section of the mesh, this can be quite
wasteful. It also makes face sets a special case compare to all other sculpt undo step
types, which makes the whole system more complex and harder to improve.
Fixes T101203.
Reviewed By: Hans Goudey
Differential Revision: https://developer.blender.org/D16224
Ref D16224
===================================================================
M .clang-format
M source/blender/blenkernel/BKE_pbvh.h
M source/blender/blenkernel/intern/pbvh.c
M source/blender/blenkernel/intern/pbvh_intern.h
M source/blender/editors/sculpt_paint/paint_mask.c
M source/blender/editors/sculpt_paint/sculpt.c
M source/blender/editors/sculpt_paint/sculpt_automasking.cc
M source/blender/editors/sculpt_paint/sculpt_expand.c
M source/blender/editors/sculpt_paint/sculpt_face_set.cc
M source/blender/editors/sculpt_paint/sculpt_intern.h
M source/blender/editors/sculpt_paint/sculpt_mask_expand.c
M source/blender/editors/sculpt_paint/sculpt_undo.c
===================================================================
diff --git a/.clang-format b/.clang-format
index 72add4594a4..4c140988720 100644
--- a/.clang-format
+++ b/.clang-format
@@ -162,6 +162,7 @@ PenaltyBreakString: 1000000
ForEachMacros:
- BEGIN_ANIMFILTER_SUBCHANNELS
- BKE_pbvh_vertex_iter_begin
+ - BKE_pbvh_face_iter_begin
- BLI_FOREACH_SPARSE_RANGE
- BLI_SMALLSTACK_ITER_BEGIN
- BMO_ITER
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 13ff0c6d5b3..d256ca81ec6 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -69,14 +69,22 @@ struct PBVHPublic {
* intptr_t's in structs.
*/
+/* A generic PBVH vertex.
+ *
+ * Note: in PBVH_GRIDS we consider the final grid points
+ * to be vertices. This is not true of edges or faces which are pulled from
+ * the base mesh.
+ */
typedef struct PBVHVertRef {
intptr_t i;
} PBVHVertRef;
+/* Note: edges in PBVH_GRIDS are always pulled from the base mesh.*/
typedef struct PBVHEdgeRef {
intptr_t i;
} PBVHEdgeRef;
+/* Note: faces in PBVH_GRIDS are always puled from the base mesh.*/
typedef struct PBVHFaceRef {
intptr_t i;
} PBVHFaceRef;
@@ -434,6 +442,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
void BKE_pbvh_node_mark_update(PBVHNode *node);
void BKE_pbvh_node_mark_update_mask(PBVHNode *node);
void BKE_pbvh_node_mark_update_color(PBVHNode *node);
+void BKE_pbvh_node_mark_update_face_sets(PBVHNode *node);
void BKE_pbvh_node_mark_update_visibility(PBVHNode *node);
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
void BKE_pbvh_node_mark_redraw(PBVHNode *node);
@@ -466,6 +475,11 @@ void BKE_pbvh_node_get_loops(PBVH *pbvh,
const int **r_loop_indices,
const struct MLoop **r_loops);
+/* Get number of faces in the mesh; for PBVH_GRIDS the
+ * number of base mesh faces is returned.
+ */
+int BKE_pbvh_num_faces(const PBVH *pbvh);
+
void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3]);
@@ -665,6 +679,57 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
} \
((void)0)
+#define PBVH_FACE_ITER_VERTS_RESERVED 8
+
+typedef struct PBVHFaceIter {
+ PBVHFaceRef face;
+ int index;
+ bool *hide;
+ int *face_set;
+ int i;
+
+ PBVHVertRef *verts;
+ int verts_num;
+
+ /* Private. */
+#ifdef __cplusplus
+ private:
+#endif
+
+ PBVHVertRef verts_reserved_[PBVH_FACE_ITER_VERTS_RESERVED];
+ const PBVHNode *node_;
+ PBVHType pbvh_type_;
+ int verts_size_;
+ GSetIterator bm_faces_iter_;
+ int cd_hide_poly_, cd_face_set_;
+ bool *hide_poly_;
+ int *face_sets_;
+ const struct MPoly *mpoly_;
+ const struct MLoopTri *looptri_;
+ const struct MLoop *mloop_;
+ int prim_index_;
+ const struct SubdivCCG *subdiv_ccg_;
+ const struct BMesh *bm;
+
+ int last_face_index_;
+} PBVHFaceIter;
+
+void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd);
+void BKE_pbvh_face_iter_step(PBVHFaceIter *fd);
+bool BKE_pbvh_face_iter_done(PBVHFaceIter *fd);
+void BKE_pbvh_face_iter_finish(PBVHFaceIter *fd);
+
+/** Iterate over faces inside a PBVHNode. These are either base mesh faces
+ * (for PBVH_FACES and PBVH_GRIDS) or BMesh faces (for PBVH_BMESH).
+ */
+#define BKE_pbvh_face_iter_begin(pbvh, node, fd) \
+ BKE_pbvh_face_iter_init(pbvh, node, &fd); \
+ for (; !BKE_pbvh_face_iter_done(&fd); BKE_pbvh_face_iter_step(&fd)) {
+
+#define BKE_pbvh_face_iter_end(fd) \
+ } \
+ BKE_pbvh_face_iter_finish(&fd)
+
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
void BKE_pbvh_node_free_proxies(PBVHNode *node);
PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 934871d22eb..9195683f70c 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -746,6 +746,7 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
pbvh->vdata = vdata;
pbvh->ldata = ldata;
pbvh->pdata = pdata;
+ pbvh->faces_num = mesh->totpoly;
pbvh->face_sets_color_seed = mesh->face_sets_color_seed;
pbvh->face_sets_color_default = mesh->face_sets_color_default;
@@ -833,6 +834,7 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->gridkey = *key;
pbvh->grid_hidden = grid_hidden;
pbvh->subdiv_ccg = subdiv_ccg;
+ pbvh->faces_num = me->totpoly;
/* Find maximum number of grids per face. */
int max_grids = 1;
@@ -853,6 +855,9 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->ldata = &me->ldata;
pbvh->pdata = &me->pdata;
+ pbvh->mpoly = BKE_mesh_polys(me);
+ pbvh->mloop = BKE_mesh_loops(me);
+
/* We also need the base mesh for PBVH draw. */
pbvh->mesh = me;
@@ -2015,6 +2020,11 @@ void BKE_pbvh_node_mark_update_color(PBVHNode *node)
node->flag |= PBVH_UpdateColor | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
}
+void BKE_pbvh_node_mark_update_face_sets(PBVHNode *node)
+{
+ node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
+}
+
void BKE_pbvh_mark_rebuild_pixels(PBVH *pbvh)
{
for (int n = 0; n < pbvh->totnode; n++) {
@@ -2119,6 +2129,20 @@ void BKE_pbvh_node_get_loops(PBVH *pbvh,
}
}
+int BKE_pbvh_num_faces(const PBVH *pbvh)
+{
+ switch (pbvh->header.type) {
+ case PBVH_GRIDS:
+ case PBVH_FACES:
+ return pbvh->faces_num;
+ case PBVH_BMESH:
+ return pbvh->header.bm->totface;
+ }
+
+ BLI_assert_unreachable();
+ return 0;
+}
+
void BKE_pbvh_node_get_verts(PBVH *pbvh,
PBVHNode *node,
const int **r_vert_indices,
@@ -3611,3 +3635,184 @@ void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
}
}
}
+
+static void pbvh_face_iter_verts_reserve(PBVHFaceIter *fd, int verts_num)
+{
+ if (verts_num >= fd->verts_size_) {
+ fd->verts_size_ = (verts_num + 1) << 2;
+
+ if (fd->verts != fd->verts_reserved_) {
+ MEM_SAFE_FREE(fd->verts);
+ }
+
+ fd->verts = MEM_malloc_arrayN(fd->verts_size_, sizeof(void *), __func__);
+ }
+
+ fd->verts_num = verts_num;
+}
+
+BLI_INLINE int face_iter_prim_to_face(PBVHFaceIter *fd, int prim_index)
+{
+ if (fd->subdiv_ccg_) {
+ return BKE_subdiv_ccg_grid_to_face_index(fd->subdiv_ccg_, prim_index);
+ }
+ else {
+ return fd->looptri_[prim_index].poly;
+ }
+}
+
+void pbvh_face_iter_step(PBVHFaceIter *fd, bool do_step)
+{
+ if (do_step) {
+ fd->i++;
+ }
+
+ switch (fd->pbvh_type_) {
+ case PBVH_BMESH: {
+ if (do_step) {
+ BLI_gsetIterator_step(&fd->bm_faces_iter_);
+ if (BLI_gsetIterator_done(&fd->bm_faces_iter_)) {
+ return;
+ }
+ }
+
+ BMFace *f = (BMFace *)BLI_gsetIterator_getKey(&fd->bm_faces_iter_);
+ fd->face.i = (intptr_t)f;
+ fd->index = f->head.index;
+
+ if (fd->cd_face_set_ != -1) {
+ fd->face_set = (int *)BM_ELEM_CD_GET_VOID_P(f, fd->cd_face_set_);
+ }
+
+ if (fd->cd_hide_poly_ != -1) {
+ fd->hide = (bool *)BM_ELEM_CD_GET_VOID_P(f, fd->cd_hide_poly_);
+ }
+
+ pbvh_face_iter_verts_reserve(fd, f->len);
+ int vertex_i = 0;
+
+ BMLoop *l = f->l_first;
+ do {
+ fd->verts[vertex_i++].i = (intptr_t)l->v;
+ } while ((l = l->next) != f->l_first);
+
+ break;
+ }
+ case PBVH_GRIDS:
+ case PBVH_FACES: {
+ int face_index = 0;
+
+ if (do_step) {
+ fd->prim_index_++;
+
+ while (fd->prim_index_ < fd->node_->totprim) {
+ face_index = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
+
+ if (face_index != fd->last_face_index_) {
+ break;
+ }
+
+ fd->prim_index_++;
+ }
+ }
+ else if (fd->prim_index_ < fd->node_->totprim) {
+ face_index = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
+ }
+
+ if (fd->prim_index_ >= fd->node_->totprim) {
+ return;
+ }
+
+ fd->last_face_index_ = face_index;
+ const MPoly *mp = fd->mpoly_ + face_index;
+
+ fd->face.i = fd->index = face_index;
+
+ if (fd->face_sets_) {
+ fd->face_set = fd->face_sets_ + face_index;
+ }
+ if (fd->hide_poly_) {
+ fd->hide = fd->hide_poly_ + face_index;
+ }
+
+ pbvh_face_iter_verts_reserve(fd, mp->totloop);
+
+ const MLoop *ml = fd->mloop_ + mp->loopstart;
+ for (int i = 0; i < mp->totloop; i++, ml++) {
+ if (fd->pbvh_type_ == PBVH_GRIDS) {
+ /* Grid corners. */
+ fd->verts[i].i = mp->loopstart + i;
+ }
+ else {
+ fd->verts[i].i = ml->v;
+ }
+ }
+
+ break;
+ }
+ }
+}
+
+void BKE_pbvh_face_iter_step(PBVHFaceIter *fd)
+{
+ pbvh_face_iter_step(fd, true);
+}
+
+void BKE_pbvh_face_iter_init(PBVH *pbvh, PBVHNode *node, PBVHFaceIter *fd)
+{
+ memset(fd, 0, sizeof(*fd));
+
+ fd->node_ = node;
+ fd->pbvh_type_ = BKE_pbvh_type(pbvh);
+
+ fd->verts = fd->verts_reserved_;
+ fd->verts_size_ = PBVH_FACE_ITER_VERTS_RESERVED;
+
+ switch (BKE_pbvh_type(pbvh)) {
+ case PBVH_GRIDS:
+ fd->subdiv_ccg_ = pbvh->subdiv_ccg;
+ case PBVH_FACES:
+ fd->mpoly_ = pbvh->mpoly;
+ fd->mloop_ = pbvh->mloop;
+ fd->looptri_ = pbvh->looptri;
+ fd->hide_poly_ = pbvh->hide_poly;
+ fd->face_sets_ = pbvh->face_sets;
+ fd->last_face_index_ = -1;
+
+ break;
+ case PBVH_BMESH:
+ fd->bm = pbvh->header.bm;
+ fd->cd_face_set_ = CustomData_get_offset_named(
+ &pbvh->header.bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
+ fd->cd_hide_poly_ = CustomData_get_offset_named(
+ &pbvh->header.bm->pdata, CD_PROP_INT32, ".hide_poly");
+
+ BLI_gsetIterator_init(&fd->bm_faces_iter_, node->bm_faces);
+ break;
+ }
+
+ if (!BKE_pbvh_face_iter_done(fd)) {
+ pbvh_face_iter_step(fd, false);
+ }
+}
+
+void BKE_pbvh_face_iter_finish(PBVHFaceIter *fd)
+{
+ if (fd->verts != fd->verts_reserved_) {
+ MEM_SAFE_FREE(fd->verts);
+ }
+}
+
+bool BKE_pbvh_face_iter_done(PBVHFaceIter *fd)
+{
+ switch (fd->pbvh_type_) {
+ case PBVH_FACES:
+ case PBVH_GRIDS:
+ ret
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list