Dissolve faces now uses a different method of finding the boundary,
that handles some non-manifold situations better without failing. Also made edge subdivide use a more specializzed internal version of BM_Connect_Verts, that should hopefully always split the correct face. Dissolve verts also now has checks to not accidentally dissolve unselected vertices. It's not kindof a hybrid tool, using dissolve faces where it can to dissolve verts for robustness, and using BM_Dissolve_Verts where it cannot. And removed some cruft from a few API functions.
This commit is contained in:
@@ -191,11 +191,18 @@ void BM_remove_tagged_verts(struct BMesh *bm, int flag);
|
||||
|
||||
|
||||
/*Modification*/
|
||||
struct BMFace *BM_Join_Faces(struct BMesh *bm, struct BMFace *f1, struct BMFace *f2, struct BMEdge *e, int calcnorm, int weldUVs);
|
||||
struct BMFace *BM_Split_Face(struct BMesh *bm, struct BMFace *f, struct BMVert *v1, struct BMVert *v2, struct BMLoop **nl, struct BMEdge *example, int calcnorm);
|
||||
void BM_Collapse_Vert(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv, float fac, int calcnorm);
|
||||
struct BMVert *BM_Split_Edge(struct BMesh *bm, struct BMVert *v, struct BMEdge *e, struct BMEdge **ne, float percent, int calcnorm);
|
||||
struct BMVert *BM_Split_Edge_Multi(struct BMesh *bm, struct BMEdge *e, int numcuts);
|
||||
struct BMFace *BM_Join_Faces(struct BMesh *bm, struct BMFace *f1,
|
||||
struct BMFace *f2, struct BMEdge *e);
|
||||
struct BMFace *BM_Split_Face(struct BMesh *bm, struct BMFace *f,
|
||||
struct BMVert *v1, struct BMVert *v2,
|
||||
struct BMLoop **nl, struct BMEdge *example);
|
||||
void BM_Collapse_Vert(struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv,
|
||||
float fac);
|
||||
struct BMVert *BM_Split_Edge(struct BMesh *bm, struct BMVert *v,
|
||||
struct BMEdge *e, struct BMEdge **ne,
|
||||
float percent);
|
||||
struct BMVert *BM_Split_Edge_Multi(struct BMesh *bm, struct BMEdge *e,
|
||||
int numcuts);
|
||||
BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf);
|
||||
void BM_Face_UpdateNormal(BMesh *bm, BMFace *f);
|
||||
void BM_Edge_UpdateNormals(BMesh *bm, BMEdge *e);
|
||||
|
||||
@@ -103,7 +103,7 @@ int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
|
||||
increasing valence to four. this may be hackish. . .*/
|
||||
loop = e->loop;
|
||||
if (loop->v == v) loop = (BMLoop*) loop->head.next;
|
||||
if (!BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL, 0))
|
||||
if (!BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
BM_Dissolve_Disk(bm, v);
|
||||
@@ -113,8 +113,8 @@ int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
|
||||
f = v->edge->loop->f;
|
||||
f2 = ((BMLoop*)v->edge->loop->radial.next->data)->f;
|
||||
/*collapse the vertex*/
|
||||
BM_Collapse_Vert(bm, v->edge, v, 1.0, 0);
|
||||
BM_Join_Faces(bm, f, f2, NULL, 0, 0);
|
||||
BM_Collapse_Vert(bm, v->edge, v, 1.0);
|
||||
BM_Join_Faces(bm, f, f2, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -128,7 +128,7 @@ int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
|
||||
f = NULL;
|
||||
len = bmesh_cycle_length(&(e->loop->radial));
|
||||
if(len == 2 && (e!=baseedge) && (e!=keepedge)) {
|
||||
f = BM_Join_Faces(bm, e->loop->f, ((BMLoop*)(e->loop->radial.next->data))->f, e, 0, 0);
|
||||
f = BM_Join_Faces(bm, e->loop->f, ((BMLoop*)(e->loop->radial.next->data))->f, e);
|
||||
/*return if couldn't join faces in manifold
|
||||
conditions.*/
|
||||
//!disabled for testing why bad things happen
|
||||
@@ -148,11 +148,11 @@ int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
|
||||
f2 = ((BMLoop*)v->edge->loop->radial.next->data)->f;
|
||||
|
||||
/*collapse the vertex*/
|
||||
BM_Collapse_Vert(bm, baseedge, v, 1.0, 0);
|
||||
BM_Collapse_Vert(bm, baseedge, v, 1.0);
|
||||
|
||||
if (f != f2) {
|
||||
/*join two remaining faces*/
|
||||
if (!BM_Join_Faces(bm, f, f2, NULL, 0, 0)) return 0;
|
||||
if (!BM_Join_Faces(bm, f, f2, NULL)) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
|
||||
if(len == 2){
|
||||
f = BM_Join_Faces(bm,e->loop->f,((BMLoop*)
|
||||
(e->loop->radial.next->data))->f,
|
||||
e, 1, 0);
|
||||
e);
|
||||
}
|
||||
if(f){
|
||||
done = 0;
|
||||
@@ -186,7 +186,7 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
|
||||
}
|
||||
};
|
||||
}
|
||||
BM_Collapse_Vert(bm, v->edge, v, 1.0, 1);
|
||||
BM_Collapse_Vert(bm, v->edge, v, 1.0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -194,16 +194,13 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
|
||||
/**
|
||||
* bmesh_join_faces
|
||||
*
|
||||
* joins two adjacenct faces togather. If weldUVs == 1
|
||||
* and the uv/vcols of the two faces are non-contigous, the
|
||||
* per-face properties of f2 will be transformed into place
|
||||
* around f1.
|
||||
* joins two adjacenct faces togather.
|
||||
*
|
||||
* Returns -
|
||||
* BMFace pointer
|
||||
*/
|
||||
|
||||
BMFace *BM_Join_Faces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, int calcnorm, int weldUVs) {
|
||||
BMFace *BM_Join_Faces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) {
|
||||
|
||||
BMLoop *l1, *l2;
|
||||
BMEdge *jed=NULL;
|
||||
@@ -229,8 +226,6 @@ BMFace *BM_Join_Faces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e, int calcnorm
|
||||
|
||||
f1 = bmesh_jfke(bm, f1, f2, jed);
|
||||
|
||||
if (calcnorm && f1) BM_Face_UpdateNormal(bm, f1);
|
||||
|
||||
return f1;
|
||||
}
|
||||
|
||||
@@ -255,7 +250,7 @@ BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
|
||||
for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
|
||||
for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
|
||||
if (v == v2) {
|
||||
face = BM_Split_Face(bm, face, v1, v2, &nl, NULL, 1);
|
||||
face = BM_Split_Face(bm, face, v1, v2, &nl, NULL);
|
||||
|
||||
if (nf) *nf = face;
|
||||
return nl->e;
|
||||
@@ -275,18 +270,13 @@ BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
|
||||
* BMFace pointer
|
||||
*/
|
||||
|
||||
BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *example, int calcnorm)
|
||||
BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *example)
|
||||
{
|
||||
BMFace *nf;
|
||||
nf = bmesh_sfme(bm,f,v1,v2,nl);
|
||||
|
||||
BM_Copy_Attributes(bm, bm, f, nf);
|
||||
|
||||
if (calcnorm && nf) {
|
||||
BM_Face_UpdateNormal(bm, nf);
|
||||
BM_Face_UpdateNormal(bm, f);
|
||||
}
|
||||
|
||||
return nf;
|
||||
}
|
||||
|
||||
@@ -307,7 +297,7 @@ BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl,
|
||||
* Nothing
|
||||
*/
|
||||
|
||||
void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, int calcnorm){
|
||||
void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
|
||||
void *src[2];
|
||||
float w[2];
|
||||
BMLoop *l=NULL, *kvloop=NULL, *tvloop=NULL;
|
||||
@@ -345,7 +335,7 @@ void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, int calcnorm
|
||||
* the new vert
|
||||
*/
|
||||
|
||||
BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percent, int calcnorm) {
|
||||
BMVert *BM_Split_Edge(BMesh *bm, BMVert *v, BMEdge *e, BMEdge **ne, float percent) {
|
||||
BMVert *nv, *v2;
|
||||
|
||||
v2 = bmesh_edge_getothervert(e,v);
|
||||
@@ -371,7 +361,7 @@ BMVert *BM_Split_Edge_Multi(BMesh *bm, BMEdge *e, int numcuts)
|
||||
|
||||
for(i=0; i < numcuts; i++){
|
||||
percent = 1.0f / (float)(numcuts + 1 - i);
|
||||
nv = BM_Split_Edge(bm, e->v2, e, NULL, percent, 0);
|
||||
nv = BM_Split_Edge(bm, e->v2, e, NULL, percent);
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
@@ -242,6 +242,85 @@ void compute_poly_plane(float (*verts)[3], int nverts)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BM LEGAL EDGES
|
||||
|
||||
takes in a face and a list of edges, and sets to NULL any edge in
|
||||
the list that bridges a concave region of the face or intersects
|
||||
any of the faces's edges.
|
||||
*/
|
||||
static void shrink_edge(float *v1, float *v2, float fac)
|
||||
{
|
||||
float mid[3];
|
||||
|
||||
VecAddf(mid, v1, v2);
|
||||
VecMulf(mid, 0.5f);
|
||||
|
||||
VecSubf(v1, v1, mid);
|
||||
VecSubf(v2, v2, mid);
|
||||
|
||||
VecMulf(v1, fac);
|
||||
VecMulf(v2, fac);
|
||||
|
||||
VecAddf(v1, v1, mid);
|
||||
VecAddf(v2, v2, mid);
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
void BM_LegalSplits(BMesh *bm, BMFace *f, BMLoop (*loops)[2], int len)
|
||||
{
|
||||
BMIter iter;
|
||||
BMLoop *l;
|
||||
float v1[3], v2[3], no[3], *p1, *p2;
|
||||
float projectverts[100][3];
|
||||
float edgevertsstack[100][2][3];
|
||||
float (*projverts)[3] = projectverts;
|
||||
float (*edgeverts)[2][3] = edgevertsstack;
|
||||
int i, nvert, j;
|
||||
|
||||
if (f->len > 100) projverts = MEM_mallocN(sizeof(float)*3*f->len, "projvertsb");
|
||||
if (len > 100) edgeverts = MEM_mallocN(sizeof(float)*3*2*len, "edgevertsb");
|
||||
|
||||
i = 0;
|
||||
l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
|
||||
for (; l; l=BMIter_Step(&iter)) {
|
||||
VECCOPY(projverts[i], l->v->co);
|
||||
i++;
|
||||
}
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
VECCOPY(v1, loops[i][0]->v->co);
|
||||
VECCOPY(v2, loops[i][0]->v->co);
|
||||
|
||||
shrink_edge(v1, v2, 0.9999f);
|
||||
|
||||
VECCOPY(edgeverts[i][0], v1);
|
||||
VECCOPY(edgeverts[i][1], v2);
|
||||
}
|
||||
|
||||
compute_poly_normal(no, projverts, f->len);
|
||||
poly_rotate_plane(no, projverts, f->len);
|
||||
poly_rotate_plane(no, edgeverts, len);
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
if (convexangle(
|
||||
}
|
||||
|
||||
for (i=0; i<f->len; i++) {
|
||||
for (j=0; j<len; j++) {
|
||||
p1 = projverts[i];
|
||||
p2 = projverts[(i+1)%f->len];
|
||||
if (convexangle(
|
||||
if (linecrosses(p1, p2,
|
||||
}
|
||||
}
|
||||
|
||||
if (projverts != projectverts) MEM_freeN(projverts);
|
||||
if (edgeverts != edgevertsstack) MEM_freeN(edgeverts);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* POLY ROTATE PLANE
|
||||
*
|
||||
@@ -308,7 +387,7 @@ void BM_Face_UpdateNormal(BMesh *bm, BMFace *f)
|
||||
|
||||
void BM_Edge_UpdateNormals(BMesh *bm, BMEdge *e)
|
||||
{
|
||||
BMIter *iter;
|
||||
BMIter iter;
|
||||
BMFace *f;
|
||||
|
||||
f = BMIter_New(&iter, bm, BM_FACES_OF_EDGE, e);
|
||||
@@ -578,7 +657,7 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
|
||||
v = l->v;
|
||||
f = BM_Split_Face(bm, l->f, ((BMLoop*)(l->head.prev))->v,
|
||||
((BMLoop*)(l->head.next))->v,
|
||||
&newl, NULL, 0);
|
||||
&newl, NULL);
|
||||
VECCOPY(f->no, l->f->no);
|
||||
|
||||
if (!f) {
|
||||
@@ -605,7 +684,7 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3],
|
||||
while (l->f->len > 3){
|
||||
nextloop = ((BMLoop*)(l->head.next->next));
|
||||
f = BM_Split_Face(bm, l->f, l->v, nextloop->v,
|
||||
&newl, NULL, 0);
|
||||
&newl, NULL);
|
||||
if (!f) {
|
||||
printf("triangle fan step of triangulator failed.\n");
|
||||
return;
|
||||
|
||||
@@ -256,7 +256,7 @@ static void fuse_fgon(BMesh *bm, BMFace *f)
|
||||
if (l->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
|
||||
if (((BMLoop*)l->radial.next->data)->f->head.flag & BM_ACTIVE) act = BM_ACTIVE;
|
||||
|
||||
sf = BM_Join_Faces(bm,l->f, ((BMLoop*)l->radial.next->data)->f, l->e, 0,0);
|
||||
sf = BM_Join_Faces(bm,l->f, ((BMLoop*)l->radial.next->data)->f, l->e);
|
||||
if (!sf) {
|
||||
//tesselation error
|
||||
break;
|
||||
|
||||
@@ -17,7 +17,7 @@ void connectverts_exec(BMesh *bm, BMOperator *op)
|
||||
BMIter iter, liter;
|
||||
BMFace *f, *nf;
|
||||
BMEdge *e;
|
||||
BMLoop *l;
|
||||
BMLoop *l, *nl;
|
||||
BMVert *v1, *v2;
|
||||
int ok;
|
||||
|
||||
@@ -41,13 +41,15 @@ void connectverts_exec(BMesh *bm, BMOperator *op)
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
e = BM_Connect_Verts(bm, v1, v2, &nf);
|
||||
if (!e) {
|
||||
|
||||
nf = BM_Split_Face(bm, f, v1, v2, &nl, NULL);
|
||||
|
||||
if (!nl || !nf) {
|
||||
BMO_RaiseError(bm, op,
|
||||
BMERR_CONNECTVERT_FAILED, NULL);
|
||||
return;
|
||||
}
|
||||
BMO_SetFlag(bm, e, EDGE_OUT);
|
||||
BMO_SetFlag(bm, nl->e, EDGE_OUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,15 +49,15 @@ static int check_hole_in_region(BMesh *bm, BMFace *f) {
|
||||
void dissolvefaces_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOIter oiter;
|
||||
BMIter liter, liter2;
|
||||
BMLoop *l, *l2;
|
||||
BMIter liter, liter2, liter3;
|
||||
BMLoop *l, *l2, *l3;
|
||||
BMFace *f, *f2, *nf = NULL;
|
||||
V_DECLARE(region);
|
||||
V_DECLARE(regions);
|
||||
BMLoop ***regions = NULL;
|
||||
BMLoop **region = NULL;
|
||||
BMWalker walker, regwalker;
|
||||
int i, j, a, fcopied;
|
||||
BMWalker regwalker;
|
||||
int i, j, fcopied;
|
||||
|
||||
BMO_Flag_Buffer(bm, op, BMOP_DISFACES_FACEIN, FACE_MARK);
|
||||
|
||||
@@ -66,62 +66,50 @@ void dissolvefaces_exec(BMesh *bm, BMOperator *op)
|
||||
for (; f; f=BMO_IterStep(&oiter)) {
|
||||
if (!BMO_TestFlag(bm, f, FACE_MARK)) continue;
|
||||
|
||||
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
|
||||
for (; l; l=BMIter_Step(&liter)) {
|
||||
l2 = bmesh_radial_nextloop(l);
|
||||
if (l2!=l && BMO_TestFlag(bm, l2->f, FACE_MARK))
|
||||
continue;
|
||||
if (BM_FacesAroundEdge(l->e) <= 2) {
|
||||
V_RESET(region);
|
||||
region = NULL; /*forces different allocation*/
|
||||
V_RESET(region);
|
||||
region = NULL; /*forces different allocation*/
|
||||
|
||||
/*yay, walk!*/
|
||||
BMW_Init(&walker, bm, BMW_ISLANDBOUND, FACE_MARK);
|
||||
l = BMW_Begin(&walker, l);
|
||||
for (; l; l=BMW_Step(&walker)) {
|
||||
/*yay, walk!*/
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK);
|
||||
f2 = BMW_Begin(®walker, f);
|
||||
for (; f2; f2=BMW_Step(®walker)) {
|
||||
l2 = BMIter_New(&liter2, bm, BM_LOOPS_OF_FACE, f2);
|
||||
for (; l2; l2=BMIter_Step(&liter2)) {
|
||||
l3 = BMIter_New(&liter3, bm, BM_LOOPS_OF_LOOP, l2);
|
||||
for (; l3; l3=BMIter_Step(&liter3)) {
|
||||
if (!BMO_TestFlag(bm, l3->f, FACE_MARK)) {
|
||||
V_GROW(region);
|
||||
region[V_COUNT(region)-1] = l2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bmesh_radial_nextloop(l2) == l2) {
|
||||
V_GROW(region);
|
||||
region[V_COUNT(region)-1] = l;
|
||||
BMO_SetFlag(bm, l->e, EDGE_MARK);
|
||||
region[V_COUNT(region)-1] = l2;
|
||||
}
|
||||
BMW_End(&walker);
|
||||
|
||||
if (BMO_HasError(bm)) {
|
||||
BMO_ClearStack(bm);
|
||||
BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (region == NULL) continue;
|
||||
|
||||
/*check for holes in boundary*/
|
||||
if (!check_hole_in_region(bm, region[0]->f)) {
|
||||
BMO_RaiseError(bm, op,
|
||||
BMERR_DISSOLVEFACES_FAILED,
|
||||
"Hole(s) in face region");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK);
|
||||
f2 = BMW_Begin(®walker, region[0]->f);
|
||||
for (; f2; f2=BMW_Step(®walker)) {
|
||||
BMO_ClearFlag(bm, f2, FACE_MARK);
|
||||
BMO_SetFlag(bm, f2, FACE_ORIG);
|
||||
}
|
||||
BMW_End(®walker);
|
||||
|
||||
if (BMO_HasError(bm)) {
|
||||
BMO_ClearStack(bm);
|
||||
BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
V_GROW(region);
|
||||
V_GROW(regions);
|
||||
regions[V_COUNT(regions)-1] = region;
|
||||
region[V_COUNT(region)-1] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BMW_End(®walker);
|
||||
|
||||
BMW_Init(®walker, bm, BMW_ISLAND, FACE_MARK);
|
||||
f2 = BMW_Begin(®walker, f);
|
||||
for (; f2; f2=BMW_Step(®walker)) {
|
||||
BMO_ClearFlag(bm, f2, FACE_MARK);
|
||||
BMO_SetFlag(bm, f2, FACE_ORIG);
|
||||
}
|
||||
|
||||
BMW_End(®walker);
|
||||
|
||||
if (BMO_HasError(bm)) {
|
||||
BMO_ClearStack(bm);
|
||||
BMO_RaiseError(bm, op, BMERR_DISSOLVEFACES_FAILED, NULL);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
V_GROW(region);
|
||||
V_GROW(regions);
|
||||
regions[V_COUNT(regions)-1] = region;
|
||||
region[V_COUNT(region)-1] = NULL;
|
||||
}
|
||||
|
||||
for (i=0; i<V_COUNT(regions); i++) {
|
||||
@@ -192,6 +180,45 @@ cleanup:
|
||||
V_FREE(regions);
|
||||
}
|
||||
|
||||
static int test_extra_verts(BMesh *bm, BMVert *v)
|
||||
{
|
||||
BMIter iter, liter, iter2, iter3;
|
||||
BMFace *f, *f2;
|
||||
BMLoop *l;
|
||||
BMEdge *e;
|
||||
int found;
|
||||
|
||||
/*test faces around verts for verts that would be wronly killed
|
||||
by dissolve faces.*/
|
||||
f = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v);
|
||||
for (; f; f=BMIter_Step(&iter)) {
|
||||
l=BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f);
|
||||
for (; l; l=BMIter_Step(&liter)) {
|
||||
if (!BMO_TestFlag(bm, l->v, VERT_MARK)) {
|
||||
/*if an edge around a vert is a boundary edge,
|
||||
then dissolve faces won't destroy it.
|
||||
also if it forms a boundary with one
|
||||
of the face regions*/
|
||||
found = 0;
|
||||
e = BMIter_New(&iter2, bm, BM_EDGES_OF_VERT, l->v);
|
||||
for (; e; e=BMIter_Step(&iter2)) {
|
||||
if (BM_FacesAroundEdge(e)==1) found = 1;
|
||||
f2 = BMIter_New(&iter3, bm, BM_FACES_OF_EDGE, e);
|
||||
for (; f2; f2=BMIter_Step(&iter3)) {
|
||||
if (!BMO_TestFlag(bm, f2, FACE_MARK)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
if (!found) return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
void dissolveverts_exec(BMesh *bm, BMOperator *op)
|
||||
{
|
||||
BMOpSlot *vinput;
|
||||
@@ -208,8 +235,26 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op)
|
||||
if (BMO_TestFlag(bm, v, VERT_MARK)) {
|
||||
f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
|
||||
for (; f; f=BMIter_Step(&fiter)) {
|
||||
BMO_SetFlag(bm, f, FACE_ORIG);
|
||||
BMO_SetFlag(bm, f, FACE_MARK);
|
||||
}
|
||||
|
||||
/*check if our additions to the input to face dissolve
|
||||
will destroy nonmarked vertices.*/
|
||||
if (!test_extra_verts(bm, v)) {
|
||||
f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
|
||||
for (; f; f=BMIter_Step(&fiter)) {
|
||||
if (BMO_TestFlag(bm, f, FACE_ORIG)) {
|
||||
BMO_ClearFlag(bm, f, FACE_MARK);
|
||||
BMO_ClearFlag(bm, f, FACE_ORIG);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
f=BMIter_New(&fiter, bm, BM_FACES_OF_VERT, v);
|
||||
for (; f; f=BMIter_Step(&fiter)) {
|
||||
BMO_ClearFlag(bm, f, FACE_ORIG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,8 +309,7 @@ void dissolveverts_exec(BMesh *bm, BMOperator *op)
|
||||
BM_FACES_OF_EDGE, l->e);
|
||||
for (; f2; f2=BMIter_Step(&fiter)) {
|
||||
if (f2 != f) {
|
||||
BM_Join_Faces(bm, f, f2, l->e,
|
||||
1, 0);
|
||||
BM_Join_Faces(bm, f, f2, l->e);
|
||||
found2 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,34 @@ NOTE: beauty has been renamed to flag!
|
||||
split the edge only?
|
||||
*/
|
||||
|
||||
/*connects face with smallest len, which I think should always be correct for
|
||||
edge subdivision*/
|
||||
BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
|
||||
BMIter iter, iter2;
|
||||
BMVert *v;
|
||||
BMLoop *nl;
|
||||
BMFace *face, *curf = NULL;
|
||||
|
||||
/*this isn't the best thing in the world. it doesn't handle cases where there's
|
||||
multiple faces yet. that might require a convexity test to figure out which
|
||||
face is "best," and who knows what for non-manifold conditions.*/
|
||||
for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
|
||||
for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
|
||||
if (v == v2) {
|
||||
if (!curf || face->len < curf->len) curf = face;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (curf) {
|
||||
face = BM_Split_Face(bm, curf, v1, v2, &nl, NULL);
|
||||
|
||||
if (nf) *nf = face;
|
||||
return nl ? nl->e : NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* calculates offset for co, based on fractal, sphere or smooth settings */
|
||||
static void alter_co(float *co, BMEdge *edge, subdparams *params, float perc,
|
||||
BMVert *vsta, BMVert *vend)
|
||||
@@ -119,7 +147,7 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,
|
||||
BMVert *ev;
|
||||
// float co[3];
|
||||
|
||||
ev = BM_Split_Edge(bm, edge->v1, edge, out, percent, 1);
|
||||
ev = BM_Split_Edge(bm, edge->v1, edge, out, percent);
|
||||
BMO_SetFlag(bm, ev, ELE_INNER);
|
||||
|
||||
/* offset for smooth or sphere or fractal */
|
||||
@@ -204,17 +232,17 @@ static void q_1edge_split(BMesh *bm, BMFace *face,
|
||||
add = 2;
|
||||
for (i=0; i<numcuts; i++) {
|
||||
if (i == numcuts/2) add -= 1;
|
||||
BM_Connect_Verts(bm, verts[i], verts[numcuts+add],
|
||||
connect_smallest_face(bm, verts[i], verts[numcuts+add],
|
||||
&nf);
|
||||
}
|
||||
} else {
|
||||
add = 2;
|
||||
for (i=0; i<numcuts; i++) {
|
||||
BM_Connect_Verts(bm, verts[i], verts[numcuts+add],
|
||||
connect_smallest_face(bm, verts[i], verts[numcuts+add],
|
||||
&nf);
|
||||
if (i == numcuts/2) {
|
||||
add -= 1;
|
||||
BM_Connect_Verts(bm, verts[i],
|
||||
connect_smallest_face(bm, verts[i],
|
||||
verts[numcuts+add],
|
||||
&nf);
|
||||
}
|
||||
@@ -248,7 +276,7 @@ static void q_2edge_op_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
int i, numcuts = params->numcuts;
|
||||
|
||||
for (i=0; i<numcuts; i++) {
|
||||
BM_Connect_Verts(bm, verts[i],verts[(numcuts-i-1)+numcuts+2],
|
||||
connect_smallest_face(bm, verts[i],verts[(numcuts-i-1)+numcuts+2],
|
||||
&nf);
|
||||
}
|
||||
}
|
||||
@@ -275,10 +303,10 @@ static void q_2edge_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
int i, numcuts = params->numcuts;
|
||||
|
||||
for (i=0; i<numcuts; i++) {
|
||||
BM_Connect_Verts(bm, verts[i], verts[numcuts+(numcuts-i)],
|
||||
connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
|
||||
&nf);
|
||||
}
|
||||
BM_Connect_Verts(bm, verts[numcuts*2+3], verts[numcuts*2+1], &nf);
|
||||
connect_smallest_face(bm, verts[numcuts*2+3], verts[numcuts*2+1], &nf);
|
||||
}
|
||||
|
||||
subdpattern q_2edge = {
|
||||
@@ -306,17 +334,17 @@ static void q_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
for (i=0; i<numcuts; i++) {
|
||||
if (i == numcuts/2) {
|
||||
if (numcuts % 2 != 0) {
|
||||
BM_Connect_Verts(bm, verts[numcuts-i-1+add],
|
||||
connect_smallest_face(bm, verts[numcuts-i-1+add],
|
||||
verts[i+numcuts+1], &nf);
|
||||
}
|
||||
add = numcuts*2+2;
|
||||
}
|
||||
BM_Connect_Verts(bm, verts[numcuts-i-1+add],
|
||||
connect_smallest_face(bm, verts[numcuts-i-1+add],
|
||||
verts[i+numcuts+1], &nf);
|
||||
}
|
||||
|
||||
for (i=0; i<numcuts/2+1; i++) {
|
||||
BM_Connect_Verts(bm, verts[i],verts[(numcuts-i)+numcuts*2+1],
|
||||
connect_smallest_face(bm, verts[i],verts[(numcuts-i)+numcuts*2+1],
|
||||
&nf);
|
||||
}
|
||||
}
|
||||
@@ -369,7 +397,9 @@ static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
a = i;
|
||||
b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
|
||||
|
||||
e = BM_Connect_Verts(bm, verts[a], verts[b], &nf);
|
||||
e = connect_smallest_face(bm, verts[a], verts[b], &nf);
|
||||
if (!e) continue;
|
||||
|
||||
BMO_SetFlag(bm, e, ELE_INNER);
|
||||
BMO_SetFlag(bm, nf, ELE_INNER);
|
||||
|
||||
@@ -389,7 +419,9 @@ static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
for (j=1; j<numcuts+1; j++) {
|
||||
a = i*s + j;
|
||||
b = (i-1)*s + j;
|
||||
e = BM_Connect_Verts(bm, lines[a], lines[b], &nf);
|
||||
e = connect_smallest_face(bm, lines[a], lines[b], &nf);
|
||||
if (!e) continue;
|
||||
|
||||
BMO_SetFlag(bm, e, ELE_INNER);
|
||||
BMO_SetFlag(bm, nf, ELE_INNER);
|
||||
}
|
||||
@@ -414,7 +446,7 @@ static void t_1edge_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
int i, numcuts = params->numcuts;
|
||||
|
||||
for (i=0; i<numcuts; i++) {
|
||||
BM_Connect_Verts(bm, verts[i], verts[numcuts+1], &nf);
|
||||
connect_smallest_face(bm, verts[i], verts[numcuts+1], &nf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +472,7 @@ static void t_2edge_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
int i, numcuts = params->numcuts;
|
||||
|
||||
for (i=0; i<numcuts; i++) {
|
||||
BM_Connect_Verts(bm, verts[i], verts[numcuts+numcuts-i], &nf);
|
||||
connect_smallest_face(bm, verts[i], verts[numcuts+numcuts-i], &nf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,7 +520,7 @@ static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
|
||||
"triangle vert table row");
|
||||
a = numcuts*2 + 2 + i;
|
||||
b = numcuts + numcuts - i;
|
||||
e = BM_Connect_Verts(bm, verts[a], verts[b], &nf);
|
||||
e = connect_smallest_face(bm, verts[a], verts[b], &nf);
|
||||
if (!e) goto cleanup;
|
||||
|
||||
BMO_SetFlag(bm, e, ELE_INNER);
|
||||
@@ -518,13 +550,13 @@ sv7/---v---\ v3 s
|
||||
*/
|
||||
for (i=1; i<numcuts+1; i++) {
|
||||
for (j=0; j<i; j++) {
|
||||
e= BM_Connect_Verts(bm, lines[i][j], lines[i+1][j+1],
|
||||
e= connect_smallest_face(bm, lines[i][j], lines[i+1][j+1],
|
||||
&nf);
|
||||
|
||||
BMO_SetFlag(bm, e, ELE_INNER);
|
||||
BMO_SetFlag(bm, nf, ELE_INNER);
|
||||
|
||||
e= BM_Connect_Verts(bm,lines[i][j+1],lines[i+1][j+1],
|
||||
e= connect_smallest_face(bm,lines[i][j+1],lines[i+1][j+1],
|
||||
&nf);
|
||||
|
||||
BMO_SetFlag(bm, e, ELE_INNER);
|
||||
|
||||
Reference in New Issue
Block a user