undo of 40542 (meant to make two separate changes)

This commit is contained in:
Andrew Wiggin
2011-09-26 00:32:45 +00:00
parent 6cd42ebe18
commit f19cb3fc6b
9 changed files with 375 additions and 458 deletions

View File

@@ -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.*/

View File

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

View File

@@ -59,7 +59,6 @@ void BME_error(void);
/*bmesh_error stub*/
void bmesh_error(void)
{
BLI_assert(0);
printf("BM modelling error!");
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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