Cleanup: Sculpt: Simplify face and face set iteration

This commit removes knowledge about face sets from the PBVH,
and changes iteration over faces to not depend on the PBVH face
iterator abstraction. Though this adds slightly more boilerplate to
iteration over faces, it makes the whole process more data oriented
and allows use of index-based utilities like `gather` and `scatter`
in the mesh case, and simpler iteration over BMesh faces for
dynamic topology.

Setting face sets is now specialized per PBVH type in a few places
in a similar way. The general goal is to reduce branching and function
calls at the lowest level of hot loops, and to make code more aware
of the data structures it uses, both for performance and clarity.

Since the remaining uses of the face iterator are removed,
the iterator itself is removed too.

Related commits:
- 97f2b01ea9
- 756dea7ca1
- a6a2af5fdd

Pull Request: https://projects.blender.org/blender/blender/pulls/114417
This commit is contained in:
Hans Goudey
2023-11-03 10:27:38 +01:00
committed by Hans Goudey
parent a7e6341e4e
commit 44b79af4fc
8 changed files with 141 additions and 402 deletions

View File

@@ -413,6 +413,7 @@ void BKE_pbvh_node_get_loops(PBVH *pbvh,
PBVHNode *node,
const int **r_loop_indices,
const int **r_corner_verts);
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
* number of base mesh faces is returned.
@@ -462,7 +463,6 @@ void BKE_pbvh_grids_update(PBVH *pbvh,
unsigned int **grid_hidden,
CCGKey *key);
void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg);
void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets);
/**
* If an operation causes the hide status stored in the mesh to change, this must be called
@@ -607,52 +607,6 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m
#define PBVH_FACE_ITER_VERTS_RESERVED 8
struct PBVHFaceIter {
PBVHFaceRef face;
int index;
bool *hide;
int *face_set;
int i;
PBVHVertRef *verts;
int verts_num;
PBVHVertRef verts_reserved_[PBVH_FACE_ITER_VERTS_RESERVED];
const PBVHNode *node_;
PBVHType pbvh_type_;
int verts_size_;
std::optional<blender::Set<BMFace *, 0>::Iterator> bm_faces_iter_;
int cd_hide_poly_, cd_face_set_;
bool *hide_poly_;
int *face_sets_;
blender::OffsetIndices<int> face_offsets_;
blender::Span<int> looptri_faces_;
blender::Span<int> corner_verts_;
int prim_index_;
const SubdivCCG *subdiv_ccg_;
const BMesh *bm;
CCGKey subdiv_key_;
int last_face_index_;
};
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);

View File

@@ -1753,7 +1753,6 @@ static void sculpt_update_object(
UNUSED_VARS_NDEBUG(pbvh);
BKE_pbvh_subdiv_cgg_set(ss->pbvh, ss->subdiv_ccg);
BKE_pbvh_face_sets_set(ss->pbvh, ss->face_sets);
BKE_pbvh_update_hide_attributes_from_mesh(ss->pbvh);
sculpt_attribute_update_refs(ob);
@@ -1970,11 +1969,8 @@ int *BKE_sculpt_face_sets_ensure(Object *ob)
AttributeInitVArray(VArray<int>::ForSingle(1, mesh->faces_num)));
mesh->face_sets_color_default = 1;
}
int *face_sets = static_cast<int *>(CustomData_get_layer_named_for_write(
return static_cast<int *>(CustomData_get_layer_named_for_write(
&mesh->face_data, CD_PROP_INT32, name.c_str(), mesh->faces_num));
BKE_pbvh_face_sets_set(pbvh, face_sets);
return face_sets;
}
case PBVH_BMESH: {
BMesh *bm = BKE_pbvh_get_bmesh(pbvh);

View File

@@ -679,6 +679,8 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
args->hide_poly = pbvh->face_data ? static_cast<const bool *>(CustomData_get_layer_named(
pbvh->face_data, CD_PROP_BOOL, ".hide_poly")) :
nullptr;
args->face_sets = static_cast<const int *>(
CustomData_get_layer_named(&pbvh->mesh->face_data, CD_PROP_INT32, ".sculpt_face_set"));
}
args->active_color = mesh.active_color_attribute;
@@ -695,7 +697,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
args->face_normals = pbvh->face_normals;
args->prim_indices = node->prim_indices;
args->face_sets = pbvh->face_sets;
args->looptri_faces = pbvh->looptri_faces;
break;
case PBVH_GRIDS:
@@ -706,7 +707,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
args->me = pbvh->mesh;
args->grid_indices = node->prim_indices;
args->subdiv_ccg = pbvh->subdiv_ccg;
args->face_sets = pbvh->face_sets;
args->faces = pbvh->faces;
args->mesh_grids_num = pbvh->totgrid;
@@ -714,7 +714,6 @@ static void pbvh_draw_args_init(const Mesh &mesh, PBVH *pbvh, PBVH_GPU_Args *arg
args->grid_flag_mats = pbvh->grid_flag_mats;
args->vert_normals = pbvh->vert_normals;
args->face_sets = pbvh->face_sets;
args->looptri_faces = pbvh->looptri_faces;
break;
case PBVH_BMESH:
@@ -1972,6 +1971,42 @@ blender::Span<int> BKE_pbvh_node_get_unique_vert_indices(const PBVHNode *node)
return node->vert_indices.as_span().take_front(node->uniq_verts);
}
blender::Vector<int> BKE_pbvh_node_calc_face_indices(const PBVH &pbvh, const PBVHNode &node)
{
Vector<int> faces;
switch (pbvh.header.type) {
case PBVH_FACES: {
const Span<int> looptri_faces = pbvh.looptri_faces;
int prev_face = -1;
for (const int tri : node.prim_indices) {
const int face = looptri_faces[tri];
if (face != prev_face) {
faces.append(face);
prev_face = face;
}
}
break;
}
case PBVH_GRIDS: {
const SubdivCCG &subdiv_ccg = *pbvh.subdiv_ccg;
int prev_face = -1;
for (const int prim : node.prim_indices) {
const int face = BKE_subdiv_ccg_grid_to_face_index(&subdiv_ccg, prim);
if (face != prev_face) {
faces.append(face);
prev_face = face;
}
}
break;
}
case PBVH_BMESH:
BLI_assert_unreachable();
break;
}
return faces;
}
void BKE_pbvh_node_num_verts(const PBVH *pbvh,
const PBVHNode *node,
int *r_uniquevert,
@@ -3243,11 +3278,6 @@ void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg)
pbvh->subdiv_ccg = subdiv_ccg;
}
void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets)
{
pbvh->face_sets = face_sets;
}
void BKE_pbvh_update_hide_attributes_from_mesh(PBVH *pbvh)
{
if (pbvh->header.type == PBVH_FACES) {
@@ -3346,190 +3376,6 @@ int BKE_pbvh_debug_draw_gen_get(PBVHNode *node)
return node->debug_draw_gen;
}
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 = static_cast<PBVHVertRef *>(
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);
}
return fd->looptri_faces_[prim_index];
}
static 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) {
(*fd->bm_faces_iter_)++;
if (*fd->bm_faces_iter_ == fd->node_->bm_faces.end()) {
return;
}
}
BMFace *f = **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_i = 0;
if (do_step) {
fd->prim_index_++;
while (fd->prim_index_ < fd->node_->prim_indices.size()) {
face_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
if (face_i != fd->last_face_index_) {
break;
}
fd->prim_index_++;
}
}
else if (fd->prim_index_ < fd->node_->prim_indices.size()) {
face_i = face_iter_prim_to_face(fd, fd->node_->prim_indices[fd->prim_index_]);
}
if (fd->prim_index_ >= fd->node_->prim_indices.size()) {
return;
}
fd->last_face_index_ = face_i;
const int poly_start = fd->face_offsets_[face_i].start();
const int poly_size = fd->face_offsets_[face_i].size();
fd->face.i = fd->index = face_i;
if (fd->face_sets_) {
fd->face_set = fd->face_sets_ + face_i;
}
if (fd->hide_poly_) {
fd->hide = fd->hide_poly_ + face_i;
}
pbvh_face_iter_verts_reserve(fd, poly_size);
const int *face_verts = &fd->corner_verts_[poly_start];
const int grid_area = fd->subdiv_key_.grid_area;
for (int i = 0; i < poly_size; i++) {
if (fd->pbvh_type_ == PBVH_GRIDS) {
/* Grid corners. */
fd->verts[i].i = (poly_start + i) * grid_area + grid_area - 1;
}
else {
fd->verts[i].i = face_verts[i];
}
}
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)
{
*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;
fd->subdiv_key_ = pbvh->gridkey;
ATTR_FALLTHROUGH;
case PBVH_FACES:
fd->face_offsets_ = pbvh->faces;
fd->corner_verts_ = pbvh->corner_verts;
fd->looptri_faces_ = pbvh->looptri_faces;
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");
fd->bm_faces_iter_ = node->bm_faces.begin();
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:
return fd->prim_index_ >= fd->node_->prim_indices.size();
case PBVH_BMESH:
return *fd->bm_faces_iter_ == fd->node_->bm_faces.end();
default:
BLI_assert_unreachable();
return true;
}
}
void BKE_pbvh_sync_visibility_from_verts(PBVH *pbvh, Mesh *mesh)
{
using namespace blender;

View File

@@ -177,8 +177,6 @@ struct PBVH {
CustomData *loop_data;
CustomData *face_data;
int *face_sets;
/* Grid Data */
CCGKey gridkey;
CCGElem **grids;

View File

@@ -56,6 +56,8 @@
/* For undo push. */
#include "sculpt_intern.hh"
using blender::float3;
using blender::OffsetIndices;
using blender::Span;
using blender::Vector;
@@ -626,11 +628,10 @@ static bool sculpt_gesture_is_effected_lasso(SculptGestureContext *sgcontext, co
return BLI_BITMAP_TEST_BOOL(lasso->mask_px, scr_co_s[1] * lasso->width + scr_co_s[0]);
}
static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, PBVHVertRef vertex)
static bool sculpt_gesture_is_effected(SculptGestureContext *sgcontext,
const float3 &co,
const float3 &vertex_normal)
{
float vertex_normal[3];
const float *co = SCULPT_vertex_co_get(sgcontext->ss, vertex);
SCULPT_vertex_normal_get(sgcontext->ss, vertex, vertex_normal);
float dot = dot_v3v3(sgcontext->view_normal, vertex_normal);
const bool is_effected_front_face = !(sgcontext->front_faces_only && dot < 0.0f);
@@ -654,17 +655,6 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P
return false;
}
static bool sculpt_gesture_is_face_effected(SculptGestureContext *sgcontext, PBVHFaceIter *fd)
{
for (int i = 0; i < fd->verts_num; i++) {
if (sculpt_gesture_is_vertex_effected(sgcontext, fd->verts[i])) {
return true;
}
}
return false;
}
static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext, wmOperator *op)
{
SculptGestureOperation *operation = sgcontext->operation;
@@ -705,23 +695,61 @@ static void sculpt_gesture_face_set_begin(bContext *C, SculptGestureContext *sgc
static void face_set_gesture_apply_task(SculptGestureContext *sgcontext, PBVHNode *node)
{
using namespace blender;
SculptGestureFaceSetOperation *face_set_operation = (SculptGestureFaceSetOperation *)
sgcontext->operation;
bool any_updated = false;
SculptSession &ss = *sgcontext->ss;
const PBVH &pbvh = *sgcontext->ss->pbvh;
SCULPT_undo_push_node(sgcontext->vc.obact, node, SCULPT_UNDO_FACE_SETS);
PBVHFaceIter fd;
BKE_pbvh_face_iter_begin (sgcontext->ss->pbvh, node, fd) {
if (sculpt_gesture_is_face_effected(sgcontext, &fd)) {
if (sgcontext->ss->hide_poly && sgcontext->ss->hide_poly[fd.face.i]) {
continue;
const int new_face_set = face_set_operation->new_face_set_id;
bool any_updated = false;
switch (BKE_pbvh_type(&pbvh)) {
case PBVH_GRIDS:
case PBVH_FACES: {
const Span<float3> positions = ss.vert_positions;
const OffsetIndices<int> faces = ss.faces;
const Span<int> corner_verts = ss.corner_verts;
const bool *hide_poly = ss.hide_poly;
const Vector<int> face_indices = BKE_pbvh_node_calc_face_indices(pbvh, *node);
for (const int face : face_indices) {
if (hide_poly && hide_poly[face]) {
continue;
}
const Span<int> face_verts = corner_verts.slice(faces[face]);
const float3 face_center = bke::mesh::face_center_calc(positions, face_verts);
const float3 face_normal = bke::mesh::face_normal_calc(positions, face_verts);
if (!sculpt_gesture_is_effected(sgcontext, face_center, face_normal)) {
continue;
}
ss.face_sets[face] = new_face_set;
any_updated = true;
}
SCULPT_face_set_set(sgcontext->ss, fd.face, face_set_operation->new_face_set_id);
any_updated = true;
break;
}
case PBVH_BMESH: {
BMesh *bm = ss.bm;
const int offset = CustomData_get_offset_named(
&bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
for (BMFace *face : BKE_pbvh_bmesh_node_faces(node)) {
if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
continue;
}
float3 center;
BM_face_calc_center_median(face, center);
if (!sculpt_gesture_is_effected(sgcontext, center, face->no)) {
continue;
}
BM_ELEM_CD_SET_INT(face, offset, new_face_set);
any_updated = true;
}
break;
}
}
BKE_pbvh_face_iter_end(fd);
if (any_updated) {
BKE_pbvh_node_mark_update_visibility(node);
@@ -793,7 +821,11 @@ static void mask_gesture_apply_task(SculptGestureContext *sgcontext,
bool redraw = false;
BKE_pbvh_vertex_iter_begin (sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
if (sculpt_gesture_is_vertex_effected(sgcontext, vd.vertex)) {
float vertex_normal[3];
const float *co = SCULPT_vertex_co_get(sgcontext->ss, vd.vertex);
SCULPT_vertex_normal_get(sgcontext->ss, vd.vertex, vertex_normal);
if (sculpt_gesture_is_effected(sgcontext, co, vertex_normal)) {
float prevmask = vd.mask;
if (!any_masked) {
any_masked = true;
@@ -1494,7 +1526,11 @@ static void project_line_gesture_apply_task(SculptGestureContext *sgcontext, PBV
SCULPT_undo_push_node(sgcontext->vc.obact, node, SCULPT_UNDO_COORDS);
BKE_pbvh_vertex_iter_begin (sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
if (!sculpt_gesture_is_vertex_effected(sgcontext, vd.vertex)) {
float vertex_normal[3];
const float *co = SCULPT_vertex_co_get(sgcontext->ss, vd.vertex);
SCULPT_vertex_normal_get(sgcontext->ss, vd.vertex, vertex_normal);
if (sculpt_gesture_is_effected(sgcontext, co, vertex_normal)) {
continue;
}

View File

@@ -1432,39 +1432,6 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter
}
}
void SCULPT_orig_face_data_unode_init(SculptOrigFaceData *data, Object *ob, SculptUndoNode *unode)
{
SculptSession *ss = ob->sculpt;
BMesh *bm = ss->bm;
memset(data, 0, sizeof(*data));
data->unode = unode;
if (bm) {
data->bm_log = ss->bm_log;
}
else {
data->face_sets = unode->face_sets.data();
}
}
void SCULPT_orig_face_data_init(SculptOrigFaceData *data,
Object *ob,
PBVHNode *node,
SculptUndoType type)
{
SculptUndoNode *unode;
unode = SCULPT_undo_push_node(ob, node, type);
SCULPT_orig_face_data_unode_init(data, ob, unode);
}
void SCULPT_orig_face_data_update(SculptOrigFaceData *orig_data, PBVHFaceIter *iter)
{
if (orig_data->unode->type == SCULPT_UNDO_FACE_SETS) {
orig_data->face_set = orig_data->face_sets ? orig_data->face_sets[iter->i] : false;
}
}
static void sculpt_rake_data_update(SculptRakeData *srd, const float co[3])
{
float rake_dist = len_v3v3(srd->follow_co, co);
@@ -1561,16 +1528,27 @@ static void paint_mesh_restore_node(Object *ob,
break;
}
case SCULPT_UNDO_FACE_SETS: {
SculptOrigFaceData orig_face_data;
SCULPT_orig_face_data_unode_init(&orig_face_data, ob, unode);
PBVHFaceIter fd;
BKE_pbvh_face_iter_begin (ss->pbvh, node, fd) {
SCULPT_orig_face_data_update(&orig_face_data, &fd);
if (fd.face_set) {
*fd.face_set = orig_face_data.face_set;
const Span<int> face_sets = unode->face_sets;
ss->face_sets = BKE_sculpt_face_sets_ensure(ob);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS: {
const Span<int> faces = unode->face_indices;
blender::array_utils::scatter(face_sets, faces, {ss->face_sets, ss->faces_num});
break;
}
case PBVH_BMESH: {
BMesh *bm = BKE_pbvh_get_bmesh(ss->pbvh);
const int offset = CustomData_get_offset_named(
&bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
int i = 0;
for (BMFace *face : BKE_pbvh_bmesh_node_faces(node)) {
BM_ELEM_CD_SET_INT(face, offset, face_sets[i]);
i++;
}
break;
}
}
BKE_pbvh_face_iter_end(fd);
BKE_pbvh_node_mark_update_face_sets(node);
break;
}
@@ -6287,32 +6265,6 @@ void SCULPT_stroke_id_ensure(Object *ob)
}
}
int SCULPT_face_set_get(const SculptSession *ss, PBVHFaceRef face)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH:
return 0;
case PBVH_FACES:
case PBVH_GRIDS:
return ss->face_sets[face.i];
}
BLI_assert_unreachable();
return 0;
}
void SCULPT_face_set_set(SculptSession *ss, PBVHFaceRef face, int fset)
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_BMESH:
break;
case PBVH_FACES:
case PBVH_GRIDS:
ss->face_sets[face.i] = fset;
}
}
int SCULPT_vertex_island_get(const SculptSession *ss, PBVHVertRef vertex)
{
if (ss->attrs.topology_island_key) {

View File

@@ -233,8 +233,7 @@ struct SculptUndoNode {
/* Sculpt Face Sets */
blender::Array<int> face_sets;
blender::Array<PBVHFaceRef> faces;
int faces_num;
blender::Vector<int> face_indices;
size_t undo_size;
};
@@ -1001,9 +1000,6 @@ int SCULPT_active_face_set_get(SculptSession *ss);
int SCULPT_vertex_face_set_get(SculptSession *ss, PBVHVertRef vertex);
void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_set);
int SCULPT_face_set_get(const SculptSession *ss, PBVHFaceRef face);
void SCULPT_face_set_set(SculptSession *ss, PBVHFaceRef face, int fset);
bool SCULPT_vertex_has_face_set(SculptSession *ss, PBVHVertRef vertex, int face_set);
bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex);
@@ -1034,23 +1030,6 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter
* handles #BMesh, #Mesh, and multi-resolution.
*/
void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, SculptUndoNode *unode);
/**
* Initialize a #SculptOrigFaceData for accessing original face data;
* handles #BMesh, #Mesh, and multi-resolution.
*/
void SCULPT_orig_face_data_init(SculptOrigFaceData *data,
Object *ob,
PBVHNode *node,
SculptUndoType type);
/**
* Update a #SculptOrigFaceData for a particular vertex from the PBVH iterator.
*/
void SCULPT_orig_face_data_update(SculptOrigFaceData *orig_data, PBVHFaceIter *iter);
/**
* Initialize a #SculptOrigVertData for accessing original vertex data;
* handles #BMesh, #Mesh, and multi-resolution.
*/
void SCULPT_orig_face_data_unode_init(SculptOrigFaceData *data, Object *ob, SculptUndoNode *unode);
/** \} */
/* -------------------------------------------------------------------- */

View File

@@ -34,7 +34,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_ghash.h"
#include "BLI_array_utils.hh"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_threads.h"
@@ -349,14 +349,12 @@ static void update_cb_partial(PBVHNode *node, void *userdata)
}
}
if (data->modified_face_set_faces) {
PBVHFaceIter fd;
BKE_pbvh_face_iter_begin (data->pbvh, node, fd) {
if (data->modified_face_set_faces[fd.index]) {
for (const int face : BKE_pbvh_node_calc_face_indices(*data->pbvh, *node)) {
if (data->modified_face_set_faces[face]) {
BKE_pbvh_node_mark_update_face_sets(node);
break;
}
}
BKE_pbvh_face_iter_end(fd);
}
}
@@ -624,19 +622,19 @@ static bool sculpt_undo_restore_face_sets(bContext *C,
SculptSession *ss = ob->sculpt;
ss->face_sets = BKE_sculpt_face_sets_ensure(ob);
BKE_pbvh_face_sets_set(ss->pbvh, ss->face_sets);
bool modified = false;
const Span<int> face_indices = unode->face_indices;
for (int i = 0; i < unode->faces_num; i++) {
int face_index = unode->faces[i].i;
for (const int i : face_indices.index_range()) {
int face_index = face_indices[i];
if (unode->face_sets[i] != ss->face_sets[face_index]) {
modified_face_set_faces[face_index] = true;
modified = true;
}
SWAP(int, unode->face_sets[i], ss->face_sets[face_index]);
modified_face_set_faces[face_index] = unode->face_sets[i] != ss->face_sets[face_index];
modified |= modified_face_set_faces[face_index];
}
return modified;
}
@@ -1231,23 +1229,6 @@ static SculptUndoNode *sculpt_undo_find_or_alloc_node_type(Object *object, Sculp
return sculpt_undo_alloc_node_type(object, type);
}
static void sculpt_undo_store_faces(SculptSession *ss, SculptUndoNode *unode)
{
unode->faces_num = 0;
PBVHFaceIter fd;
BKE_pbvh_face_iter_begin (ss->pbvh, static_cast<PBVHNode *>(unode->node), fd) {
unode->faces_num++;
}
BKE_pbvh_face_iter_end(fd);
unode->faces.reinitialize(unode->faces_num);
BKE_pbvh_face_iter_begin (ss->pbvh, static_cast<PBVHNode *>(unode->node), fd) {
unode->faces[fd.i] = fd.face;
}
BKE_pbvh_face_iter_end(fd);
}
static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, SculptUndoType type)
{
UndoSculpt *usculpt = sculpt_undo_get_nodes();
@@ -1285,8 +1266,8 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
}
if (need_faces) {
sculpt_undo_store_faces(ss, unode);
usculpt->undo_size += unode->faces.as_span().size_in_bytes();
unode->face_indices = BKE_pbvh_node_calc_face_indices(*ss->pbvh, *node);
usculpt->undo_size += unode->face_indices.as_span().size_in_bytes();
}
switch (type) {
@@ -1336,7 +1317,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, Sculpt
case SCULPT_UNDO_GEOMETRY:
break;
case SCULPT_UNDO_FACE_SETS: {
unode->face_sets.reinitialize(unode->faces_num);
unode->face_sets.reinitialize(unode->face_indices.size());
usculpt->undo_size += unode->face_sets.as_span().size_in_bytes();
break;
}
@@ -1456,15 +1437,12 @@ static SculptUndoNode *sculpt_undo_geometry_push(Object *object, SculptUndoType
return unode;
}
static void sculpt_undo_store_face_sets(SculptSession *ss, SculptUndoNode *unode)
static void sculpt_undo_store_face_sets(const Mesh &mesh, SculptUndoNode &unode)
{
unode->face_sets.reinitialize(unode->faces_num);
PBVHFaceIter fd;
BKE_pbvh_face_iter_begin (ss->pbvh, static_cast<PBVHNode *>(unode->node), fd) {
unode->face_sets[fd.i] = fd.face_set ? *fd.face_set : SCULPT_FACE_SET_NONE;
}
BKE_pbvh_face_iter_end(fd);
blender::array_utils::gather(
*mesh.attributes().lookup_or_default<int>(".sculpt_face_set", ATTR_DOMAIN_FACE, 0),
unode.face_indices.as_span(),
unode.face_sets.as_mutable_span());
}
static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, PBVHNode *node, SculptUndoType type)
@@ -1622,7 +1600,7 @@ SculptUndoNode *SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType
case SCULPT_UNDO_GEOMETRY:
break;
case SCULPT_UNDO_FACE_SETS:
sculpt_undo_store_face_sets(ss, unode);
sculpt_undo_store_face_sets(*static_cast<const Mesh *>(ob->data), *unode);
break;
}