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:
Joseph Eagar
2009-03-13 13:11:50 +00:00
parent 215f0fa27d
commit 7b5f9c2dec
7 changed files with 266 additions and 112 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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(&regwalker, bm, BMW_ISLAND, FACE_MARK);
f2 = BMW_Begin(&regwalker, f);
for (; f2; f2=BMW_Step(&regwalker)) {
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(&regwalker, bm, BMW_ISLAND, FACE_MARK);
f2 = BMW_Begin(&regwalker, region[0]->f);
for (; f2; f2=BMW_Step(&regwalker)) {
BMO_ClearFlag(bm, f2, FACE_MARK);
BMO_SetFlag(bm, f2, FACE_ORIG);
}
BMW_End(&regwalker);
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(&regwalker);
BMW_Init(&regwalker, bm, BMW_ISLAND, FACE_MARK);
f2 = BMW_Begin(&regwalker, f);
for (; f2; f2=BMW_Step(&regwalker)) {
BMO_ClearFlag(bm, f2, FACE_MARK);
BMO_SetFlag(bm, f2, FACE_ORIG);
}
BMW_End(&regwalker);
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;
}

View File

@@ -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);