Edit face set brush now works for pbvh bmesh

This commit is contained in:
Joseph Eagar 2021-04-27 09:51:49 -07:00
parent 02b4df9827
commit 3028d53865
3 changed files with 146 additions and 45 deletions

View File

@ -65,7 +65,7 @@ typedef struct PBVHTriBuf {
SculptVertRef *verts;
int tottri, totvert;
//private field
// private field
intptr_t *loops;
int totloop;
} PBVHTriBuf;
@ -73,6 +73,7 @@ typedef struct PBVHTriBuf {
struct BMLog;
struct BMesh;
struct BMVert;
struct BMFace;
struct CCGElem;
struct CCGKey;
struct CustomData;
@ -696,6 +697,7 @@ void BKE_pbvh_bmesh_free_tris(PBVH *pbvh, PBVHNode *node);
/*recalculates boundary flags for *all* vertices. used by
symmetrize.*/
void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh);
void BKE_pbvh_bmesh_face_kill(PBVH *pbvh, struct BMFace *f);
#ifdef __cplusplus
}

View File

@ -888,6 +888,12 @@ static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f)
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateTris;
}
void BKE_pbvh_bmesh_face_kill(PBVH *pbvh, BMFace *f)
{
pbvh_bmesh_face_remove(pbvh, f);
BM_face_kill(pbvh->bm, f);
}
static void pbvh_bmesh_edge_loops(BLI_Buffer *buf, BMEdge *e)
{
/* fast-path for most common case where an edge has 2 faces,
@ -3222,7 +3228,8 @@ void BKE_pbvh_recalc_bmesh_boundary(PBVH *pbvh)
if (BM_vert_is_boundary(v)) {
mv->flag |= DYNVERT_BOUNDARY;
} else {
}
else {
mv->flag &= ~DYNVERT_BOUNDARY;
}
}

View File

@ -25,6 +25,7 @@
#include "BLI_array.h"
#include "BLI_blenlib.h"
#include "BLI_compiler_attrs.h"
#include "BLI_hash.h"
#include "BLI_math.h"
#include "BLI_task.h"
@ -934,10 +935,23 @@ static int sculpt_face_sets_change_visibility_exec(bContext *C, wmOperator *op)
}
}
for (int i = 0; i < ss->totfaces; i++) {
if (ss->face_sets[i] <= 0) {
hidden_vertex = true;
break;
if (ss->bm) {
BMIter iter;
BMFace *f;
BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
if (BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset) <= 0) {
hidden_vertex = true;
break;
}
}
}
else {
for (int i = 0; i < ss->totfaces; i++) {
if (ss->face_sets[i] <= 0) {
hidden_vertex = true;
break;
}
}
}
@ -1176,7 +1190,7 @@ static void sculpt_face_set_grow_bmesh(Object *ob,
do {
if (l->radial_next != l) {
BM_ELEM_CD_GET_INT(l->radial_next->f, active_face_set_id);
BM_ELEM_CD_SET_INT(l->radial_next->f, ss->cd_faceset_offset, active_face_set_id);
}
l = l->next;
} while (l != f->l_first);
@ -1218,6 +1232,59 @@ static void sculpt_face_set_grow(Object *ob,
}
}
static void sculpt_face_set_shrink_bmesh(Object *ob,
SculptSession *ss,
const int *prev_face_sets,
const int active_face_set_id,
const bool modify_hidden)
{
BMesh *bm = ss->bm;
BMIter iter;
BMFace *f;
BMFace **faces = NULL;
BLI_array_declare(faces);
if (ss->cd_faceset_offset < 0) {
return;
}
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) && !modify_hidden) {
continue;
}
int fset = abs(BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset));
if (fset == active_face_set_id) {
BLI_array_append(faces, f);
}
}
for (int i = 0; i < BLI_array_len(faces); i++) {
BMFace *f = faces[i];
BMLoop *l = f->l_first;
do {
if (!modify_hidden && BM_elem_flag_test(l->radial_next->f, BM_ELEM_HIDDEN)) {
l = l->next;
continue;
}
if (l->radial_next != l &&
abs(BM_ELEM_CD_GET_INT(l->radial_next->f, ss->cd_faceset_offset)) !=
abs(active_face_set_id)) {
BM_ELEM_CD_SET_INT(f,
ss->cd_faceset_offset,
BM_ELEM_CD_GET_INT(l->radial_next->f, ss->cd_faceset_offset));
break;
}
l = l->next;
} while (l != f->l_first);
}
BLI_array_free(faces);
}
static void sculpt_face_set_shrink(Object *ob,
SculptSession *ss,
const int *prev_face_sets,
@ -1225,7 +1292,7 @@ static void sculpt_face_set_shrink(Object *ob,
const bool modify_hidden)
{
if (ss && ss->bm) {
// XXX implement me
sculpt_face_set_shrink_bmesh(ob, ss, prev_face_sets, active_face_set_id, modify_hidden);
return;
}
@ -1290,41 +1357,65 @@ static void sculpt_face_set_delete_geometry(Object *ob,
Mesh *mesh = ob->data;
const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh);
BMesh *bm = BM_mesh_create(&allocsize,
&((struct BMeshCreateParams){
.use_toolflags = true,
}));
BM_mesh_bm_from_me(ob,
if (ss->bm) {
BMFace **faces = NULL;
BLI_array_declare(faces);
BMIter iter;
BMFace *f;
BM_ITER_MESH (f, &iter, ss->bm, BM_FACES_OF_MESH) {
const int face_set_id = modify_hidden ? abs(BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset)) :
BM_ELEM_CD_GET_INT(f, ss->cd_faceset_offset);
if (face_set_id == active_face_set_id) {
BLI_array_append(faces, f);
}
}
for (int i = 0; i < BLI_array_len(faces); i++) {
BKE_pbvh_bmesh_face_kill(ss->pbvh, faces[i]);
}
BLI_array_free(faces);
}
else {
BMesh *bm = BM_mesh_create(&allocsize,
&((struct BMeshCreateParams){
.use_toolflags = true,
}));
BM_mesh_bm_from_me(ob,
bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
}));
BM_mesh_elem_table_init(bm, BM_FACE);
BM_mesh_elem_table_ensure(bm, BM_FACE);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BMIter iter;
BMFace *f;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
const int face_index = BM_elem_index_get(f);
const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) :
ss->face_sets[face_index];
BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id);
}
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BM_mesh_bm_to_me(NULL,
ob,
bm,
mesh,
(&(struct BMeshFromMeshParams){
.calc_face_normal = true,
ob->data,
(&(struct BMeshToMeshParams){
.calc_object_remap = false,
}));
BM_mesh_elem_table_init(bm, BM_FACE);
BM_mesh_elem_table_ensure(bm, BM_FACE);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BMIter iter;
BMFace *f;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
const int face_index = BM_elem_index_get(f);
const int face_set_id = modify_hidden ? abs(ss->face_sets[face_index]) :
ss->face_sets[face_index];
BM_elem_flag_set(f, BM_ELEM_TAG, face_set_id == active_face_set_id);
BM_mesh_free(bm);
}
BM_mesh_delete_hflag_context(bm, BM_ELEM_TAG, DEL_FACES);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BM_mesh_bm_to_me(NULL,
ob,
bm,
ob->data,
(&(struct BMeshToMeshParams){
.calc_object_remap = false,
}));
BM_mesh_free(bm);
}
static void sculpt_face_set_edit_fair_face_set(Object *ob,
@ -1349,8 +1440,14 @@ static void sculpt_face_set_edit_fair_face_set(Object *ob,
SCULPT_vertex_has_unique_face_set(ss, vref);
}
MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
BKE_mesh_prefair_and_fair_vertices(mesh, mvert, fair_vertices, fair_order);
if (ss->bm) {
BKE_bmesh_prefair_and_fair_vertices(ss->bm, fair_vertices, fair_order);
}
else {
MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
BKE_mesh_prefair_and_fair_vertices(mesh, mvert, fair_vertices, fair_order);
}
MEM_freeN(fair_vertices);
}
@ -1390,11 +1487,6 @@ static bool sculpt_face_set_edit_is_operation_valid(SculptSession *ss,
const eSculptFaceSetEditMode mode,
const bool modify_hidden)
{
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
/* Dyntopo is not supported. */
return false;
}
if (mode == SCULPT_FACE_SET_EDIT_DELETE_GEOMETRY) {
if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
/* Modification of base mesh geometry requires special remapping of multires displacement,