diff options
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_walkers_impl.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_walkers_impl.c | 911 |
1 files changed, 911 insertions, 0 deletions
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c new file mode 100644 index 00000000000..e6bcbf405fe --- /dev/null +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -0,0 +1,911 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Joseph Eagar, Geoffrey Bantle, Levi Schooley. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/intern/bmesh_walkers_impl.c + * \ingroup bmesh + * + * BMesh Walker Code. + */ + +#include "BKE_customdata.h" + +#include "bmesh.h" +#include "bmesh_private.h" +#include "bmesh_walkers_private.h" + +/* Shell Walker: + * + * Starts at a vertex on the mesh and walks over the 'shell' it belongs + * to via visiting connected edges. + * + * TODO: + * + * Add restriction flag/callback for wire edges. + * + */ + +static void shellWalker_visitEdge(BMWalker *walker, BMEdge *e) +{ + shellWalker *shellWalk = NULL; + + if (BLI_ghash_haskey(walker->visithash, e)) { + return; + } + + if (walker->mask_edge && !BMO_elem_flag_test(walker->bm, e, walker->mask_edge)) { + return; + } + + shellWalk = BMW_state_add(walker); + shellWalk->curedge = e; + BLI_ghash_insert(walker->visithash, e, NULL); +} + +static void shellWalker_begin(BMWalker *walker, void *data) +{ + BMIter eiter; + BMHeader *h = data; + BMEdge *e; + BMVert *v; + + if (h == NULL) + { + return; + } + + switch (h->htype) { + case BM_VERT: + { + /* starting the walk at a vert, add all the edges + * to the worklist */ + v = (BMVert *)h; + BM_ITER(e, &eiter, walker->bm, BM_EDGES_OF_VERT, v) { + shellWalker_visitEdge(walker, e); + } + break; + } + + case BM_EDGE: + { + /* starting the walk at an edge, add the single edge + * to the worklist */ + e = (BMEdge *)h; + shellWalker_visitEdge(walker, e); + break; + } + } +} + +static void *shellWalker_yield(BMWalker *walker) +{ + shellWalker *shellWalk = BMW_current_state(walker); + return shellWalk->curedge; +} + +static void *shellWalker_step(BMWalker *walker) +{ + shellWalker *swalk = BMW_current_state(walker); + BMEdge *e, *e2; + BMVert *v; + BMIter iter; + int i; + + e = swalk->curedge; + BMW_state_remove(walker); + + for (i = 0; i < 2; i++) { + v = i ? e->v2 : e->v1; + BM_ITER(e2, &iter, walker->bm, BM_EDGES_OF_VERT, v) { + shellWalker_visitEdge(walker, e2); + } + } + + return e; +} + +#if 0 +static void *shellWalker_step(BMWalker *walker) +{ + BMEdge *curedge, *next = NULL; + BMVert *ov = NULL; + int restrictpass = 1; + shellWalker shellWalk = *((shellWalker *)BMW_current_state(walker)); + + if (!BLI_ghash_haskey(walker->visithash, shellWalk.base)) { + BLI_ghash_insert(walker->visithash, shellWalk.base, NULL); + } + + BMW_state_remove(walker); + + + /* find the next edge whose other vertex has not been visite */ + curedge = shellWalk.curedge; + do { + if (!BLI_ghash_haskey(walker->visithash, curedge)) { + if (!walker->restrictflag || + (walker->restrictflag && BMO_elem_flag_test(walker->bm, curedge, walker->restrictflag))) + { + shellWalker *newstate; + + ov = BM_edge_other_vert(curedge, shellWalk.base); + + /* push a new state onto the stac */ + newState = BMW_state_add(walker); + BLI_ghash_insert(walker->visithash, curedge, NULL); + + /* populate the new stat */ + + newState->base = ov; + newState->curedge = curedge; + } + } + curedge = bmesh_disk_nextedge(curedge, shellWalk.base); + } while (curedge != shellWalk.curedge); + + return shellWalk.curedge; +} +#endif + +/* Connected Vertex Walker: + * + * Similar to shell walker, but visits vertices instead of edges. + * + */ + +static void connectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v) +{ + connectedVertexWalker *vwalk; + + if (BLI_ghash_haskey(walker->visithash, v)) { + /* already visited */ + return; + } + if (walker->mask_vert && !BMO_elem_flag_test(walker->bm, v, walker->mask_vert)) { + /* not flagged for walk */ + return; + } + + vwalk = BMW_state_add(walker); + vwalk->curvert = v; + BLI_ghash_insert(walker->visithash, v, NULL); +} + +static void connectedVertexWalker_begin(BMWalker *walker, void *data) +{ + BMVert *v = data; + connectedVertexWalker_visitVertex(walker, v); +} + +static void *connectedVertexWalker_yield(BMWalker *walker) +{ + connectedVertexWalker *vwalk = BMW_current_state(walker); + return vwalk->curvert; +} + +static void *connectedVertexWalker_step(BMWalker *walker) +{ + connectedVertexWalker *vwalk = BMW_current_state(walker); + BMVert *v, *v2; + BMEdge *e; + BMIter iter; + + v = vwalk->curvert; + + BMW_state_remove(walker); + + BM_ITER(e, &iter, walker->bm, BM_EDGES_OF_VERT, v) { + v2 = BM_edge_other_vert(e, v); + if (!BLI_ghash_haskey(walker->visithash, v2)) { + connectedVertexWalker_visitVertex(walker, v2); + } + } + + return v; +} + +/* Island Boundary Walker: + * + * Starts at a edge on the mesh and walks over the boundary of an + * island it belongs to. + * + * TODO: + * + * Add restriction flag/callback for wire edges. + * + */ + +static void islandboundWalker_begin(BMWalker *walker, void *data) +{ + BMLoop *l = data; + islandboundWalker *iwalk = NULL; + + iwalk = BMW_state_add(walker); + + iwalk->base = iwalk->curloop = l; + iwalk->lastv = l->v; + + BLI_ghash_insert(walker->visithash, data, NULL); + +} + +static void *islandboundWalker_yield(BMWalker *walker) +{ + islandboundWalker *iwalk = BMW_current_state(walker); + + return iwalk->curloop; +} + +static void *islandboundWalker_step(BMWalker *walker) +{ + islandboundWalker *iwalk = BMW_current_state(walker), owalk; + BMVert *v; + BMEdge *e = iwalk->curloop->e; + BMFace *f; + BMLoop *l = iwalk->curloop; + /* int found = 0; */ + + owalk = *iwalk; + + if (iwalk->lastv == e->v1) v = e->v2; + else v = e->v1; + + if (!BM_vert_is_manifold(walker->bm, v)) { + BMW_reset(walker); + BMO_error_raise(walker->bm, NULL, BMERR_WALKER_FAILED, + "Non-manifold vert " + "while searching region boundary"); + return NULL; + } + + /* pop off current stat */ + BMW_state_remove(walker); + + f = l->f; + + while (1) { + l = BM_face_other_loop(e, f, v); + if (bmesh_radial_nextloop(l) != l) { + l = bmesh_radial_nextloop(l); + f = l->f; + e = l->e; + if (walker->mask_face && !BMO_elem_flag_test(walker->bm, f, walker->mask_face)) { + l = l->radial_next; + break; + } + } + else { + f = l->f; + e = l->e; + break; + } + } + + if (l == owalk.curloop) { + return NULL; + } + else if (BLI_ghash_haskey(walker->visithash, l)) { + return owalk.curloop; + } + + BLI_ghash_insert(walker->visithash, l, NULL); + iwalk = BMW_state_add(walker); + iwalk->base = owalk.base; + + //if (!BMO_elem_flag_test(walker->bm, l->f, walker->restrictflag)) + // iwalk->curloop = l->radial_next; + iwalk->curloop = l; //else iwalk->curloop = l; + iwalk->lastv = v; + + return owalk.curloop; +} + + +/* Island Walker: + * + * Starts at a tool flagged-face and walks over the face region + * + * TODO: + * + * Add restriction flag/callback for wire edges. + * + */ + +static void islandWalker_begin(BMWalker *walker, void *data) +{ + islandWalker *iwalk = NULL; + + if (walker->mask_face && !BMO_elem_flag_test(walker->bm, (BMElemF *)data, walker->mask_face)) { + return; + } + + iwalk = BMW_state_add(walker); + BLI_ghash_insert(walker->visithash, data, NULL); + + iwalk->cur = data; +} + +static void *islandWalker_yield(BMWalker *walker) +{ + islandWalker *iwalk = BMW_current_state(walker); + + return iwalk->cur; +} + +static void *islandWalker_step(BMWalker *walker) +{ + islandWalker *iwalk = BMW_current_state(walker); + /* islandWalker *owalk = iwalk; */ /* UNUSED */ + BMIter iter, liter; + BMFace *f, *curf = iwalk->cur; + BMLoop *l; + + BMW_state_remove(walker); + + l = BM_iter_new(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur); + for ( ; l; l = BM_iter_step(&liter)) { + /* could skip loop here too, but dont add unless we need it */ + if (walker->mask_edge && !BMO_elem_flag_test(walker->bm, l->e, walker->mask_edge)) { + continue; + } + + f = BM_iter_new(&iter, walker->bm, BM_FACES_OF_EDGE, l->e); + for ( ; f; f = BM_iter_step(&iter)) { + if (walker->mask_face && !BMO_elem_flag_test(walker->bm, f, walker->mask_face)) { + continue; + } + if (BLI_ghash_haskey(walker->visithash, f)) continue; + + iwalk = BMW_state_add(walker); + iwalk->cur = f; + BLI_ghash_insert(walker->visithash, f, NULL); + break; + } + } + + return curf; +} + + +/* Edge Loop Walker: + * + * Starts at a tool-flagged edge and walks over the edge loop + * + */ + +static void loopWalker_begin(BMWalker *walker, void *data) +{ + loopWalker *lwalk = NULL, owalk; + BMEdge *e = data; + BMVert *v; + /* int found = 1, val; */ /* UNUSED */ + + v = e->v1; + + /* val = BM_vert_edge_count(v); */ /* UNUSED */ + + lwalk = BMW_state_add(walker); + BLI_ghash_insert(walker->visithash, e, NULL); + + lwalk->cur = lwalk->start = e; + lwalk->lastv = lwalk->startv = v; + lwalk->stage2 = 0; + lwalk->startrad = BM_edge_face_count(e); + + /* rewin */ + while (BMW_current_state(walker)) { + owalk = *((loopWalker *)BMW_current_state(walker)); + BMW_walk(walker); + } + + lwalk = BMW_state_add(walker); + *lwalk = owalk; + + if (lwalk->lastv == owalk.cur->v1) lwalk->lastv = owalk.cur->v2; + else lwalk->lastv = owalk.cur->v1; + + lwalk->startv = lwalk->lastv; + + BLI_ghash_free(walker->visithash, NULL, NULL); + walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 2"); + BLI_ghash_insert(walker->visithash, owalk.cur, NULL); +} + +static void *loopWalker_yield(BMWalker *walker) +{ + loopWalker *lwalk = BMW_current_state(walker); + + return lwalk->cur; +} + +static void *loopWalker_step(BMWalker *walker) +{ + loopWalker *lwalk = BMW_current_state(walker), owalk; + BMIter eiter; + BMEdge *e = lwalk->cur, *nexte = NULL; + BMLoop *l, *l2; + BMVert *v; + int val, rlen /* , found = 0 */, i = 0, stopi; + + owalk = *lwalk; + BMW_state_remove(walker); + + l = e->l; + + /* handle wire edge case */ + if (!l) { + + /* match trunk: mark all connected wire edges */ + for (i = 0; i < 2; i++) { + v = i ? e->v2 : e->v1; + + BM_ITER(nexte, &eiter, walker->bm, BM_EDGES_OF_VERT, v) { + if ((nexte->l == NULL) && !BLI_ghash_haskey(walker->visithash, nexte)) { + lwalk = BMW_state_add(walker); + lwalk->cur = nexte; + lwalk->lastv = v; + lwalk->startrad = owalk.startrad; + + BLI_ghash_insert(walker->visithash, nexte, NULL); + } + } + } + + return owalk.cur; + } + + v = (e->v1 == lwalk->lastv) ? e->v2 : e->v1; + + val = BM_vert_edge_count(v); + + rlen = owalk.startrad; + + if (val == 4 || val == 2 || rlen == 1) { + i = 0; + stopi = val / 2; + while (1) { + if (rlen != 1 && i == stopi) break; + + l = BM_face_other_loop(l->e, l->f, v); + + if (!l) + break; + + l2 = bmesh_radial_nextloop(l); + + if (l2 == l) { + break; + } + + l = l2; + i += 1; + } + } + + if (!l) { + return owalk.cur; + } + + if (l != e->l && !BLI_ghash_haskey(walker->visithash, l->e)) { + if (!(rlen != 1 && i != stopi)) { + lwalk = BMW_state_add(walker); + lwalk->cur = l->e; + lwalk->lastv = v; + lwalk->startrad = owalk.startrad; + BLI_ghash_insert(walker->visithash, l->e, NULL); + } + } + + return owalk.cur; +} + +/* Face Loop Walker: + * + * Starts at a tool-flagged face and walks over the face loop + * Conditions for starting and stepping the face loop have been + * tuned in an attempt to match the face loops built by EditMesh + * + */ + +/* Check whether the face loop should includes the face specified + * by the given BMLoop */ +static int faceloopWalker_include_face(BMWalker *walker, BMLoop *l) +{ + /* face must have degree 4 */ + if (l->f->len != 4) { + return FALSE; + } + + /* the face must not have been already visite */ + if (BLI_ghash_haskey(walker->visithash, l->f)) { + return FALSE; + } + + return TRUE; +} + +/* Check whether the face loop can start from the given edge */ +static int faceloopWalker_edge_begins_loop(BMWalker *walker, BMEdge *e) +{ + BMesh *bm = walker->bm; + + /* There is no face loop starting from a wire edge */ + if (BM_edge_is_wire(bm, e)) { + return FALSE; + } + + /* Don't start a loop from a boundary edge if it cannot + * be extended to cover any faces */ + if (BM_edge_face_count(e) == 1) { + if (!faceloopWalker_include_face(walker, e->l)) { + return FALSE; + } + } + + /* Don't start a face loop from non-manifold edges */ + if (!BM_edge_is_manifold(bm, e)) { + return FALSE; + } + + return TRUE; +} + +static void faceloopWalker_begin(BMWalker *walker, void *data) +{ + faceloopWalker *lwalk, owalk; + BMEdge *e = data; + /* BMesh *bm = walker->bm; */ /* UNUSED */ + /* int fcount = BM_edge_face_count(e); */ /* UNUSED */ + + if (!faceloopWalker_edge_begins_loop(walker, e)) + return; + + lwalk = BMW_state_add(walker); + lwalk->l = e->l; + lwalk->nocalc = 0; + BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL); + + /* rewin */ + while (BMW_current_state(walker)) { + owalk = *((faceloopWalker *)BMW_current_state(walker)); + BMW_walk(walker); + } + + lwalk = BMW_state_add(walker); + *lwalk = owalk; + lwalk->nocalc = 0; + + BLI_ghash_free(walker->visithash, NULL, NULL); + walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 3"); + BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL); +} + +static void *faceloopWalker_yield(BMWalker *walker) +{ + faceloopWalker *lwalk = BMW_current_state(walker); + + if (!lwalk) { + return NULL; + } + + return lwalk->l->f; +} + +static void *faceloopWalker_step(BMWalker *walker) +{ + faceloopWalker *lwalk = BMW_current_state(walker); + BMFace *f = lwalk->l->f; + BMLoop *l = lwalk->l, *origl = lwalk->l; + + BMW_state_remove(walker); + + l = l->radial_next; + + if (lwalk->nocalc) + return f; + + if (!faceloopWalker_include_face(walker, l)) { + l = lwalk->l; + l = l->next->next; + if (BM_edge_face_count(l->e) != 2) { + l = l->prev->prev; + } + l = l->radial_next; + } + + if (faceloopWalker_include_face(walker, l)) { + lwalk = BMW_state_add(walker); + lwalk->l = l; + + if (l->f->len != 4) { + lwalk->nocalc = 1; + lwalk->l = origl; + } + else { + lwalk->nocalc = 0; + } + + BLI_ghash_insert(walker->visithash, l->f, NULL); + } + + return f; +} + +/* Edge Ring Walker: + * + * Starts at a tool-flagged edge and walks over the edge ring + * Conditions for starting and stepping the edge ring have been + * tuned in an attempt to match the edge rings built by EditMesh + * + */ + +static void edgeringWalker_begin(BMWalker *walker, void *data) +{ + edgeringWalker *lwalk, owalk; + BMEdge *e = data; + + lwalk = BMW_state_add(walker); + lwalk->l = e->l; + + if (!lwalk->l) { + lwalk->wireedge = e; + return; + } + else { + lwalk->wireedge = NULL; + } + + BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL); + + /* rewin */ + while (BMW_current_state(walker)) { + owalk = *((edgeringWalker *)BMW_current_state(walker)); + BMW_walk(walker); + } + + lwalk = BMW_state_add(walker); + *lwalk = owalk; + + if (lwalk->l->f->len != 4) + lwalk->l = lwalk->l->radial_next; + + BLI_ghash_free(walker->visithash, NULL, NULL); + walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 4"); + BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL); +} + +static void *edgeringWalker_yield(BMWalker *walker) +{ + edgeringWalker *lwalk = BMW_current_state(walker); + + if (!lwalk) { + return NULL; + } + + if (lwalk->l) + return lwalk->l->e; + else + return lwalk->wireedge; +} + +static void *edgeringWalker_step(BMWalker *walker) +{ + edgeringWalker *lwalk = BMW_current_state(walker); + BMEdge *e; + BMLoop *l = lwalk->l /* , *origl = lwalk->l */; + BMesh *bm = walker->bm; + + BMW_state_remove(walker); + + if (!l) + return lwalk->wireedge; + + e = l->e; + if (!BM_edge_is_manifold(bm, e)) { + /* walker won't traverse to a non-manifold edge, but may + * be started on one, and should not traverse *away* from + * a non-manfold edge (non-manifold edges are never in an + * edge ring with manifold edges */ + return e; + } + + l = l->radial_next; + l = l->next->next; + + if ((l->f->len != 4) || !BM_edge_is_manifold(bm, l->e)) { + l = lwalk->l->next->next; + } + + /* only walk to manifold edge */ + if ((l->f->len == 4) && BM_edge_is_manifold(bm, l->e) && + !BLI_ghash_haskey(walker->visithash, l->e)) { + lwalk = BMW_state_add(walker); + lwalk->l = l; + lwalk->wireedge = NULL; + + BLI_ghash_insert(walker->visithash, l->e, NULL); + } + + return e; +} + +static void uvedgeWalker_begin(BMWalker *walker, void *data) +{ + uvedgeWalker *lwalk; + BMLoop *l = data; + + if (BLI_ghash_haskey(walker->visithash, l)) + return; + + lwalk = BMW_state_add(walker); + lwalk->l = l; + BLI_ghash_insert(walker->visithash, l, NULL); +} + +static void *uvedgeWalker_yield(BMWalker *walker) +{ + uvedgeWalker *lwalk = BMW_current_state(walker); + + if (!lwalk) { + return NULL; + } + + return lwalk->l; +} + +static void *uvedgeWalker_step(BMWalker *walker) +{ + uvedgeWalker *lwalk = BMW_current_state(walker); + BMLoop *l, *l2, *l3, *nl, *cl; + BMIter liter; + void *d1, *d2; + int i, j, rlen, type; + + l = lwalk->l; + nl = l->next; + type = walker->bm->ldata.layers[walker->layer].type; + + BMW_state_remove(walker); + + if (walker->mask_edge && !BMO_elem_flag_test(walker->bm, l->e, walker->mask_edge)) + return l; + + /* go over loops around l->v and nl->v and see which ones share l and nl's + * mloopuv's coordinates. in addition, push on l->next if necassary */ + for (i = 0; i < 2; i++) { + cl = i ? nl : l; + BM_ITER(l2, &liter, walker->bm, BM_LOOPS_OF_VERT, cl->v) { + d1 = CustomData_bmesh_get_layer_n(&walker->bm->ldata, + cl->head.data, walker->layer); + + rlen = BM_edge_face_count(l2->e); + for (j = 0; j < rlen; j++) { + if (BLI_ghash_haskey(walker->visithash, l2)) + continue; + if (walker->mask_edge && !(BMO_elem_flag_test(walker->bm, l2->e, walker->mask_edge))) { + if (l2->v != cl->v) + continue; + } + + l3 = l2->v != cl->v ? l2->next : l2; + d2 = CustomData_bmesh_get_layer_n(&walker->bm->ldata, + l3->head.data, walker->layer); + + if (!CustomData_data_equals(type, d1, d2)) + continue; + + lwalk = BMW_state_add(walker); + BLI_ghash_insert(walker->visithash, l2, NULL); + + lwalk->l = l2; + + l2 = l2->radial_next; + } + } + } + + return l; +} + +static BMWalker shell_walker_type = { + shellWalker_begin, + shellWalker_step, + shellWalker_yield, + sizeof(shellWalker), + BMW_BREADTH_FIRST, + BM_EDGE, /* valid restrict masks */ +}; + +static BMWalker islandbound_walker_type = { + islandboundWalker_begin, + islandboundWalker_step, + islandboundWalker_yield, + sizeof(islandboundWalker), + BMW_DEPTH_FIRST, + BM_FACE, /* valid restrict masks */ +}; + +static BMWalker island_walker_type = { + islandWalker_begin, + islandWalker_step, + islandWalker_yield, + sizeof(islandWalker), + BMW_BREADTH_FIRST, + BM_EDGE | BM_FACE, /* valid restrict masks */ +}; + +static BMWalker loop_walker_type = { + loopWalker_begin, + loopWalker_step, + loopWalker_yield, + sizeof(loopWalker), + BMW_DEPTH_FIRST, + 0, /* valid restrict masks */ /* could add flags here but so far none are used */ +}; + +static BMWalker faceloop_walker_type = { + faceloopWalker_begin, + faceloopWalker_step, + faceloopWalker_yield, + sizeof(faceloopWalker), + BMW_DEPTH_FIRST, + 0, /* valid restrict masks */ /* could add flags here but so far none are used */ +}; + +static BMWalker edgering_walker_type = { + edgeringWalker_begin, + edgeringWalker_step, + edgeringWalker_yield, + sizeof(edgeringWalker), + BMW_DEPTH_FIRST, + 0, /* valid restrict masks */ /* could add flags here but so far none are used */ +}; + +static BMWalker loopdata_region_walker_type = { + uvedgeWalker_begin, + uvedgeWalker_step, + uvedgeWalker_yield, + sizeof(uvedgeWalker), + BMW_DEPTH_FIRST, + BM_EDGE, /* valid restrict masks */ +}; + +static BMWalker connected_vertex_walker_type = { + connectedVertexWalker_begin, + connectedVertexWalker_step, + connectedVertexWalker_yield, + sizeof(connectedVertexWalker), + BMW_BREADTH_FIRST, + BM_VERT, /* valid restrict masks */ +}; + +BMWalker *bm_walker_types[] = { + &shell_walker_type, /* BMW_SHELL */ + &loop_walker_type, /* BMW_LOOP */ + &faceloop_walker_type, /* BMW_FACELOOP */ + &edgering_walker_type, /* BMW_EDGERING */ + &loopdata_region_walker_type, /* BMW_LOOPDATA_ISLAND */ + &islandbound_walker_type, /* BMW_ISLANDBOUND */ + &island_walker_type, /* BMW_ISLAND */ + &connected_vertex_walker_type, /* BMW_CONNECTED_VERTEX */ +}; + +int bm_totwalkers = sizeof(bm_walker_types) / sizeof(*bm_walker_types); |