[Bf-blender-cvs] [71959181ade] temp_bmesh_multires: * Fix bug with symmetrize creating non-manifold geometry. * Fix bug in pbvh face create
Joseph Eagar
noreply at git.blender.org
Wed May 19 07:27:24 CEST 2021
Commit: 71959181ade3bff4640ea594eb582a9ac8c53e20
Author: Joseph Eagar
Date: Tue May 18 22:26:49 2021 -0700
Branches: temp_bmesh_multires
https://developer.blender.org/rB71959181ade3bff4640ea594eb582a9ac8c53e20
* Fix bug with symmetrize creating non-manifold geometry.
* Fix bug in pbvh face create
===================================================================
M source/blender/blenkernel/intern/pbvh_bmesh.c
M source/blender/bmesh/intern/bmesh_log.c
M source/blender/bmesh/operators/bmo_symmetrize.c
M source/blender/editors/sculpt_paint/sculpt.c
M source/blender/editors/sculpt_paint/sculpt_undo.c
M source/blender/makesdna/DNA_meshdata_types.h
===================================================================
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 7758a84e9e8..f2635856a64 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1060,7 +1060,7 @@ static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
BM_FACES_OF_VERT_ITER_END;
}
-static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f, bool log_face)
+static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f, bool log_face, bool check_verts)
{
PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
@@ -1072,32 +1072,30 @@ static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f, bool log_face)
/* Check if any of this face's vertices need to be removed
* from the node */
- BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
- BMLoop *l_iter = l_first;
- do {
- BMVert *v = l_iter->v;
- if (pbvh_bmesh_node_vert_use_count_is_equal(pbvh, f_node, v, 1)) {
- if (BLI_table_gset_haskey(f_node->bm_unique_verts, v)) {
- /* Find a different node that uses 'v' */
- PBVHNode *new_node;
+ if (check_verts) {
+ BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+ BMLoop *l_iter = l_first;
+ do {
+ BMVert *v = l_iter->v;
+ if (pbvh_bmesh_node_vert_use_count_is_equal(pbvh, f_node, v, 1)) {
+ if (BLI_table_gset_haskey(f_node->bm_unique_verts, v)) {
+ /* Find a different node that uses 'v' */
+ PBVHNode *new_node;
- new_node = pbvh_bmesh_vert_other_node_find(pbvh, v);
- BLI_assert(new_node || BM_vert_face_count_is_equal(v, 1));
+ new_node = pbvh_bmesh_vert_other_node_find(pbvh, v);
+ BLI_assert(new_node || BM_vert_face_count_is_equal(v, 1));
- if (new_node) {
- pbvh_bmesh_vert_ownership_transfer(pbvh, new_node, v);
+ if (new_node) {
+ pbvh_bmesh_vert_ownership_transfer(pbvh, new_node, v);
+ }
}
else {
- BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
- BLI_table_gset_remove(f_node->bm_unique_verts, v, NULL);
+ /* Remove from other verts */
+ BLI_table_gset_remove(f_node->bm_other_verts, v, NULL);
}
}
- else {
- /* Remove from other verts */
- BLI_table_gset_remove(f_node->bm_other_verts, v, NULL);
- }
- }
- } while ((l_iter = l_iter->next) != l_first);
+ } while ((l_iter = l_iter->next) != l_first);
+ }
/* Remove face from node and top level */
BLI_table_gset_remove(f_node->bm_faces, f, NULL);
@@ -1114,7 +1112,7 @@ static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f, bool log_face)
void BKE_pbvh_bmesh_remove_face(PBVH *pbvh, BMFace *f, bool log_face)
{
- pbvh_bmesh_face_remove(pbvh, f, log_face);
+ pbvh_bmesh_face_remove(pbvh, f, log_face, true);
}
void BKE_pbvh_bmesh_remove_vertex(PBVH *pbvh, BMVert *v, bool log_vert)
@@ -2660,7 +2658,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
&pbvh->bm->ldata, (const void **)lsrcs, lws, lws, 1, f_new->l_first->prev->head.data);
/* Delete original */
- pbvh_bmesh_face_remove(pbvh, f_adj, true);
+ pbvh_bmesh_face_remove(pbvh, f_adj, true, true);
BM_face_kill(pbvh->bm, f_adj);
/* Ensure new vertex is in the node */
@@ -2841,7 +2839,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
l = l->next;
} while (l != f_adj->l_first);
- pbvh_bmesh_face_remove(pbvh, f_adj, true);
+ pbvh_bmesh_face_remove(pbvh, f_adj, true, true);
BM_face_kill(pbvh->bm, f_adj);
}
@@ -3015,7 +3013,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
} while (l1 != f_del->l_first);
/* Remove the face */
- pbvh_bmesh_face_remove(pbvh, f_del, true);
+ pbvh_bmesh_face_remove(pbvh, f_del, true, true);
BM_face_kill(pbvh->bm, f_del);
/* Check if any of the face's edges are now unused by any
@@ -3939,8 +3937,6 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
continue;
}
- PBVHVertexIter vi;
- GSetIterator gi;
BMVert *v;
TGSET_ITER (v, node->bm_unique_verts) {
@@ -4022,7 +4018,7 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
BLI_table_gset_remove(node2->bm_unique_verts, v, NULL);
BLI_table_gset_remove(node2->bm_other_verts, v, NULL);
- pbvh_bmesh_face_remove(pbvh, f, true);
+ pbvh_bmesh_face_remove(pbvh, f, true, true);
}
}
@@ -4037,6 +4033,8 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
BMFace *f1 = NULL;
if (vs[0] != vs[1] && vs[1] != vs[2] && vs[0] != vs[2]) {
f1 = pbvh_bmesh_face_create(pbvh, n, vs, NULL, l->f, false, false);
+ normal_tri_v3(
+ f1->no, f1->l_first->v->co, f1->l_first->next->v->co, f1->l_first->prev->v->co);
}
if (val == 4 && vs[0] != vs[2] && vs[2] != vs[3] && vs[0] != vs[3]) {
@@ -4052,6 +4050,8 @@ static bool cleanup_valence_3_4(PBVH *pbvh,
CustomData_bmesh_copy_data(
&pbvh->bm->ldata, &pbvh->bm->ldata, ls[2]->head.data, &f2->l_first->next->head.data);
+ normal_tri_v3(
+ f2->no, f2->l_first->v->co, f2->l_first->next->v->co, f2->l_first->prev->v->co);
BM_log_face_added(pbvh->bm_log, f2);
}
diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c
index f1b42072a86..c01bc92fd0d 100644
--- a/source/blender/bmesh/intern/bmesh_log.c
+++ b/source/blender/bmesh/intern/bmesh_log.c
@@ -57,12 +57,6 @@
struct Mesh;
-typedef struct BMLogEdge {
- uint v1, v2;
- void *data;
- int flag;
-} BMLogEdge;
-
struct BMLogEntry {
struct BMLogEntry *next, *prev;
@@ -142,6 +136,7 @@ struct BMLog {
BMLogEntry *current_entry;
int cd_dyn_vert;
+ bool dead;
};
typedef struct {
@@ -168,8 +163,8 @@ typedef struct {
static void full_copy_swap(BMesh *bm, BMLog *log, BMLogEntry *entry);
static void full_copy_load(BMesh *bm, BMLog *log, BMLogEntry *entry);
-
static void bm_log_entry_free(BMLogEntry *entry);
+static bool bm_log_free_direct(BMLog *log, bool safe_mode);
static void *log_ghash_lookup(BMLog *log, GHash *gh, const void *key)
{
@@ -608,10 +603,10 @@ static void bm_log_vert_values_swap(
}
}
-ATTR_NO_OPT static void bm_log_face_values_swap(BMLog *log,
- GHash *faces,
- BMLogEntry *entry,
- BMLogCallbacks *callbacks)
+static void bm_log_face_values_swap(BMLog *log,
+ GHash *faces,
+ BMLogEntry *entry,
+ BMLogCallbacks *callbacks)
{
void *scratch = log->bm->pdata.pool ? BLI_mempool_alloc(log->bm->pdata.pool) : NULL;
@@ -737,13 +732,18 @@ static BMLogEntry *bm_log_entry_create(void)
* Note: does not free the log entry itself */
static void bm_log_entry_free(BMLogEntry *entry)
{
- if (entry->log) {
- entry->log->refcount--;
+ BMLog *log = entry->log;
+ bool kill_log = false;
+
+ if (log) {
+ log->refcount--;
- if (entry->log->refcount < 0) {
+ if (log->refcount < 0) {
fprintf(stderr, "BMLog refcount error\n");
- entry->log->refcount = 0;
+ log->refcount = 0;
}
+
+ kill_log = !log->refcount;
}
if (entry->full_copy_mesh) {
@@ -781,6 +781,10 @@ static void bm_log_entry_free(BMLogEntry *entry)
CustomData_free(&entry->edata, 0);
CustomData_free(&entry->ldata, 0);
CustomData_free(&entry->pdata, 0);
+
+ if (kill_log) {
+ bm_log_free_direct(log, true);
+ }
}
static void bm_log_id_ghash_retake(RangeTreeUInt *unused_ids, GHash *id_ghash)
@@ -981,7 +985,7 @@ BMLog *BM_log_unfreeze(BMesh *bm, BMLogEntry *entry)
/* Free all the data in a BMLog including the log itself
* safe_mode means log->refcount will be checked, and if nonzero log will not be freed
*/
-bool BM_log_free(BMLog *log, bool safe_mode)
+static bool bm_log_free_direct(BMLog *log, bool safe_mode)
{
BMLogEntry *entry;
@@ -998,6 +1002,8 @@ bool BM_log_free(BMLog *log, bool safe_mode)
return false;
}
+ log->dead = true;
+
BLI_rw_mutex_end(&log->lock);
if (log->unused_ids) {
@@ -1018,11 +1024,24 @@ bool BM_log_free(BMLog *log, bool safe_mode)
entry->log = NULL;
}
- MEM_freeN(log);
-
return true;
}
+bool BM_log_free(BMLog *log, bool safe_mode)
+{
+ if (log->dead) {
+ MEM_freeN(log);
+ return true;
+ }
+
+ if (bm_log_free_direct(log, safe_mode)) {
+ MEM_freeN(log);
+ return true;
+ }
+
+ return false;
+}
+
/* Get the number of log entries */
int BM_log_length(const BMLog *log)
{
@@ -1127,6 +1146,12 @@ BMLogEntry *BM_log_entry_add(BMesh *bm, BMLog *log)
BMLogEntry *BM_log_entry_add_ex(BMesh *bm, BMLog *log, bool combine_with_last)
{
+ if (log->dead) {
+ fprintf(stderr, "BMLog Error: log is dead\n");
+ fflush(stderr);
+ return NULL;
+ }
+
log->bm = bm;
/* WARNING: this is now handled by the UndoSystem: BKE_UNDOSYS_TYPE_SCULPT
diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index f5bfd22bd51..6565df13ea8 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -28,6 +28,8 @@
#define ELE_OUT 1
+#include "BLI_compiler_attrs.h"
+
void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
{
const float dist = BMO_slot_float_get(op->slots_in, "dist");
@@ -96,6 +98,10 @@ void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
BMO_ITER (v, &siter, op_bisect.slots_out, "geom_cut.out", BM_VERT) {
+ if (!BM_vert_is_boundary(v)) {
+ continue;
+ }
+
BMVert *v_dupe = BMO_slot_map_elem_get(slot_vertmap, v);
BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_dupe, v);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 2ed195c5c41..ed676aaccf8 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -872,7 +872,7 @@ int SCULPT_vertex_face_set_get(S
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list