undo of 40542 (meant to make two separate changes)
This commit is contained in:
@@ -181,7 +181,7 @@ struct BMFace *BM_Split_Face ( struct BMesh *bm, struct BMFace *f,
|
||||
struct BMLoop **nl, struct BMEdge *example );
|
||||
|
||||
/*dissolves a vert shared only by two edges*/
|
||||
BMEdge* BM_Collapse_Vert ( struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv,
|
||||
void BM_Collapse_Vert ( struct BMesh *bm, struct BMEdge *ke, struct BMVert *kv,
|
||||
float fac );
|
||||
|
||||
/*splits an edge. ne is set to the new edge created.*/
|
||||
|
||||
@@ -7,26 +7,19 @@
|
||||
NOTE: do NOT modify topology while walking a mesh!
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
BMW_DEPTH_FIRST,
|
||||
BMW_BREADTH_FIRST,
|
||||
} BMWOrder;
|
||||
|
||||
/*Walkers*/
|
||||
typedef struct BMWalker {
|
||||
void (*begin) (struct BMWalker *walker, void *start);
|
||||
void *(*step) (struct BMWalker *walker);
|
||||
void *(*yield)(struct BMWalker *walker);
|
||||
int structsize;
|
||||
BMWOrder order;
|
||||
int flag;
|
||||
|
||||
BMesh *bm;
|
||||
BLI_mempool *worklist;
|
||||
ListBase states;
|
||||
BLI_mempool *stack;
|
||||
void *currentstate;
|
||||
int restrictflag;
|
||||
GHash *visithash;
|
||||
int depth;
|
||||
} BMWalker;
|
||||
|
||||
/*initialize a walker. searchmask restricts some (not all) walkers to
|
||||
@@ -35,12 +28,10 @@ void BMW_Init(struct BMWalker *walker, BMesh *bm, int type, int searchmask, int
|
||||
void *BMW_Begin(BMWalker *walker, void *start);
|
||||
void *BMW_Step(struct BMWalker *walker);
|
||||
void BMW_End(struct BMWalker *walker);
|
||||
int BMW_CurrentDepth(BMWalker *walker);
|
||||
|
||||
/*these are used by custom walkers*/
|
||||
void *BMW_currentstate(BMWalker *walker);
|
||||
void *BMW_addstate(BMWalker *walker);
|
||||
void BMW_removestate(BMWalker *walker);
|
||||
void BMW_pushstate(BMWalker *walker);
|
||||
void BMW_popstate(BMWalker *walker);
|
||||
void *BMW_walk(BMWalker *walker);
|
||||
void BMW_reset(BMWalker *walker);
|
||||
|
||||
@@ -84,8 +75,6 @@ enum {
|
||||
BMW_ISLANDBOUND,
|
||||
/*walk over all faces in an island of tool flagged faces.*/
|
||||
BMW_ISLAND,
|
||||
/*walk from a vertex to all connected vertices.*/
|
||||
BMW_CONNECTED_VERTEX,
|
||||
/*do not intitialze function pointers and struct size in BMW_Init*/
|
||||
BMW_CUSTOM,
|
||||
BMW_MAXWALKERS
|
||||
|
||||
@@ -59,7 +59,6 @@ void BME_error(void);
|
||||
/*bmesh_error stub*/
|
||||
void bmesh_error(void)
|
||||
{
|
||||
BLI_assert(0);
|
||||
printf("BM modelling error!");
|
||||
}
|
||||
|
||||
|
||||
@@ -110,21 +110,15 @@ int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
|
||||
if (!BM_Split_Face(bm, loop->f, v, loop->v, NULL, NULL))
|
||||
return 0;
|
||||
|
||||
if (!BM_Dissolve_Disk(bm, v)) {
|
||||
return 0;
|
||||
}
|
||||
BM_Dissolve_Disk(bm, v);
|
||||
return 1;
|
||||
} else if (keepedge == NULL && len == 2) {
|
||||
/*collapse the vertex*/
|
||||
e = BM_Collapse_Vert(bm, v->e, v, 1.0);
|
||||
|
||||
if (!e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*handle two-valence*/
|
||||
f = e->l->f;
|
||||
f = e->l->radial_next->f;
|
||||
f = v->e->l->f;
|
||||
f2 = v->e->l->radial_next->f;
|
||||
|
||||
/*collapse the vertex*/
|
||||
BM_Collapse_Vert(bm, v->e, v, 1.0);
|
||||
|
||||
if (f != f2 && !BM_Join_TwoFaces(bm, f, f2, NULL))
|
||||
return 0;
|
||||
@@ -156,22 +150,16 @@ int BM_Dissolve_Disk(BMesh *bm, BMVert *v) {
|
||||
}while(e != v->e);
|
||||
}
|
||||
|
||||
/*collapse the vertex*/
|
||||
e = BM_Collapse_Vert(bm, baseedge, v, 1.0);
|
||||
|
||||
if (!e) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*get remaining two faces*/
|
||||
f = e->l->f;
|
||||
f2 = e->l->radial_next->f;
|
||||
f = v->e->l->f;
|
||||
f2 = v->e->l->radial_next->f;
|
||||
|
||||
/*collapse the vertex*/
|
||||
BM_Collapse_Vert(bm, baseedge, v, 1.0);
|
||||
|
||||
if (f != f2) {
|
||||
/*join two remaining faces*/
|
||||
if (!BM_Join_TwoFaces(bm, f, f2, NULL)) {
|
||||
return 0;
|
||||
}
|
||||
if (!BM_Join_TwoFaces(bm, f, f2, NULL)) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,21 +199,16 @@ void BM_Dissolve_Disk(BMesh *bm, BMVert *v){
|
||||
#endif
|
||||
|
||||
/**
|
||||
* BM_Join_TwoFaces
|
||||
* bmesh_join_faces
|
||||
*
|
||||
* Joins two adjacenct faces togather.
|
||||
* joins two adjacenct faces togather.
|
||||
*
|
||||
* Because this method calls to BM_Join_Faces to do its work, ff a pair
|
||||
* of faces share multiple edges, the pair of faces will be joined at
|
||||
* every edge (not just edge e). This part of the functionality might need
|
||||
* to be reconsidered.
|
||||
*
|
||||
* Returns:
|
||||
* pointer to the combined face
|
||||
* Returns -
|
||||
* BMFace pointer
|
||||
*/
|
||||
|
||||
BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
|
||||
{
|
||||
BMFace *BM_Join_TwoFaces(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) {
|
||||
|
||||
BMLoop *l1, *l2;
|
||||
BMEdge *jed=NULL;
|
||||
BMFace *faces[2] = {f1, f2};
|
||||
@@ -296,21 +279,12 @@ BMEdge *BM_Connect_Verts(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
|
||||
}
|
||||
|
||||
/**
|
||||
* BM_Split_Face
|
||||
* BM_split_face
|
||||
*
|
||||
* Splits a single face into two.
|
||||
*
|
||||
* f - the original face
|
||||
* v1 & v2 - vertices which define the split edge, must be different
|
||||
* nl - pointer which will receive the BMLoop for the split edge in the new face
|
||||
*
|
||||
* Notes: the
|
||||
|
||||
*
|
||||
* Returns -
|
||||
* Pointer to the newly created face representing one side of the split
|
||||
* if the split is successful (and the original original face will be the
|
||||
* other side). NULL if the split fails.
|
||||
*
|
||||
* BMFace pointer
|
||||
*/
|
||||
|
||||
BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl, BMEdge *UNUSED(example))
|
||||
@@ -370,19 +344,15 @@ BMFace *BM_Split_Face(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **nl,
|
||||
* Nothing
|
||||
*/
|
||||
|
||||
BMEdge* BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
|
||||
void BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
|
||||
BMFace **faces = NULL, *f;
|
||||
BLI_array_staticdeclare(faces, 8);
|
||||
BMIter iter;
|
||||
BMLoop *l=NULL, *kvloop=NULL, *tvloop=NULL;
|
||||
BMEdge *ne = NULL;
|
||||
BMVert *tv = bmesh_edge_getothervert(ke,kv);
|
||||
void *src[2];
|
||||
float w[2];
|
||||
|
||||
/* Only intended to be called for 2-valence vertices */
|
||||
BLI_assert(bmesh_disk_count(kv) <= 2);
|
||||
|
||||
w[0] = 1.0f - fac;
|
||||
w[1] = fac;
|
||||
|
||||
@@ -413,16 +383,13 @@ BMEdge* BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
|
||||
BMEdge *e2;
|
||||
BMVert *tv2;
|
||||
|
||||
/*ok, no faces, means we have a wire edge*/
|
||||
e2 = bmesh_disk_nextedge(ke, kv);
|
||||
tv2 = BM_OtherEdgeVert(e2, kv);
|
||||
|
||||
f2 = BM_Join_Faces(bm, faces, BLI_array_count(faces));
|
||||
if (f2) {
|
||||
BMLoop *nl = NULL;
|
||||
if (BM_Split_Face(bm, f2, tv, tv2, &nl, NULL)) {
|
||||
ne = nl->e;
|
||||
}
|
||||
}
|
||||
if (f2)
|
||||
BM_Split_Face(bm, f2, tv, tv2, NULL, NULL);
|
||||
} else if (faces && BLI_array_count(faces) == 1) {
|
||||
BMLoop **loops = NULL;
|
||||
BMEdge *e;
|
||||
@@ -446,19 +413,14 @@ BMEdge* BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
|
||||
BLI_array_append(edges, l->e);
|
||||
} else {
|
||||
BMVert *v2;
|
||||
|
||||
/* Create a single edge to replace the two edges incident on kv */
|
||||
|
||||
if (BM_Vert_In_Edge(l->next->e, kv))
|
||||
v2 = BM_OtherEdgeVert(l->next->e, kv);
|
||||
else
|
||||
v2 = BM_OtherEdgeVert(l->prev->e, kv);
|
||||
|
||||
/* Only one new edge should be created */
|
||||
BLI_assert(ne == NULL);
|
||||
|
||||
ne = BM_Make_Edge(bm, BM_OtherEdgeVert(l->e, kv), v2, l->e, 1);
|
||||
BLI_array_append(edges, ne);
|
||||
|
||||
e = BM_Make_Edge(bm, BM_OtherEdgeVert(l->e, kv), v2, l->e, 1);
|
||||
BLI_array_append(edges, e);
|
||||
}
|
||||
|
||||
BLI_array_append(loops, l);
|
||||
@@ -497,8 +459,6 @@ BMEdge* BM_Collapse_Vert(BMesh *bm, BMEdge *ke, BMVert *kv, float fac){
|
||||
}
|
||||
|
||||
BLI_array_free(faces);
|
||||
|
||||
return ne;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -702,17 +702,8 @@ static int disk_is_flagged(BMVert *v, int flag)
|
||||
|
||||
/* Midlevel Topology Manipulation Functions */
|
||||
|
||||
/*
|
||||
* BM_Join_Faces
|
||||
*
|
||||
* Joins a collected group of faces into one. Only restriction on
|
||||
* the input data is that the faces must be connected to each other.
|
||||
*
|
||||
* If a pair of faces share multiple edges, the pair of
|
||||
* faces will be joined at every edge.
|
||||
*
|
||||
* Returns a pointer to the combined face.
|
||||
*/
|
||||
/*joins a collected group of faces into one. only restriction on
|
||||
the input data is that the faces must be connected to each other.*/
|
||||
BMFace *BM_Join_Faces(BMesh *bm, BMFace **faces, int totface)
|
||||
{
|
||||
BMFace *f, *newf;
|
||||
@@ -911,7 +902,7 @@ static BMFace *bmesh_addpolylist(BMesh *bm, BMFace *UNUSED(example)) {
|
||||
*
|
||||
* Before: After:
|
||||
* ---------- ----------
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | | | f1 |
|
||||
* v1 f1 v2 v1======v2
|
||||
* | | | f2 |
|
||||
@@ -1349,7 +1340,7 @@ int bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv)
|
||||
*
|
||||
* A B
|
||||
* ---------- ----------
|
||||
* | | | |
|
||||
* | | | |
|
||||
* | f1 | | f1 |
|
||||
* v1========v2 = Ok! v1==V2==v3 == Wrong!
|
||||
* | f2 | | f2 |
|
||||
|
||||
@@ -51,14 +51,14 @@
|
||||
design notes:
|
||||
|
||||
original desing: walkers directly emulation recursive functions.
|
||||
functions save their state onto a worklist, and also add new states
|
||||
functions save their state onto a stack, and also push new states
|
||||
to implement recursive or looping behaviour. generally only one
|
||||
state push per call with a specific state is desired.
|
||||
|
||||
basic design pattern: the walker step function goes through it's
|
||||
list of possible choices for recursion, and recurses (by pushing a new state)
|
||||
using the first non-visited one. this choise is the flagged as visited using
|
||||
the ghash. each step may push multiple new states onto the worklist at once.
|
||||
the ghash. each step may push multiple new states onto the stack at once.
|
||||
|
||||
* walkers use tool flags, not header flags
|
||||
* walkers now use ghash for storing visited elements,
|
||||
@@ -68,10 +68,17 @@
|
||||
for if walkers fail.
|
||||
*/
|
||||
|
||||
|
||||
/* Pointer hiding*/
|
||||
typedef struct bmesh_walkerGeneric{
|
||||
struct bmesh_walkerGeneric *prev;
|
||||
} bmesh_walkerGeneric;
|
||||
|
||||
|
||||
void *BMW_Begin(BMWalker *walker, void *start) {
|
||||
walker->begin(walker, start);
|
||||
|
||||
return BMW_currentstate(walker) ? walker->step(walker) : NULL;
|
||||
return walker->currentstate ? walker->step(walker) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -102,23 +109,22 @@ void BMW_Init(BMWalker *walker, BMesh *bm, int type, int searchmask, int flag)
|
||||
walker->yield = bm_walker_types[type]->yield;
|
||||
walker->step = bm_walker_types[type]->step;
|
||||
walker->structsize = bm_walker_types[type]->structsize;
|
||||
walker->order = bm_walker_types[type]->order;
|
||||
}
|
||||
|
||||
walker->worklist = BLI_mempool_create(walker->structsize, 100, 100, 1, 0);
|
||||
walker->states.first = walker->states.last = NULL;
|
||||
walker->stack = BLI_mempool_create(walker->structsize, 100, 100, 1, 0);
|
||||
walker->currentstate = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_End
|
||||
*
|
||||
* Frees a walker's worklist.
|
||||
* Frees a walker's stack.
|
||||
*
|
||||
*/
|
||||
|
||||
void BMW_End(BMWalker *walker)
|
||||
{
|
||||
BLI_mempool_destroy(walker->worklist);
|
||||
BLI_mempool_destroy(walker->stack);
|
||||
BLI_ghash_free(walker->visithash, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -137,18 +143,6 @@ void *BMW_Step(BMWalker *walker)
|
||||
return head;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_CurrentDepth
|
||||
*
|
||||
* Returns the current depth of the walker.
|
||||
*
|
||||
*/
|
||||
|
||||
int BMW_CurrentDepth(BMWalker *walker)
|
||||
{
|
||||
return walker->depth;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_WALK
|
||||
*
|
||||
@@ -163,7 +157,7 @@ void *BMW_walk(BMWalker *walker)
|
||||
{
|
||||
void *current = NULL;
|
||||
|
||||
while(BMW_currentstate(walker)){
|
||||
while(walker->currentstate){
|
||||
current = walker->step(walker);
|
||||
if(current) return current;
|
||||
}
|
||||
@@ -171,93 +165,40 @@ void *BMW_walk(BMWalker *walker)
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_currentstate
|
||||
* BMW_popstate
|
||||
*
|
||||
* Returns the first state from the walker state
|
||||
* worklist. This state is the the next in the
|
||||
* worklist for processing.
|
||||
* Pops the current walker state off the stack
|
||||
* and makes the previous state current
|
||||
*
|
||||
*/
|
||||
|
||||
void* BMW_currentstate(BMWalker *walker)
|
||||
{
|
||||
bmesh_walkerGeneric *currentstate = walker->states.first;
|
||||
if (currentstate) {
|
||||
/* Automatic update of depth. For most walkers that
|
||||
follow the standard "Step" pattern of:
|
||||
- read current state
|
||||
- remove current state
|
||||
- push new states
|
||||
- return walk result from just-removed current state
|
||||
this simple automatic update should keep track of depth
|
||||
just fine. Walkers that deviate from that pattern may
|
||||
need to manually update the depth if they care about
|
||||
keeping it correct. */
|
||||
walker->depth = currentstate->depth + 1;
|
||||
}
|
||||
return currentstate;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_removestate
|
||||
*
|
||||
* Remove and free an item from the end of the walker state
|
||||
* worklist.
|
||||
*
|
||||
*/
|
||||
|
||||
void BMW_removestate(BMWalker *walker)
|
||||
void BMW_popstate(BMWalker *walker)
|
||||
{
|
||||
void *oldstate;
|
||||
oldstate = BMW_currentstate(walker);
|
||||
BLI_remlink(&walker->states, oldstate);
|
||||
BLI_mempool_free(walker->worklist, oldstate);
|
||||
oldstate = walker->currentstate;
|
||||
walker->currentstate
|
||||
= ((bmesh_walkerGeneric*)walker->currentstate)->prev;
|
||||
BLI_mempool_free(walker->stack, oldstate);
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_newstate
|
||||
* BMW_pushstate
|
||||
*
|
||||
* Allocate a new empty state and put it on the worklist.
|
||||
* A pointer to the new state is returned so that the caller
|
||||
* can fill in the state data. The new state will be inserted
|
||||
* at the front for depth-first walks, and at the end for
|
||||
* breadth-first walks.
|
||||
* Pushes the current state down the stack and allocates
|
||||
* a new one.
|
||||
*
|
||||
*/
|
||||
|
||||
void* BMW_addstate(BMWalker *walker)
|
||||
void BMW_pushstate(BMWalker *walker)
|
||||
{
|
||||
bmesh_walkerGeneric *newstate;
|
||||
newstate = BLI_mempool_alloc(walker->worklist);
|
||||
newstate->depth = walker->depth;
|
||||
switch (walker->order)
|
||||
{
|
||||
case BMW_DEPTH_FIRST:
|
||||
BLI_addhead(&walker->states, newstate);
|
||||
break;
|
||||
case BMW_BREADTH_FIRST:
|
||||
BLI_addtail(&walker->states, newstate);
|
||||
break;
|
||||
default:
|
||||
BLI_assert(0);
|
||||
break;
|
||||
}
|
||||
return newstate;
|
||||
newstate = BLI_mempool_alloc(walker->stack);
|
||||
newstate->prev = walker->currentstate;
|
||||
walker->currentstate = newstate;
|
||||
}
|
||||
|
||||
/*
|
||||
* BMW_reset
|
||||
*
|
||||
* Frees all states from the worklist, resetting the walker
|
||||
* for reuse in a new walk.
|
||||
*
|
||||
*/
|
||||
|
||||
void BMW_reset(BMWalker *walker) {
|
||||
while (BMW_currentstate(walker)) {
|
||||
BMW_removestate(walker);
|
||||
while (walker->currentstate) {
|
||||
BMW_popstate(walker);
|
||||
}
|
||||
walker->depth = 0;
|
||||
BLI_ghash_free(walker->visithash, NULL, NULL);
|
||||
walker->visithash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "bmesh walkers 1");
|
||||
}
|
||||
|
||||
@@ -57,77 +57,68 @@
|
||||
*
|
||||
*/
|
||||
|
||||
static void shellWalker_visitEdge(BMWalker *walker, BMEdge *e) {
|
||||
static void shellWalker_begin(BMWalker *walker, void *data){
|
||||
BMIter eiter;
|
||||
BMEdge *e;
|
||||
BMVert *v = data;
|
||||
shellWalker *shellWalk = NULL;
|
||||
|
||||
if (BLI_ghash_haskey(walker->visithash, e)) {
|
||||
if (!v->e)
|
||||
return;
|
||||
|
||||
if (walker->restrictflag) {
|
||||
BM_ITER(e, &eiter, walker->bm, BM_EDGES_OF_VERT, v) {
|
||||
if (BMO_TestFlag(walker->bm, e, walker->restrictflag))
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
e = v->e;
|
||||
}
|
||||
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, e, walker->restrictflag)) {
|
||||
if (!e)
|
||||
return;
|
||||
}
|
||||
|
||||
shellWalk = BMW_addstate(walker);
|
||||
if (BLI_ghash_haskey(walker->visithash, e))
|
||||
return;
|
||||
|
||||
BMW_pushstate(walker);
|
||||
|
||||
shellWalk = walker->currentstate;
|
||||
shellWalk->base = v;
|
||||
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->type) {
|
||||
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_currentstate(walker);
|
||||
shellWalker *shellWalk = walker->currentstate;
|
||||
return shellWalk->curedge;
|
||||
}
|
||||
|
||||
static void *shellWalker_step(BMWalker *walker)
|
||||
{
|
||||
shellWalker *swalk = BMW_currentstate(walker);
|
||||
shellWalker *swalk = walker->currentstate;
|
||||
BMEdge *e, *e2;
|
||||
BMVert *v;
|
||||
BMIter iter;
|
||||
int i;
|
||||
|
||||
e = swalk->curedge;
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
e = swalk->curedge;
|
||||
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);
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, e2, walker->restrictflag))
|
||||
continue;
|
||||
if (BLI_ghash_haskey(walker->visithash, e2))
|
||||
continue;
|
||||
|
||||
BMW_pushstate(walker);
|
||||
BLI_ghash_insert(walker->visithash, e2, NULL);
|
||||
|
||||
swalk = walker->currentstate;
|
||||
swalk->curedge = e2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,12 +131,12 @@ static void *shellWalker_step(BMWalker *walker)
|
||||
BMEdge *curedge, *next = NULL;
|
||||
BMVert *ov = NULL;
|
||||
int restrictpass = 1;
|
||||
shellWalker shellWalk = *((shellWalker*)BMW_currentstate(walker));
|
||||
shellWalker shellWalk = *((shellWalker*)walker->currentstate);
|
||||
|
||||
if (!BLI_ghash_haskey(walker->visithash, shellWalk.base))
|
||||
BLI_ghash_insert(walker->visithash, shellWalk.base, NULL);
|
||||
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
|
||||
/*find the next edge whose other vertex has not been visited*/
|
||||
@@ -155,18 +146,16 @@ static void *shellWalker_step(BMWalker *walker)
|
||||
if(!walker->restrictflag || (walker->restrictflag &&
|
||||
BMO_TestFlag(walker->bm, curedge, walker->restrictflag)))
|
||||
{
|
||||
shellWalker *newstate;
|
||||
|
||||
ov = BM_OtherEdgeVert(curedge, shellWalk.base);
|
||||
|
||||
/*push a new state onto the stack*/
|
||||
newState = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
BLI_ghash_insert(walker->visithash, curedge, NULL);
|
||||
|
||||
/*populate the new state*/
|
||||
|
||||
newState->base = ov;
|
||||
newState->curedge = curedge;
|
||||
((shellWalker*)walker->currentstate)->base = ov;
|
||||
((shellWalker*)walker->currentstate)->curedge = curedge;
|
||||
}
|
||||
}
|
||||
curedge = bmesh_disk_nextedge(curedge, shellWalk.base);
|
||||
@@ -176,63 +165,6 @@ static void *shellWalker_step(BMWalker *walker)
|
||||
}
|
||||
#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->restrictflag && !BMO_TestFlag(walker->bm, v, walker->restrictflag)) {
|
||||
/* not flagged for walk */
|
||||
return;
|
||||
}
|
||||
|
||||
vwalk = BMW_addstate(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_currentstate(walker);
|
||||
return vwalk->curvert;
|
||||
}
|
||||
|
||||
static void *connectedVertexWalker_step(BMWalker *walker)
|
||||
{
|
||||
connectedVertexWalker *vwalk = BMW_currentstate(walker);
|
||||
BMVert *v, *v2;
|
||||
BMEdge *e;
|
||||
BMIter iter;
|
||||
|
||||
v = vwalk->curvert;
|
||||
|
||||
BMW_removestate(walker);
|
||||
|
||||
BM_ITER(e, &iter, walker->bm, BM_EDGES_OF_VERT, v) {
|
||||
v2 = BM_OtherEdgeVert(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
|
||||
@@ -248,7 +180,9 @@ static void islandboundWalker_begin(BMWalker *walker, void *data){
|
||||
BMLoop *l = data;
|
||||
islandboundWalker *iwalk = NULL;
|
||||
|
||||
iwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
|
||||
iwalk = walker->currentstate;
|
||||
|
||||
iwalk->base = iwalk->curloop = l;
|
||||
iwalk->lastv = l->v;
|
||||
@@ -259,14 +193,14 @@ static void islandboundWalker_begin(BMWalker *walker, void *data){
|
||||
|
||||
static void *islandboundWalker_yield(BMWalker *walker)
|
||||
{
|
||||
islandboundWalker *iwalk = BMW_currentstate(walker);
|
||||
islandboundWalker *iwalk = walker->currentstate;
|
||||
|
||||
return iwalk->curloop;
|
||||
}
|
||||
|
||||
static void *islandboundWalker_step(BMWalker *walker)
|
||||
{
|
||||
islandboundWalker *iwalk = BMW_currentstate(walker), owalk;
|
||||
islandboundWalker *iwalk = walker->currentstate, owalk;
|
||||
BMVert *v;
|
||||
BMEdge *e = iwalk->curloop->e;
|
||||
BMFace *f;
|
||||
@@ -287,7 +221,7 @@ static void *islandboundWalker_step(BMWalker *walker)
|
||||
}
|
||||
|
||||
/*pop off current state*/
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
f = l->f;
|
||||
|
||||
@@ -312,7 +246,8 @@ static void *islandboundWalker_step(BMWalker *walker)
|
||||
if (BLI_ghash_haskey(walker->visithash, l)) return owalk.curloop;
|
||||
|
||||
BLI_ghash_insert(walker->visithash, l, NULL);
|
||||
iwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
iwalk = walker->currentstate;
|
||||
iwalk->base = owalk.base;
|
||||
|
||||
//if (!BMO_TestFlag(walker->bm, l->f, walker->restrictflag))
|
||||
@@ -337,11 +272,9 @@ static void *islandboundWalker_step(BMWalker *walker)
|
||||
static void islandWalker_begin(BMWalker *walker, void *data){
|
||||
islandWalker *iwalk = NULL;
|
||||
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, data, walker->restrictflag)) {
|
||||
return;
|
||||
}
|
||||
BMW_pushstate(walker);
|
||||
|
||||
iwalk = BMW_addstate(walker);
|
||||
iwalk = walker->currentstate;
|
||||
BLI_ghash_insert(walker->visithash, data, NULL);
|
||||
|
||||
iwalk->cur = data;
|
||||
@@ -349,31 +282,31 @@ static void islandWalker_begin(BMWalker *walker, void *data){
|
||||
|
||||
static void *islandWalker_yield(BMWalker *walker)
|
||||
{
|
||||
islandWalker *iwalk = BMW_currentstate(walker);
|
||||
islandWalker *iwalk = walker->currentstate;
|
||||
|
||||
return iwalk->cur;
|
||||
}
|
||||
|
||||
static void *islandWalker_step(BMWalker *walker)
|
||||
{
|
||||
islandWalker *iwalk = BMW_currentstate(walker), *owalk;
|
||||
islandWalker *iwalk = walker->currentstate, *owalk;
|
||||
BMIter iter, liter;
|
||||
BMFace *f, *curf = iwalk->cur;
|
||||
BMLoop *l;
|
||||
owalk = iwalk;
|
||||
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
l = BMIter_New(&liter, walker->bm, BM_LOOPS_OF_FACE, iwalk->cur);
|
||||
for (; l; l=BMIter_Step(&liter)) {
|
||||
f = BMIter_New(&iter, walker->bm, BM_FACES_OF_EDGE, l->e);
|
||||
for (; f; f=BMIter_Step(&iter)) {
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag)) {
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, f, walker->restrictflag))
|
||||
continue;
|
||||
}
|
||||
if (BLI_ghash_haskey(walker->visithash, f)) continue;
|
||||
|
||||
iwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
iwalk = walker->currentstate;
|
||||
iwalk->cur = f;
|
||||
BLI_ghash_insert(walker->visithash, f, NULL);
|
||||
break;
|
||||
@@ -400,7 +333,9 @@ static void loopWalker_begin(BMWalker *walker, void *data){
|
||||
|
||||
/* val = BM_Vert_EdgeCount(v); */ /* UNUSED */
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
|
||||
lwalk = walker->currentstate;
|
||||
BLI_ghash_insert(walker->visithash, e, NULL);
|
||||
|
||||
lwalk->cur = lwalk->start = e;
|
||||
@@ -409,12 +344,13 @@ static void loopWalker_begin(BMWalker *walker, void *data){
|
||||
lwalk->startrad = BM_Edge_FaceCount(e);
|
||||
|
||||
/*rewind*/
|
||||
while (BMW_currentstate(walker)) {
|
||||
owalk = *((loopWalker*)BMW_currentstate(walker));
|
||||
while (walker->currentstate) {
|
||||
owalk = *((loopWalker*)walker->currentstate);
|
||||
BMW_walk(walker);
|
||||
}
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
*lwalk = owalk;
|
||||
|
||||
if (lwalk->lastv == owalk.cur->v1) lwalk->lastv = owalk.cur->v2;
|
||||
@@ -429,14 +365,14 @@ static void loopWalker_begin(BMWalker *walker, void *data){
|
||||
|
||||
static void *loopWalker_yield(BMWalker *walker)
|
||||
{
|
||||
loopWalker *lwalk = BMW_currentstate(walker);
|
||||
loopWalker *lwalk = walker->currentstate;
|
||||
|
||||
return lwalk->cur;
|
||||
}
|
||||
|
||||
static void *loopWalker_step(BMWalker *walker)
|
||||
{
|
||||
loopWalker *lwalk = BMW_currentstate(walker), owalk;
|
||||
loopWalker *lwalk = walker->currentstate, owalk;
|
||||
BMEdge *e = lwalk->cur /* , *nexte = NULL */;
|
||||
BMLoop *l, *l2;
|
||||
BMVert *v;
|
||||
@@ -449,7 +385,7 @@ static void *loopWalker_step(BMWalker *walker)
|
||||
|
||||
val = BM_Vert_EdgeCount(v);
|
||||
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
rlen = owalk.startrad;
|
||||
l = e->l;
|
||||
@@ -459,7 +395,8 @@ static void *loopWalker_step(BMWalker *walker)
|
||||
e = bmesh_disk_nextedge(e, v);
|
||||
|
||||
if (!BLI_ghash_haskey(walker->visithash, e)) {
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
*lwalk = owalk;
|
||||
lwalk->cur = e;
|
||||
lwalk->lastv = v;
|
||||
@@ -497,7 +434,8 @@ static void *loopWalker_step(BMWalker *walker)
|
||||
|
||||
if (l != e->l && !BLI_ghash_haskey(walker->visithash, l->e)) {
|
||||
if (!(rlen != 1 && i != stopi)) {
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
*lwalk = owalk;
|
||||
lwalk->cur = l->e;
|
||||
lwalk->lastv = v;
|
||||
@@ -566,18 +504,21 @@ static void faceloopWalker_begin(BMWalker *walker, void *data)
|
||||
if (!faceloopWalker_edge_begins_loop(walker, e))
|
||||
return;
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
|
||||
lwalk = walker->currentstate;
|
||||
lwalk->l = e->l;
|
||||
lwalk->nocalc = 0;
|
||||
BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL);
|
||||
|
||||
/*rewind*/
|
||||
while (BMW_currentstate(walker)) {
|
||||
owalk = *((faceloopWalker*)BMW_currentstate(walker));
|
||||
while (walker->currentstate) {
|
||||
owalk = *((faceloopWalker*)walker->currentstate);
|
||||
BMW_walk(walker);
|
||||
}
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
*lwalk = owalk;
|
||||
lwalk->nocalc = 0;
|
||||
|
||||
@@ -588,7 +529,7 @@ static void faceloopWalker_begin(BMWalker *walker, void *data)
|
||||
|
||||
static void *faceloopWalker_yield(BMWalker *walker)
|
||||
{
|
||||
faceloopWalker *lwalk = BMW_currentstate(walker);
|
||||
faceloopWalker *lwalk = walker->currentstate;
|
||||
|
||||
if (!lwalk) return NULL;
|
||||
|
||||
@@ -597,11 +538,11 @@ static void *faceloopWalker_yield(BMWalker *walker)
|
||||
|
||||
static void *faceloopWalker_step(BMWalker *walker)
|
||||
{
|
||||
faceloopWalker *lwalk = BMW_currentstate(walker);
|
||||
faceloopWalker *lwalk = walker->currentstate;
|
||||
BMFace *f = lwalk->l->f;
|
||||
BMLoop *l = lwalk->l, *origl = lwalk->l;
|
||||
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
l = l->radial_next;
|
||||
|
||||
@@ -618,7 +559,8 @@ static void *faceloopWalker_step(BMWalker *walker)
|
||||
}
|
||||
|
||||
if (faceloopWalker_include_face(walker, l)) {
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
lwalk->l = l;
|
||||
|
||||
if (l->f->len != 4) {
|
||||
@@ -646,7 +588,9 @@ static void edgeringWalker_begin(BMWalker *walker, void *data)
|
||||
edgeringWalker *lwalk, owalk;
|
||||
BMEdge *e = data;
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
|
||||
lwalk = walker->currentstate;
|
||||
lwalk->l = e->l;
|
||||
|
||||
if (!lwalk->l) {
|
||||
@@ -659,12 +603,13 @@ static void edgeringWalker_begin(BMWalker *walker, void *data)
|
||||
BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL);
|
||||
|
||||
/*rewind*/
|
||||
while (BMW_currentstate(walker)) {
|
||||
owalk = *((edgeringWalker*)BMW_currentstate(walker));
|
||||
while (walker->currentstate) {
|
||||
owalk = *((edgeringWalker*)walker->currentstate);
|
||||
BMW_walk(walker);
|
||||
}
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
*lwalk = owalk;
|
||||
|
||||
if (lwalk->l->f->len != 4)
|
||||
@@ -677,7 +622,7 @@ static void edgeringWalker_begin(BMWalker *walker, void *data)
|
||||
|
||||
static void *edgeringWalker_yield(BMWalker *walker)
|
||||
{
|
||||
edgeringWalker *lwalk = BMW_currentstate(walker);
|
||||
edgeringWalker *lwalk = walker->currentstate;
|
||||
|
||||
if (!lwalk) return NULL;
|
||||
|
||||
@@ -689,12 +634,12 @@ static void *edgeringWalker_yield(BMWalker *walker)
|
||||
|
||||
static void *edgeringWalker_step(BMWalker *walker)
|
||||
{
|
||||
edgeringWalker *lwalk = BMW_currentstate(walker);
|
||||
edgeringWalker *lwalk = walker->currentstate;
|
||||
BMEdge *e;
|
||||
BMLoop *l = lwalk->l /* , *origl = lwalk->l */;
|
||||
BMesh *bm = walker->bm;
|
||||
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
if (!l)
|
||||
return lwalk->wireedge;
|
||||
@@ -718,7 +663,8 @@ static void *edgeringWalker_step(BMWalker *walker)
|
||||
/*only walk to manifold edges*/
|
||||
if ((l->f->len == 4) && !BM_Nonmanifold_Edge(bm, l->e) &&
|
||||
!BLI_ghash_haskey(walker->visithash, l->e)) {
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
lwalk->l = l;
|
||||
lwalk->wireedge = NULL;
|
||||
|
||||
@@ -736,14 +682,15 @@ static void uvedgeWalker_begin(BMWalker *walker, void *data)
|
||||
if (BLI_ghash_haskey(walker->visithash, l))
|
||||
return;
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
lwalk = walker->currentstate;
|
||||
lwalk->l = l;
|
||||
BLI_ghash_insert(walker->visithash, l, NULL);
|
||||
}
|
||||
|
||||
static void *uvedgeWalker_yield(BMWalker *walker)
|
||||
{
|
||||
uvedgeWalker *lwalk = BMW_currentstate(walker);
|
||||
uvedgeWalker *lwalk = walker->currentstate;
|
||||
|
||||
if (!lwalk) return NULL;
|
||||
|
||||
@@ -752,7 +699,7 @@ static void *uvedgeWalker_yield(BMWalker *walker)
|
||||
|
||||
static void *uvedgeWalker_step(BMWalker *walker)
|
||||
{
|
||||
uvedgeWalker *lwalk = BMW_currentstate(walker);
|
||||
uvedgeWalker *lwalk = walker->currentstate;
|
||||
BMLoop *l, *l2, *l3, *nl, *cl;
|
||||
BMIter liter;
|
||||
void *d1, *d2;
|
||||
@@ -762,7 +709,7 @@ static void *uvedgeWalker_step(BMWalker *walker)
|
||||
nl = l->next;
|
||||
type = walker->bm->ldata.layers[walker->flag].type;
|
||||
|
||||
BMW_removestate(walker);
|
||||
BMW_popstate(walker);
|
||||
|
||||
if (walker->restrictflag && !BMO_TestFlag(walker->bm, l->e, walker->restrictflag))
|
||||
return l;
|
||||
@@ -792,8 +739,9 @@ static void *uvedgeWalker_step(BMWalker *walker)
|
||||
if (!CustomData_data_equals(type, d1, d2))
|
||||
continue;
|
||||
|
||||
lwalk = BMW_addstate(walker);
|
||||
BMW_pushstate(walker);
|
||||
BLI_ghash_insert(walker->visithash, l2, NULL);
|
||||
lwalk = walker->currentstate;
|
||||
|
||||
lwalk->l = l2;
|
||||
|
||||
@@ -805,12 +753,12 @@ static void *uvedgeWalker_step(BMWalker *walker)
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
static BMWalker shell_walker_type = {
|
||||
shellWalker_begin,
|
||||
shellWalker_step,
|
||||
shellWalker_yield,
|
||||
sizeof(shellWalker),
|
||||
BMW_BREADTH_FIRST,
|
||||
};
|
||||
|
||||
static BMWalker islandbound_walker_type = {
|
||||
@@ -818,15 +766,14 @@ static BMWalker islandbound_walker_type = {
|
||||
islandboundWalker_step,
|
||||
islandboundWalker_yield,
|
||||
sizeof(islandboundWalker),
|
||||
BMW_DEPTH_FIRST,
|
||||
};
|
||||
|
||||
|
||||
static BMWalker island_walker_type = {
|
||||
islandWalker_begin,
|
||||
islandWalker_step,
|
||||
islandWalker_yield,
|
||||
sizeof(islandWalker),
|
||||
BMW_BREADTH_FIRST,
|
||||
};
|
||||
|
||||
static BMWalker loop_walker_type = {
|
||||
@@ -834,15 +781,14 @@ static BMWalker loop_walker_type = {
|
||||
loopWalker_step,
|
||||
loopWalker_yield,
|
||||
sizeof(loopWalker),
|
||||
BMW_DEPTH_FIRST,
|
||||
};
|
||||
|
||||
|
||||
static BMWalker faceloop_walker_type = {
|
||||
faceloopWalker_begin,
|
||||
faceloopWalker_step,
|
||||
faceloopWalker_yield,
|
||||
sizeof(faceloopWalker),
|
||||
BMW_DEPTH_FIRST,
|
||||
};
|
||||
|
||||
static BMWalker edgering_walker_type = {
|
||||
@@ -850,7 +796,6 @@ static BMWalker edgering_walker_type = {
|
||||
edgeringWalker_step,
|
||||
edgeringWalker_yield,
|
||||
sizeof(edgeringWalker),
|
||||
BMW_DEPTH_FIRST,
|
||||
};
|
||||
|
||||
static BMWalker loopdata_region_walker_type = {
|
||||
@@ -858,15 +803,6 @@ static BMWalker loopdata_region_walker_type = {
|
||||
uvedgeWalker_step,
|
||||
uvedgeWalker_yield,
|
||||
sizeof(uvedgeWalker),
|
||||
BMW_DEPTH_FIRST,
|
||||
};
|
||||
|
||||
static BMWalker connected_vertex_walker_type = {
|
||||
connectedVertexWalker_begin,
|
||||
connectedVertexWalker_step,
|
||||
connectedVertexWalker_yield,
|
||||
sizeof(connectedVertexWalker),
|
||||
BMW_BREADTH_FIRST,
|
||||
};
|
||||
|
||||
BMWalker *bm_walker_types[] = {
|
||||
@@ -877,7 +813,8 @@ BMWalker *bm_walker_types[] = {
|
||||
&loopdata_region_walker_type,
|
||||
&islandbound_walker_type,
|
||||
&island_walker_type,
|
||||
&connected_vertex_walker_type,
|
||||
};
|
||||
|
||||
int bm_totwalkers = sizeof(bm_walker_types) / sizeof(*bm_walker_types);
|
||||
|
||||
|
||||
|
||||
@@ -32,56 +32,44 @@
|
||||
extern BMWalker *bm_walker_types[];
|
||||
extern int bm_totwalkers;
|
||||
|
||||
|
||||
/* Pointer hiding*/
|
||||
typedef struct bmesh_walkerGeneric{
|
||||
Link link;
|
||||
int depth;
|
||||
} bmesh_walkerGeneric;
|
||||
|
||||
|
||||
typedef struct shellWalker{
|
||||
bmesh_walkerGeneric header;
|
||||
BMEdge *curedge;
|
||||
struct shellWalker *prev;
|
||||
BMVert *base;
|
||||
BMEdge *curedge, *current;
|
||||
} shellWalker;
|
||||
|
||||
typedef struct islandboundWalker {
|
||||
bmesh_walkerGeneric header;
|
||||
struct islandboundWalker *prev;
|
||||
BMLoop *base;
|
||||
BMVert *lastv;
|
||||
BMLoop *curloop;
|
||||
} islandboundWalker;
|
||||
|
||||
typedef struct islandWalker {
|
||||
bmesh_walkerGeneric header;
|
||||
struct islandWalker * prev;
|
||||
BMFace *cur;
|
||||
} islandWalker;
|
||||
|
||||
typedef struct loopWalker {
|
||||
bmesh_walkerGeneric header;
|
||||
struct loopWalker * prev;
|
||||
BMEdge *cur, *start;
|
||||
BMVert *lastv, *startv;
|
||||
int startrad, stage2;
|
||||
} loopWalker;
|
||||
|
||||
typedef struct faceloopWalker {
|
||||
bmesh_walkerGeneric header;
|
||||
struct faceloopWalker * prev;
|
||||
BMLoop *l;
|
||||
int nocalc;
|
||||
} faceloopWalker;
|
||||
|
||||
typedef struct edgeringWalker {
|
||||
bmesh_walkerGeneric header;
|
||||
struct edgeringWalker * prev;
|
||||
BMLoop *l;
|
||||
BMEdge *wireedge;
|
||||
} edgeringWalker;
|
||||
|
||||
typedef struct uvedgeWalker {
|
||||
bmesh_walkerGeneric header;
|
||||
struct uvedgeWalker *prev;
|
||||
BMLoop *l;
|
||||
} uvedgeWalker;
|
||||
|
||||
typedef struct connectedVertexWalker {
|
||||
bmesh_walkerGeneric header;
|
||||
BMVert *curvert;
|
||||
} connectedVertexWalker;
|
||||
|
||||
@@ -890,8 +890,9 @@ static void walker_select(BMEditMesh *em, int walkercode, void *start, int selec
|
||||
BMW_Init(&walker, bm, walkercode, 0, 0);
|
||||
h = BMW_Begin(&walker, start);
|
||||
for (; h; h=BMW_Step(&walker)) {
|
||||
if (!select)
|
||||
if (!select) {
|
||||
BM_remove_selection(bm, h);
|
||||
}
|
||||
BM_Select(bm, h, select);
|
||||
}
|
||||
BMW_End(&walker);
|
||||
@@ -982,7 +983,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
|
||||
BMEditMesh *em;
|
||||
BMEdge *eed;
|
||||
int select= 1;
|
||||
int dist = 50;
|
||||
int dist= 50;
|
||||
|
||||
em_setup_viewcontext(C, &vc);
|
||||
vc.mval[0]= mval[0];
|
||||
@@ -992,16 +993,12 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
|
||||
/* no afterqueue (yet), so we check it now, otherwise the bm_xxxofs indices are bad */
|
||||
view3d_validate_backbuf(&vc);
|
||||
|
||||
eed = EDBM_findnearestedge(&vc, &dist);
|
||||
if (eed) {
|
||||
eed= EDBM_findnearestedge(&vc, &dist);
|
||||
if(eed) {
|
||||
if(extend==0) EDBM_clear_flag_all(em, BM_SELECT);
|
||||
|
||||
if (BM_TestHFlag(eed, BM_SELECT)==0) {
|
||||
select=1;
|
||||
}
|
||||
else if (extend) {
|
||||
select=0;
|
||||
}
|
||||
if(BM_TestHFlag(eed, BM_SELECT)==0) select=1;
|
||||
else if(extend) select=0;
|
||||
|
||||
if(em->selectmode & SCE_SELECT_FACE) {
|
||||
walker_select(em, BMW_FACELOOP, eed, select);
|
||||
@@ -1015,7 +1012,6 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
|
||||
else if(em->selectmode & SCE_SELECT_VERTEX) {
|
||||
if(ring)
|
||||
walker_select(em, BMW_EDGERING, eed, select);
|
||||
|
||||
else
|
||||
walker_select(em, BMW_LOOP, eed, select);
|
||||
}
|
||||
@@ -1024,19 +1020,8 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short ring)
|
||||
// if (EM_texFaceCheck())
|
||||
|
||||
/* sets as active, useful for other tools */
|
||||
if (select) {
|
||||
if (em->selectmode & SCE_SELECT_VERTEX) {
|
||||
/* TODO: would be nice if the edge vertex chosen here
|
||||
was the one closer to the selection pointer, instead
|
||||
of arbitrarily selecting the first one */
|
||||
EDBM_store_selection(em, eed->v1);
|
||||
}
|
||||
else if(em->selectmode & SCE_SELECT_EDGE) {
|
||||
EDBM_store_selection(em, eed);
|
||||
}
|
||||
/* TODO: would be nice if the nearest face that
|
||||
belongs to the selected edge could be set to
|
||||
active here in face select mode */
|
||||
if(select && em->selectmode & SCE_SELECT_EDGE) {
|
||||
EDBM_store_selection(em, eed);
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit);
|
||||
@@ -1936,66 +1921,197 @@ void MESH_OT_select_less(wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* Walk all reachable elements of the same type as h_act in breadth-first
|
||||
order, starting from h_act. Deselects elements if the depth when they
|
||||
are reached is not a multiple of "nth". */
|
||||
static void walker_deselect_nth(BMEditMesh *em, int nth, int offset, BMHeader *h_act)
|
||||
/* not that optimal!, should be nicer with bmesh */
|
||||
static void tag_face_edges(BMesh* bm, BMFace *f)
|
||||
{
|
||||
BMHeader *h;
|
||||
BMesh *bm = em->bm;
|
||||
BMWalker walker;
|
||||
BMLoop *l;
|
||||
BMIter iter;
|
||||
int walktype = 0, itertype = 0, flushtype = 0;
|
||||
|
||||
/* No active element from which to start - nothing to do */
|
||||
if(h_act==NULL) {
|
||||
BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
|
||||
BM_SetIndex(l->e, 1);
|
||||
}
|
||||
}
|
||||
static int tag_face_edges_test(BMesh* bm, BMFace *f)
|
||||
{
|
||||
BMLoop *l;
|
||||
BMIter iter;
|
||||
|
||||
BM_ITER(l, &iter, bm, BM_LOOPS_OF_FACE, f) {
|
||||
if(BM_GetIndex(l->e) != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void em_deselect_nth_face(BMEditMesh *em, int nth, BMFace *f_act)
|
||||
{
|
||||
BMFace *f;
|
||||
BMEdge *e;
|
||||
BMIter iter;
|
||||
BMesh *bm = em->bm;
|
||||
int index;
|
||||
int ok= 1;
|
||||
|
||||
if(f_act==NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine which type of iter, walker, and select flush to use
|
||||
based on type of the elements being deselected */
|
||||
switch (h_act->type) {
|
||||
case BM_VERT:
|
||||
itertype = BM_VERTS_OF_MESH;
|
||||
walktype = BMW_CONNECTED_VERTEX;
|
||||
flushtype = SCE_SELECT_VERTEX;
|
||||
break;
|
||||
case BM_EDGE:
|
||||
itertype = BM_EDGES_OF_MESH;
|
||||
walktype = BMW_SHELL;
|
||||
flushtype = SCE_SELECT_EDGE;
|
||||
break;
|
||||
case BM_FACE:
|
||||
itertype = BM_FACES_OF_MESH;
|
||||
walktype = BMW_ISLAND;
|
||||
flushtype = SCE_SELECT_FACE;
|
||||
break;
|
||||
/* to detect loose edges, we put f2 flag on 1 */
|
||||
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
BM_SetIndex(e, 0);
|
||||
}
|
||||
|
||||
/* Walker restrictions uses BMO flags, not header flags,
|
||||
so transfer BM_SELECT from HFlags onto a BMO flag layer. */
|
||||
BMO_push(bm, NULL);
|
||||
BM_ITER(h, &iter, bm, itertype, NULL) {
|
||||
if (BM_TestHFlag(h, BM_SELECT)) {
|
||||
BMO_SetFlag(bm, h, BM_SELECT);
|
||||
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
||||
BM_SetIndex(f, 0);
|
||||
}
|
||||
|
||||
BM_SetIndex(f_act, 1);
|
||||
|
||||
while(ok) {
|
||||
ok = 0;
|
||||
|
||||
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
||||
index= BM_GetIndex(f);
|
||||
if(index==1) { /* initialize */
|
||||
tag_face_edges(bm, f);
|
||||
}
|
||||
|
||||
if (index)
|
||||
BM_SetIndex(f, index+1);
|
||||
}
|
||||
|
||||
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
||||
if(BM_GetIndex(f)==0 && tag_face_edges_test(bm, f)) {
|
||||
BM_SetIndex(f, 1);
|
||||
ok= 1; /* keep looping */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk over selected elements starting at active */
|
||||
BMW_Init(&walker, bm, walktype, BM_SELECT, 0);
|
||||
BLI_assert(walker.order == BMW_BREADTH_FIRST);
|
||||
for (h = BMW_Begin(&walker, h_act); h != NULL; h = BMW_Step(&walker)) {
|
||||
/* Deselect elements that aren't at "nth" depth from active */
|
||||
if ((offset + BMW_CurrentDepth(&walker)) % nth) {
|
||||
BM_Select(bm, h, 0);
|
||||
BM_ITER(f, &iter, bm, BM_FACES_OF_MESH, NULL) {
|
||||
index= BM_GetIndex(f);
|
||||
if(index > 0 && index % nth) {
|
||||
BM_Select(bm, f, 0);
|
||||
}
|
||||
}
|
||||
BMW_End(&walker);
|
||||
|
||||
BMO_pop(bm);
|
||||
EDBM_select_flush(em, SCE_SELECT_FACE);
|
||||
}
|
||||
|
||||
/* Flush selection up */
|
||||
EDBM_select_flush(em, flushtype);
|
||||
/* not that optimal!, should be nicer with bmesh */
|
||||
static void tag_edge_verts(BMEdge *e)
|
||||
{
|
||||
BM_SetIndex(e->v1, 1);
|
||||
BM_SetIndex(e->v2, 1);
|
||||
}
|
||||
static int tag_edge_verts_test(BMEdge *e)
|
||||
{
|
||||
return (BM_GetIndex(e->v1) || BM_GetIndex(e->v2)) ? 1:0;
|
||||
}
|
||||
|
||||
static void em_deselect_nth_edge(BMEditMesh *em, int nth, BMEdge *e_act)
|
||||
{
|
||||
BMEdge *e;
|
||||
BMVert *v;
|
||||
BMIter iter;
|
||||
BMesh *bm = em->bm;
|
||||
int index;
|
||||
int ok= 1;
|
||||
|
||||
if(e_act==NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
||||
BM_SetIndex(v, 0);
|
||||
}
|
||||
|
||||
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
BM_SetIndex(e, 0);
|
||||
}
|
||||
|
||||
BM_SetIndex(e_act, 1);
|
||||
|
||||
while(ok) {
|
||||
ok = 0;
|
||||
|
||||
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
index= BM_GetIndex(e);
|
||||
if (index==1) { /* initialize */
|
||||
tag_edge_verts(e);
|
||||
}
|
||||
|
||||
if (index)
|
||||
BM_SetIndex(e, index+1);
|
||||
}
|
||||
|
||||
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
if (BM_GetIndex(e)==0 && tag_edge_verts_test(e)) {
|
||||
BM_SetIndex(e, 1);
|
||||
ok = 1; /* keep looping */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
index= BM_GetIndex(e);
|
||||
if (index > 0 && index % nth)
|
||||
BM_Select(bm, e, 0);
|
||||
}
|
||||
|
||||
EDBM_select_flush(em, SCE_SELECT_EDGE);
|
||||
}
|
||||
|
||||
static void em_deselect_nth_vert(BMEditMesh *em, int nth, BMVert *v_act)
|
||||
{
|
||||
BMEdge *e;
|
||||
BMVert *v;
|
||||
BMIter iter;
|
||||
BMesh *bm = em->bm;
|
||||
int ok= 1;
|
||||
|
||||
if(v_act==NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
||||
BM_SetIndex(v, 0);
|
||||
}
|
||||
|
||||
BM_SetIndex(v_act, 1);
|
||||
|
||||
while(ok) {
|
||||
ok = 0;
|
||||
|
||||
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
||||
int index = BM_GetIndex(v);
|
||||
if (index != 0)
|
||||
BM_SetIndex(v, index+1);
|
||||
}
|
||||
|
||||
BM_ITER(e, &iter, bm, BM_EDGES_OF_MESH, NULL) {
|
||||
int indexv1= BM_GetIndex(e->v1);
|
||||
int indexv2= BM_GetIndex(e->v2);
|
||||
if (indexv1 == 2 && indexv2 == 0) {
|
||||
BM_SetIndex(e->v2, 1);
|
||||
ok = 1; /* keep looping */
|
||||
}
|
||||
else if (indexv2 == 2 && indexv1 == 0) {
|
||||
BM_SetIndex(e->v1, 1);
|
||||
ok = 1; /* keep looping */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BM_ITER(v, &iter, bm, BM_VERTS_OF_MESH, NULL) {
|
||||
int index= BM_GetIndex(v);
|
||||
if(index && index % nth) {
|
||||
BM_Select(bm, v, 0);
|
||||
}
|
||||
}
|
||||
|
||||
EDBM_select_flush(em, SCE_SELECT_VERTEX);
|
||||
}
|
||||
|
||||
static void deselect_nth_active(BMEditMesh *em, BMVert **v_p, BMEdge **e_p, BMFace **f_p)
|
||||
@@ -2052,7 +2168,7 @@ static void deselect_nth_active(BMEditMesh *em, BMVert **v_p, BMEdge **e_p, BMFa
|
||||
}
|
||||
}
|
||||
|
||||
static int EM_deselect_nth(BMEditMesh *em, int nth, int offset)
|
||||
static int EM_deselect_nth(BMEditMesh *em, int nth)
|
||||
{
|
||||
BMVert *v;
|
||||
BMEdge *e;
|
||||
@@ -2060,16 +2176,16 @@ static int EM_deselect_nth(BMEditMesh *em, int nth, int offset)
|
||||
|
||||
deselect_nth_active(em, &v, &e, &f);
|
||||
|
||||
if (v) {
|
||||
walker_deselect_nth(em, nth, offset, v);
|
||||
if(v) {
|
||||
em_deselect_nth_vert(em, nth, v);
|
||||
return 1;
|
||||
}
|
||||
else if(e) {
|
||||
walker_deselect_nth(em, nth, offset, e);
|
||||
em_deselect_nth_edge(em, nth, e);
|
||||
return 1;
|
||||
}
|
||||
else if(f) {
|
||||
walker_deselect_nth(em, nth, offset, f);
|
||||
em_deselect_nth_face(em, nth, f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2081,11 +2197,8 @@ static int mesh_select_nth_exec(bContext *C, wmOperator *op)
|
||||
Object *obedit= CTX_data_edit_object(C);
|
||||
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
|
||||
int nth= RNA_int_get(op->ptr, "nth");
|
||||
int offset= RNA_int_get(op->ptr, "offset");
|
||||
|
||||
offset = MIN2(nth, offset);
|
||||
|
||||
if(EM_deselect_nth(em, nth, offset) == 0) {
|
||||
if(EM_deselect_nth(em, nth) == 0) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
@@ -2112,7 +2225,6 @@ void MESH_OT_select_nth(wmOperatorType *ot)
|
||||
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||
|
||||
RNA_def_int(ot->srna, "nth", 2, 2, 100, "Nth Selection", "", 1, INT_MAX);
|
||||
RNA_def_int(ot->srna, "offset", 0, 0, 100, "Offset", "", 0, INT_MAX);
|
||||
}
|
||||
|
||||
void em_setup_viewcontext(bContext *C, ViewContext *vc)
|
||||
|
||||
Reference in New Issue
Block a user