sculpt-dev: Dyntopo collapse now works with new id system

. . .but subdivide is now broken.
This commit is contained in:
Joseph Eagar 2023-01-28 00:34:05 -08:00
parent f68b5cd7e1
commit b4cc9b67fc
5 changed files with 63 additions and 232 deletions

View File

@ -80,7 +80,6 @@ static void edge_queue_create_local(struct EdgeQueueContext *eq_ctx,
const bool use_projected,
PBVHTopologyUpdateMode local_mode);
BLI_INLINE void surface_smooth_v_safe(PBVH *pbvh, BMVert *v, float fac)
{
float co[3];
@ -714,7 +713,7 @@ static float maskcb_get(EdgeQueueContext *eq_ctx, BMVert *v1, BMVert *v2)
return min_ff(w1, w2);
//}
return (w1 + w2) * 0.5f;
// return (w1 + w2) * 0.5f;
}
return 1.0f;
@ -1392,8 +1391,7 @@ bool check_face_is_tri(PBVH *pbvh, BMFace *f)
ATTR_NO_OPT bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
{
return false;
#if 0
bm_logstack_push();
static int max_faces = 64;
@ -1436,7 +1434,6 @@ ATTR_NO_OPT bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
continue;
}
void **val = nullptr;
BMFace *f2 = l->radial_next->f;
if (visit.add(f2)) {
@ -1469,7 +1466,7 @@ ATTR_NO_OPT bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
return false;
}
printf("manifold fin size: %d\n", minfs.size());
printf("manifold fin size: %d\n", (int)minfs.size());
const int tag = BM_ELEM_TAG_ALT;
for (int i = 0; i < minfs.size(); i++) {
@ -1534,9 +1531,9 @@ ATTR_NO_OPT bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
}
pbvh_bmesh_face_remove(pbvh, f, true, false, false);
#ifdef USE_NEW_IDMAP
# ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, (BMElem *)f, true);
#endif
# endif
BM_face_kill(pbvh->header.bm, f);
}
@ -1547,9 +1544,9 @@ ATTR_NO_OPT bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
if (!e->l) {
BM_log_edge_removed(pbvh->bm_log, e);
#ifdef USE_NEW_IDMAP
# ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, (BMElem *)e, true);
#endif
# endif
BM_edge_kill(pbvh->header.bm, e);
}
}
@ -1561,9 +1558,9 @@ ATTR_NO_OPT bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
pbvh_bmesh_vert_remove(pbvh, v);
BM_log_vert_removed(pbvh->bm_log, v, pbvh->cd_vert_mask_offset);
#ifdef USE_NEW_IDMAP
# ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, (BMElem *)v, true);
#endif
# endif
BM_vert_kill(pbvh->header.bm, v);
}
else {
@ -1576,6 +1573,9 @@ ATTR_NO_OPT bool destroy_nonmanifold_fins(PBVH *pbvh, BMEdge *e_root)
bm_logstack_pop();
return true;
#else
return false;
#endif
}
bool check_for_fins(PBVH *pbvh, BMVert *v)
@ -3192,16 +3192,6 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
for (int i = 0; i < totedge; i++) {
BMEdge *e = edges[i];
#if 0
BMLoop *l = e->l;
while (e->l) {
BMFace *f = e->l->f;
BM_log_face_removed(pbvh->bm_log, f);
BKE_pbvh_bmesh_remove_face(pbvh, f, false);
BM_idmap_release(pbvh->bm_idmap, (BMElem *)f, true);
BM_face_kill(pbvh->header.bm, f);
}
#endif
check_vert_fan_are_tris(pbvh, e->v1);
check_vert_fan_are_tris(pbvh, e->v2);
}
@ -3287,7 +3277,6 @@ static void pbvh_split_edges(EdgeQueueContext *eq_ctx,
BMFace *f = faces[i];
BMLoop *l = f->l_first;
// pbvh_bmesh_face_remove(pbvh, f, true, false, false);
if (!ignore_isolated_edges) {
f->head.hflag |= SPLIT_TAG;
BM_log_face_pre(pbvh->bm_log, f);

View File

@ -47,6 +47,11 @@ using blender::Vector;
namespace blender::dyntopo {
typedef struct TraceData {
PBVH *pbvh;
BMEdge *e;
} TraceData;
// copied from decimate modifier code
inline bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
{
@ -130,128 +135,6 @@ inline bool bm_edge_collapse_is_degenerate_topology(BMEdge *e_first)
return false;
}
typedef struct TraceData {
PBVH *pbvh;
blender::Set<void *> visit;
BMEdge *e;
} TraceData;
ATTR_NO_OPT void col_on_vert_kill(BMesh *bm, BMVert *v, void *userdata)
{
TraceData *data = (TraceData *)userdata;
PBVH *pbvh = data->pbvh;
if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
// printf("vert pbvh remove!\n");
blender::dyntopo::pbvh_bmesh_vert_remove(pbvh, v);
}
if (!data->visit.add(static_cast<void *>(v))) {
// printf("vert kill!\n");
BM_log_vert_pre(pbvh->bm_log, v);
#ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, reinterpret_cast<BMElem *>(v), true);
#endif
}
}
ATTR_NO_OPT void col_on_edge_kill(BMesh *bm, BMEdge *e, void *userdata)
{
TraceData *data = (TraceData *)userdata;
PBVH *pbvh = data->pbvh;
if (!data->visit.add(static_cast<void *>(e))) {
// printf("edge kill!\n");
BM_log_edge_pre(pbvh->bm_log, e);
#ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, reinterpret_cast<BMElem *>(e), true);
#endif
}
}
ATTR_NO_OPT void col_on_face_kill(BMesh *bm, BMFace *f, void *userdata)
{
TraceData *data = (TraceData *)userdata;
PBVH *pbvh = data->pbvh;
if (BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset) != DYNTOPO_NODE_NONE) {
pbvh_bmesh_face_remove(pbvh, f, false, false, false);
}
if (!data->visit.add(static_cast<void *>(f))) {
BM_log_face_pre(pbvh->bm_log, f);
#ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, reinterpret_cast<BMElem *>(f), true);
#endif
}
}
ATTR_NO_OPT static void collapse_restore_id(BMIdMap *idmap, BMElem *elem)
{
int id = BM_idmap_get_id(idmap, elem);
if (id < 0 || id >= idmap->map_size || idmap->map[id]) {
BM_idmap_alloc(idmap, elem);
}
else {
BM_idmap_assign(idmap, elem, id);
}
}
ATTR_NO_OPT void col_on_vert_add(BMesh *bm, BMVert *v, void *userdata)
{
TraceData *data = (TraceData *)userdata;
PBVH *pbvh = data->pbvh;
if (!data->visit.add(static_cast<void *>(v))) {
// return;
}
pbvh_boundary_update_bmesh(pbvh, v);
MSculptVert *mv = (MSculptVert *)BM_ELEM_CD_GET_VOID_P(v, data->pbvh->cd_sculpt_vert);
mv->flag |= SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT;
collapse_restore_id(pbvh->bm_idmap, (BMElem *)v);
BM_log_vert_post(pbvh->bm_log, v);
}
ATTR_NO_OPT void col_on_edge_add(BMesh *bm, BMEdge *e, void *userdata)
{
TraceData *data = (TraceData *)userdata;
PBVH *pbvh = data->pbvh;
if (!data->visit.add(static_cast<void *>(e))) {
// return;
}
collapse_restore_id(pbvh->bm_idmap, (BMElem *)e);
BM_log_edge_post(pbvh->bm_log, e);
}
ATTR_NO_OPT void col_on_face_add(BMesh *bm, BMFace *f, void *userdata)
{
TraceData *data = (TraceData *)userdata;
PBVH *pbvh = data->pbvh;
if (!data->visit.add(static_cast<void *>(f))) {
// return;
}
if (bm_elem_is_free((BMElem *)f, BM_FACE)) {
printf("%s: error, f was freed!\n", __func__);
return;
}
if (BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset) != DYNTOPO_NODE_NONE) {
pbvh_bmesh_face_remove(pbvh, f, false, false, false);
}
collapse_restore_id(pbvh->bm_idmap, (BMElem *)f);
BM_log_face_post(pbvh->bm_log, f);
BKE_pbvh_bmesh_add_face(pbvh, f, false, false);
}
/* Faces *outside* the ring region are tagged with facetag, used to detect
* border edges.
*/
@ -382,31 +265,11 @@ ATTR_NO_OPT void vert_ring_do_apply(BMVert *v,
const int COLLAPSE_TAG = BM_ELEM_INTERNAL_TAG;
const int COLLAPSE_FACE_TAG = BM_ELEM_TAG_ALT;
ATTR_NO_OPT static void vert_ring_do_old(BMVert *v,
void (*callback)(BMElem *elem, void *userdata),
void *userdata,
int tag,
int facetag,
int depth)
{
if (!v->e) {
v->head.hflag &= ~tag;
callback((BMElem *)v, userdata);
return;
}
vert_ring_do_tag(v, tag, facetag, depth);
vert_ring_untag_inner_faces(v, tag, facetag, depth);
vert_ring_do_apply(v, callback, userdata, tag, facetag, depth);
}
ATTR_NO_OPT static void collapse_ring_callback_pre(BMElem *elem, void *userdata)
{
TraceData *data = static_cast<TraceData *>(userdata);
if (!data->visit.add(static_cast<void *>(elem))) {
return;
}
BM_idmap_check_assign(data->pbvh->bm_idmap, elem);
switch (elem->head.htype) {
case BM_VERT: {
@ -414,44 +277,74 @@ ATTR_NO_OPT static void collapse_ring_callback_pre(BMElem *elem, void *userdata)
BM_log_vert_removed(data->pbvh->bm_log, v, -1);
pbvh_bmesh_vert_remove(data->pbvh, v);
BM_idmap_release(data->pbvh->bm_idmap, elem, false);
break;
}
case BM_EDGE: {
BMEdge *e = reinterpret_cast<BMEdge *>(elem);
BM_log_edge_removed(data->pbvh->bm_log, e);
BM_idmap_release(data->pbvh->bm_idmap, elem, false);
break;
}
case BM_FACE: {
BMFace *f = reinterpret_cast<BMFace *>(elem);
BM_log_face_removed(data->pbvh->bm_log, f);
pbvh_bmesh_face_remove(data->pbvh, f, false, false, false);
BM_idmap_release(data->pbvh->bm_idmap, elem, false);
break;
}
}
}
ATTR_NO_OPT static void check_new_elem_id(BMElem *elem, TraceData *data)
{
int id = BM_ELEM_CD_GET_INT(elem, data->pbvh->bm_idmap->cd_id_off[elem->head.htype]);
if (id >= 0) {
BMElem *existing = id < data->pbvh->bm_idmap->map_size ?
BM_idmap_lookup(data->pbvh->bm_idmap, id) :
nullptr;
if (existing) {
BM_idmap_release(data->pbvh->bm_idmap, existing, true);
}
BM_idmap_assign(data->pbvh->bm_idmap, elem, id);
if (existing) {
BM_idmap_check_assign(data->pbvh->bm_idmap, existing);
}
}
else {
BM_idmap_check_assign(data->pbvh->bm_idmap, elem);
}
}
ATTR_NO_OPT static void collapse_ring_callback_post(BMElem *elem, void *userdata)
{
TraceData *data = static_cast<TraceData *>(userdata);
if (!data->visit.add(static_cast<void *>(elem))) {
return;
}
switch (elem->head.htype) {
case BM_VERT: {
BMVert *v = reinterpret_cast<BMVert *>(elem);
MSculptVert *mv = (MSculptVert *)BM_ELEM_CD_GET_VOID_P(v, data->pbvh->cd_sculpt_vert);
mv->flag |= SCULPTVERT_NEED_VALENCE | SCULPTVERT_NEED_DISK_SORT;
check_new_elem_id(elem, data);
BM_log_vert_added(data->pbvh->bm_log, v, -1);
break;
}
case BM_EDGE: {
BMEdge *e = reinterpret_cast<BMEdge *>(elem);
check_new_elem_id(elem, data);
BM_log_edge_added(data->pbvh->bm_log, e);
break;
}
case BM_FACE: {
BMFace *f = reinterpret_cast<BMFace *>(elem);
check_new_elem_id(elem, data);
BM_log_face_added(data->pbvh->bm_log, f);
BKE_pbvh_bmesh_add_face(data->pbvh, f, false, false);
break;
@ -485,14 +378,14 @@ ATTR_NO_OPT static void vert_ring_do(BMVert *v,
int facetag,
int depth)
{
blender::Set<BMFace *> faces;
blender::Set<BMFace *, 128> faces;
std::function<void(BMVert * v, int depth)> recurse = [&](BMVert *v, int depth) {
if (!v->e) {
return;
}
const int max_depth = 2;
const int max_depth = 1;
BMEdge *e = v->e;
do {
BMVert *v2 = BM_edge_other_vert(e, v);
@ -520,8 +413,8 @@ ATTR_NO_OPT static void vert_ring_do(BMVert *v,
recurse(v_extra, 0);
}
blender::Set<BMVert *> verts;
blender::Set<BMEdge *> edges;
blender::Set<BMVert *, 64> verts;
blender::Set<BMEdge *, 128> edges;
for (BMFace *f : faces) {
BMLoop *l = f->l_first;
@ -802,44 +695,14 @@ ATTR_NO_OPT BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
const int facetag = COLLAPSE_FACE_TAG;
const int log_rings = 1;
blender::dyntopo::pbvh_bmesh_vert_remove(pbvh, v_del);
BM_log_edge_pre(pbvh->bm_log, e);
tdata.visit.add(static_cast<void *>(e));
#ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, (BMElem *)e, true);
#endif
BM_log_vert_removed(pbvh->bm_log, v_del, pbvh->cd_vert_mask_offset);
tdata.visit.add(static_cast<void *>(v_del));
#ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, (BMElem *)v_del, true);
#endif
if (deleted_verts) {
BLI_ghash_insert(deleted_verts, (void *)v_del, nullptr);
}
pbvh_bmesh_check_nodes(pbvh);
validate_vert_faces(pbvh, pbvh->header.bm, v_conn, false, true);
BMTracer tracer;
BM_empty_tracer(&tracer, &tdata);
//#define USE_TRACER
#ifdef USE_TRACER
tracer.on_vert_kill = col_on_vert_kill;
tracer.on_edge_kill = col_on_edge_kill;
tracer.on_face_kill = col_on_face_kill;
tracer.on_vert_create = col_on_vert_add;
tracer.on_edge_create = col_on_edge_add;
tracer.on_face_create = col_on_face_add;
#else
vert_ring_do(e->v1, e->v2, collapse_ring_callback_pre, &tdata, tag, facetag, log_rings - 1);
#endif
if (!uvs_snapped) {
float co[3];
@ -861,9 +724,6 @@ ATTR_NO_OPT BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
copy_v3_v3(v_conn->co, co);
}
#ifdef USE_TRACER
#else
tdata.visit.clear();
vert_ring_do(v_conn,
nullptr,
collapse_ring_callback_post,
@ -871,7 +731,6 @@ ATTR_NO_OPT BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
tag,
facetag,
log_rings - 1);
#endif
if (!v_conn->e) {
printf("%s: pbvh error, v_conn->e was null\n", __func__);
@ -942,13 +801,7 @@ ATTR_NO_OPT BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
blender::dyntopo::pbvh_bmesh_vert_remove(pbvh, v_conn);
}
// if (!tdata.visit.contains(static_cast<void *>(v_conn))) {
BM_log_vert_removed(pbvh->bm_log, v_conn, 0);
//}
#ifdef USE_NEW_IDMAP
BM_idmap_release(pbvh->bm_idmap, (BMElem *)v_conn, true);
#endif
BM_vert_kill(pbvh->header.bm, v_conn);
bm_logstack_pop();
@ -959,20 +812,6 @@ ATTR_NO_OPT BMVert *pbvh_bmesh_collapse_edge(PBVH *pbvh,
printf("%s: error: failed to remove vert from pbvh?\n", __func__);
}
#if 0
e = v_conn->e;
if (e) {
do {
enext = BM_DISK_EDGE_NEXT(e, v_conn);
BMVert *v2 = BM_edge_other_vert(e, v_conn);
MSculptVert *mv4 = BKE_PBVH_SCULPTVERT(pbvh->cd_sculpt_vert, v2);
} while ((e = enext) != v_conn->e);
}
#endif
if (v_conn) {
check_for_fins(pbvh, v_conn);
}

View File

@ -246,7 +246,7 @@ ATTR_NO_OPT int BM_idmap_alloc(BMIdMap *idmap, BMElem *elem)
while (idmap->freelist.size()) {
id = idmap->freelist.pop_last();
if (id == -1) {
continue;
}

View File

@ -3487,7 +3487,7 @@ void _BM_log_vert_removed(BMLog *log, BMVert *v, int UNUSED(cd_vert_mask_offset)
BM_idmap_check_assign(log->idmap, (BMElem *)v);
if (bm_log_vert_from_id(log, (uint)bm_log_vert_id_get(log, v)) != v) {
fprintf(DEBUG_FILE, "%s: idmap error\n", __func__);
fprintf(DEBUG_FILE, "%s: idmap error: %d\n", __func__, bm_log_vert_id_get(log, v));
bm_logstack_pop();
return;
}
@ -3517,10 +3517,13 @@ BMVert *BM_log_edge_split_do(BMLog *log, BMEdge *e, BMVert *v, BMEdge **newe, fl
}
BM_log_edge_pre(log, e);
BM_idmap_release(log->idmap, (BMElem *)e, true);
BMVert *newv = BM_edge_split(log->bm, e, v, newe, t);
BM_idmap_alloc(log->idmap, (BMElem *)newv);
BM_idmap_alloc(log->idmap, (BMElem *)e);
BM_idmap_alloc(log->idmap, (BMElem *)*newe);
BM_idmap_alloc(log->idmap, (BMElem *)newv);
BMIter iter;
BMLoop *l;

View File

@ -1164,7 +1164,7 @@ static int sculpt_face_set_init_exec(bContext *C, wmOperator *op)
const int mode = RNA_enum_get(op->ptr, "mode");
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
BKE_sculpt_face_sets_ensure(ob);
ss->face_sets = BKE_sculpt_face_sets_ensure(ob);
/* Dyntopo not supported. */
if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {