fix for limited dissolve (after sine intended fixes - not cleaning up before vertex dissolve would skip dissolving some verts that should be dissolved).
now do this: - edge dissolve - cleanup (removing edges left over from dissolving faces) cleanup removes verts and NULL vertex input array - dissolve verts which haven't been removed.
This commit is contained in:
@@ -34,14 +34,14 @@
|
||||
|
||||
#include "intern/bmesh_operators_private.h" /* own include */
|
||||
|
||||
#define FACE_MARK 1
|
||||
#define FACE_ORIG 2
|
||||
#define FACE_NEW 4
|
||||
#define EDGE_MARK 1
|
||||
#define FACE_MARK 1
|
||||
#define FACE_ORIG 2
|
||||
#define FACE_NEW 4
|
||||
#define EDGE_MARK 1
|
||||
|
||||
#define VERT_MARK 1
|
||||
#define VERT_MARK 1
|
||||
|
||||
static int UNUSED_FUNCTION(check_hole_in_region)(BMesh *bm, BMFace *f)
|
||||
static int UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f)
|
||||
{
|
||||
BMWalker regwalker;
|
||||
BMIter liter2;
|
||||
@@ -60,8 +60,8 @@ static int UNUSED_FUNCTION(check_hole_in_region)(BMesh *bm, BMFace *f)
|
||||
l2 = BM_iter_new(&liter2, bm, BM_LOOPS_OF_FACE, f2);
|
||||
for ( ; l2; l2 = BM_iter_step(&liter2)) {
|
||||
l3 = l2->radial_next;
|
||||
if ( BMO_elem_flag_test(bm, l3->f, FACE_MARK) !=
|
||||
BMO_elem_flag_test(bm, l2->f, FACE_MARK))
|
||||
if (BMO_elem_flag_test(bm, l3->f, FACE_MARK) !=
|
||||
BMO_elem_flag_test(bm, l2->f, FACE_MARK))
|
||||
{
|
||||
if (!BMO_elem_flag_test(bm, l2->e, EDGE_MARK)) {
|
||||
return FALSE;
|
||||
@@ -433,8 +433,8 @@ void dummy_exec(BMesh *bm, BMOperator *op)
|
||||
fe = l->e;
|
||||
for ( ; l; l = BM_iter_step(&liter)) {
|
||||
f2 = BM_iter_new(&fiter, bm,
|
||||
BM_FACES_OF_EDGE, l->e);
|
||||
for ( ; f2; f2 = BM_iter_step(&fiter)) {
|
||||
BM_FACES_OF_EDGE, l->e);
|
||||
for (; f2; f2 = BM_iter_step(&fiter)) {
|
||||
if (f2 != f) {
|
||||
BM_faces_join_pair(bm, f, f2, l->e);
|
||||
found2 = 1;
|
||||
@@ -520,23 +520,28 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
|
||||
const float angle_max = (float)M_PI / 2.0f;
|
||||
const float angle_limit = minf(angle_max, BMO_slot_float_get(op, "angle_limit"));
|
||||
DissolveElemWeight *weight_elems = MEM_mallocN(MAX2(einput->len, vinput->len) *
|
||||
sizeof(DissolveElemWeight), __func__);
|
||||
sizeof(DissolveElemWeight), __func__);
|
||||
int i, tot_found;
|
||||
|
||||
BMIter iter;
|
||||
BMEdge *e_iter;
|
||||
BMEdge **earray;
|
||||
|
||||
int *vert_reverse_lookup;
|
||||
|
||||
BMEdge **einput_arr = (BMEdge **)einput->data.p;
|
||||
BMVert **vinput_arr = (BMVert **)vinput->data.p;
|
||||
|
||||
/* --- first edges --- */
|
||||
|
||||
/* wire -> tag */
|
||||
BM_ITER_MESH(e_iter, &iter, bm, BM_EDGES_OF_MESH) {
|
||||
BM_ITER_MESH (e_iter, &iter, bm, BM_EDGES_OF_MESH) {
|
||||
BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter));
|
||||
}
|
||||
|
||||
/* go through and split edge */
|
||||
for (i = 0, tot_found = 0; i < einput->len; i++) {
|
||||
BMEdge *e = ((BMEdge **)einput->data.p)[i];
|
||||
BMEdge *e = einput_arr[i];
|
||||
const float angle = BM_edge_calc_face_angle(e);
|
||||
|
||||
if (angle < angle_limit) {
|
||||
@@ -573,10 +578,51 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
|
||||
}
|
||||
}
|
||||
|
||||
/* prepare for cleanup */
|
||||
BM_mesh_elem_index_ensure(bm, BM_VERT);
|
||||
vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__);
|
||||
fill_vn_i(vert_reverse_lookup, bm->totvert, -1);
|
||||
for (i = 0, tot_found = 0; i < vinput->len; i++) {
|
||||
BMVert *v = vinput_arr[i];
|
||||
vert_reverse_lookup[BM_elem_index_get(v)] = i;
|
||||
}
|
||||
|
||||
/* --- cleanup --- */
|
||||
earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__);
|
||||
BM_ITER_MESH_INDEX (e_iter, &iter, bm, BM_EDGES_OF_MESH, i) {
|
||||
earray[i] = e_iter;
|
||||
}
|
||||
/* remove all edges/verts left behind from dissolving, NULL'ing the vertex array so we dont re-use */
|
||||
for (i = bm->totedge - 1; i != -1; i--) {
|
||||
e_iter = earray[i];
|
||||
|
||||
if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) {
|
||||
/* edge has become wire */
|
||||
int vidx_reverse;
|
||||
BMVert *v1 = e_iter->v1;
|
||||
BMVert *v2 = e_iter->v2;
|
||||
BM_edge_kill(bm, e_iter);
|
||||
if (v1->e == NULL) {
|
||||
vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v1)];
|
||||
if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL;
|
||||
BM_vert_kill(bm, v1);
|
||||
}
|
||||
if (v2->e == NULL) {
|
||||
vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v2)];
|
||||
if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL;
|
||||
BM_vert_kill(bm, v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
MEM_freeN(vert_reverse_lookup);
|
||||
|
||||
MEM_freeN(earray);
|
||||
|
||||
|
||||
/* --- second verts --- */
|
||||
for (i = 0, tot_found = 0; i < vinput->len; i++) {
|
||||
BMVert *v = ((BMVert **)vinput->data.p)[i];
|
||||
const float angle = bm_vert_edge_face_angle(v);
|
||||
BMVert *v = vinput_arr[i];
|
||||
const float angle = v ? bm_vert_edge_face_angle(v) : angle_limit;
|
||||
|
||||
if (angle < angle_limit) {
|
||||
weight_elems[i].ele = (BMHeader *)v;
|
||||
@@ -609,25 +655,4 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op)
|
||||
}
|
||||
|
||||
MEM_freeN(weight_elems);
|
||||
|
||||
/* --- cleanup --- */
|
||||
earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__);
|
||||
BM_ITER_MESH_INDEX(e_iter, &iter, bm, BM_EDGES_OF_MESH, i) {
|
||||
earray[i] = e_iter;
|
||||
}
|
||||
/* remove all edges/verts left behind from dissolving */
|
||||
for (i = bm->totedge - 1; i != -1; i--) {
|
||||
e_iter = earray[i];
|
||||
|
||||
if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) {
|
||||
/* edge has become wire */
|
||||
BMVert *v1 = e_iter->v1;
|
||||
BMVert *v2 = e_iter->v2;
|
||||
BM_edge_kill(bm, e_iter);
|
||||
if (v1->e == NULL) BM_vert_kill(bm, v1);
|
||||
if (v2->e == NULL) BM_vert_kill(bm, v2);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(earray);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user