Example #1
0
/**
 *			BME_SFME
 *
 *	SPLIT FACE MAKE EDGE:
 *
 *	Takes as input two vertices in a single face. An edge is created which divides the original face
 *	into two distinct regions. One of the regions is assigned to the original face and it is closed off.
 *	The second region has a new face assigned to it.
 *
 *	Examples:
 *	
 *     Before:               After:
 *	 ----------           ----------
 *	 |		  |           |        | 
 *	 |        |           |   f1   |
 *	v1   f1   v2          v1======v2
 *	 |        |           |   f2   |
 *	 |        |           |        |
 *	 ----------           ---------- 
 *
 *	Note that the input vertices can be part of the same edge. This will result in a two edged face.
 *  This is desirable for advanced construction tools and particularly essential for edge bevel. Because
 *  of this it is up to the caller to decide what to do with the extra edge.
 *
 *	Returns -
 *  A BME_Poly pointer
 */
BME_Poly *BME_SFME(BME_Mesh *bm, BME_Poly *f, BME_Vert *v1, BME_Vert *v2, BME_Loop **rl){

	BME_Poly *f2;
	BME_Loop *v1loop = NULL, *v2loop = NULL, *curloop, *f1loop=NULL, *f2loop=NULL;
	BME_Edge *e;
	int i, len, f1len, f2len;
	
	
	/*verify that v1 and v2 are in face.*/
	len = BME_cycle_length(f->loopbase);
	for(i = 0, curloop = f->loopbase; i < len; i++, curloop = curloop->next){
		if(curloop->v == v1) v1loop = curloop;
		else if(curloop->v == v2) v2loop = curloop;
	}
	
	if(!v1loop || !v2loop) return NULL;
	
	/*allocate new edge between v1 and v2*/
	e = BME_addedgelist(bm, v1, v2,NULL);
	BME_disk_append_edge(e, v1);
	BME_disk_append_edge(e, v2);
	
	f2 = BME_addpolylist(bm,f);
	f1loop = BME_create_loop(bm,v2,e,f,v2loop);
	f2loop = BME_create_loop(bm,v1,e,f2,v1loop);
	
	f1loop->prev = v2loop->prev;
	f2loop->prev = v1loop->prev;
	v2loop->prev->next = f1loop;
	v1loop->prev->next = f2loop;
	
	f1loop->next = v1loop;
	f2loop->next = v2loop;
	v1loop->prev = f1loop;
	v2loop->prev = f2loop;
	
	f2->loopbase = f2loop;
	f->loopbase = f1loop;
	
	/*validate both loops*/
	/*I dont know how many loops are supposed to be in each face at this point! FIXME!*/
	
	/*go through all of f2's loops and make sure they point to it properly.*/
	f2len = BME_cycle_length(f2->loopbase);
	for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next) curloop->f = f2;
	
	/*link up the new loops into the new edges radial*/
	BME_radial_append(e, f1loop);
	BME_radial_append(e, f2loop);
	
	
	f2->len = f2len;
	
	f1len = BME_cycle_length(f->loopbase);
	f->len = f1len;
	
	if(rl) *rl = f2loop;
	return f2;
}
Example #2
0
int BME_loop_reverse(BME_Mesh *bm, BME_Poly *f){
	BME_Loop *l = f->loopbase, *curloop, *oldprev, *oldnext;
	int i, j, edok, len = 0;

	len = BME_cycle_length(l);
	if(bm->edarlen < len){
		MEM_freeN(bm->edar);
		bm->edar = MEM_callocN(sizeof(BME_Edge *)* len, "BMesh Edge pointer array");
		bm->edarlen = len;
	}
	
	for(i=0, curloop = l; i< len; i++, curloop=curloop->next){
		curloop->e->eflag1 = 0;
		curloop->e->eflag2 = BME_cycle_length(&curloop->radial);
		BME_radial_remove_loop(curloop, curloop->e);
		/*in case of border edges we HAVE to zero out curloop->radial Next/Prev*/
		curloop->radial.next = curloop->radial.prev = NULL;
		bm->edar[i] = curloop->e;
	}
	
	/*actually reverse the loop. This belongs in BME_cycle_reverse!*/
	for(i=0, curloop = l; i < len; i++){
		oldnext = curloop->next;
		oldprev = curloop->prev;
		curloop->next = oldprev;
		curloop->prev = oldnext;
		curloop = oldnext;
	}

	if(len == 2){ //two edged face
		//do some verification here!
		l->e = bm->edar[1];
		l->next->e = bm->edar[0];
	}
	else{
		for(i=0, curloop = l; i < len; i++, curloop = curloop->next){
			edok = 0;
			for(j=0; j < len; j++){
				edok = BME_verts_in_edge(curloop->v, curloop->next->v, bm->edar[j]);
				if(edok){
					curloop->e = bm->edar[j];
					break;
				}
			}
		}
	}
	/*rebuild radial*/
	for(i=0, curloop = l; i < len; i++, curloop = curloop->next) BME_radial_append(curloop->e, curloop);
	
	/*validate radial*/
	for(i=0, curloop = l; i < len; i++, curloop = curloop->next){
		edok = BME_cycle_validate(curloop->e->eflag2, &(curloop->radial));
		if(!edok){
			BME_error();
		}
	}
	return 1;
}
static void bmesh_dissolve_disk(BME_Mesh *bm, BME_Vert *v){
	BME_Poly *f;
	BME_Edge *e;
	int done, len;
	
	if(v->edge){
		done = 0;
		while(!done){
			done = 1;
			e = v->edge; /*loop the edge looking for a edge to dissolve*/
			do{
				f = NULL;
				len = BME_cycle_length(&(e->loop->radial));
				if(len == 2){
					f = BME_JFKE_safe(bm,e->loop->f, ((BME_Loop*)(e->loop->radial.next->data))->f, e);
				}
				if(f){ 
					done = 0;
					break;
				}
				e = BME_disk_nextedge(e,v);
			}while(e != v->edge);
		}
		BME_collapse_vert(bm, v->edge, v, 1.0);
		//BME_JEKV(bm,v->edge,v);
	}
}
static int BME_is_nonmanifold_vert(BME_Mesh *UNUSED(bm), BME_Vert *v) {
	BME_Edge *e, *oe;
	BME_Loop *l;
	int len, count, flag;

	if (v->edge == NULL) {
		/* loose vert */
		return 1;
	}

	/* count edges while looking for non-manifold edges */
	oe = v->edge;
	for (len=0,e=v->edge; e != oe || (e == oe && len == 0); len++,e=BME_disk_nextedge(e,v)) {
		if (e->loop == NULL) {
			/* loose edge */
			return 1;
		}

		if (BME_cycle_length(&(e->loop->radial)) > 2) {
			/* edge shared by more than two faces */
			return 1;
		}
	}

	count = 1;
	flag = 1;
	e = NULL;
	oe = v->edge;
	l = oe->loop;
	while(e != oe) {
		if (l->v == v) l = l->prev;
		else l = l->next;
		e = l->e;
		count++; /* count the edges */

		if (flag && l->radial.next->data == l) {
			/* we've hit the edge of an open mesh, reset once */
			flag = 0;
			count = 1;
			oe = e;
			e = NULL;
			l = oe->loop;
		}
		else if (l->radial.next->data == l) {
			/* break the loop */
			e = oe;
		}
		else {
			l = l->radial.next->data;
		}
	}

	if (count < len) {
		/* vert shared by multiple regions */
		return 1;
	}

	return 0;
}
Example #5
0
BME_Edge *BME_ME(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2){
	BME_Edge *e=NULL;
	BME_CycleNode *d1=NULL, *d2=NULL;
	int valance1=0, valance2=0, edok;
	
	/*edge must be between two distinct vertices...*/
	if(v1 == v2) return NULL;
	
	#ifndef BME_FASTEULER
	/*count valance of v1*/
	if(v1->edge){ 
		d1 = BME_disk_getpointer(v1->edge,v1);
		if(d1) valance1 = BME_cycle_length(d1);
		else BME_error();
	}
	if(v2->edge){
		d2 = BME_disk_getpointer(v2->edge,v2);
		if(d2) valance2 = BME_cycle_length(d2);
		else BME_error();
	}
	#endif
	
	/*go ahead and add*/
	e = BME_addedgelist(bm, v1, v2, NULL);
	BME_disk_append_edge(e, e->v1);
	BME_disk_append_edge(e, e->v2);
	
	#ifndef BME_FASTEULER
	/*verify disk cycle lengths*/
	d1 = BME_disk_getpointer(e, e->v1);
	edok = BME_cycle_validate(valance1+1, d1);
	if(!edok) BME_error();
	d2 = BME_disk_getpointer(e, e->v2);
	edok = BME_cycle_validate(valance2+1, d2);
	if(!edok) BME_error();
	
	/*verify that edge actually made it into the cycle*/
	edok = BME_disk_hasedge(v1, e);
	if(!edok) BME_error();
	edok = BME_disk_hasedge(v2, e);
	if(!edok) BME_error();
	#endif
	return e;
}
Example #6
0
int BME_KF(BME_Mesh *bm, BME_Poly *bply){
	BME_Loop *newbase,*oldbase, *curloop;
	int i,len=0;
	
	/*add validation to make sure that radial cycle is cleaned up ok*/
	/*deal with radial cycle first*/
	len = BME_cycle_length(bply->loopbase);
	for(i=0, curloop=bply->loopbase; i < len; i++, curloop = curloop->next) 
		BME_radial_remove_loop(curloop, curloop->e);
	
	/*now deallocate the editloops*/
	for(i=0; i < len; i++){
		newbase = bply->loopbase->next;
		oldbase = bply->loopbase;
		BME_cycle_remove(oldbase, oldbase);
		BME_free_loop(bm, oldbase);
		bply->loopbase = newbase;
	}
	
	BLI_remlink(&(bm->polys), bply);
	BME_free_poly(bm, bply);
	return 1;
}
Example #7
0
DerivedMesh *BME_bmesh_to_derivedmesh(BME_Mesh *bm, DerivedMesh *dm)
{
	MFace *mface, *mf;
	MEdge *medge, *me;
	MVert *mvert, *mv;
	int *origindex;
	int totface,totedge,totvert,i,bmeshok,len, numTex, numCol;

	BME_Vert *v1=NULL;
	BME_Edge *e=NULL, *oe=NULL;
	BME_Poly *f=NULL;
	
	DerivedMesh *result;
	EdgeHash *edge_hash = BLI_edgehash_new();

	totvert = BLI_countlist(&(bm->verts));
	totedge = 0;
	
	/*we cannot have double edges in a derived mesh!*/
	for(i=0, v1=bm->verts.first; v1; v1=v1->next, i++) v1->tflag1 = i;
	for(e=bm->edges.first; e; e=e->next){
		oe = BLI_edgehash_lookup(edge_hash,e->v1->tflag1, e->v2->tflag1);
		if(!oe){
			totedge++;
			BLI_edgehash_insert(edge_hash,e->v1->tflag1,e->v2->tflag1,e);
			e->tflag2 = 1;
		}
		else{
			e->tflag2 = 0;
		}
	}
	
	/*count quads and tris*/
	totface = 0;
	bmeshok = 1;
	for(f=bm->polys.first;f;f=f->next){
		len = BME_cycle_length(f->loopbase);
		if(len == 3 || len == 4) totface++;
	}
	
	/*convert back to mesh*/
	result = CDDM_from_template(dm,totvert,totedge,totface);
	CustomData_merge(&bm->vdata, &result->vertData, CD_MASK_BMESH, CD_CALLOC, totvert);
	CustomData_merge(&bm->edata, &result->edgeData, CD_MASK_BMESH, CD_CALLOC, totedge);
	CustomData_merge(&bm->pdata, &result->faceData, CD_MASK_BMESH, CD_CALLOC, totface);
	CustomData_from_bmeshpoly(&result->faceData, &bm->pdata, &bm->ldata,totface);
	numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);


	/*Make Verts*/
	mvert = CDDM_get_verts(result);
	origindex = result->getVertDataArray(result, CD_ORIGINDEX);
	for(i=0,v1=bm->verts.first,mv=mvert;v1;v1=v1->next,i++,mv++){
		VECCOPY(mv->co,v1->co);
		mv->flag = (unsigned char)v1->flag;
		mv->bweight = (char)(255.0*v1->bweight);
		CustomData_from_bmesh_block(&bm->vdata, &result->vertData, &v1->data, i);
		origindex[i] = ORIGINDEX_NONE;
	}
	medge = CDDM_get_edges(result);
	origindex = result->getEdgeDataArray(result, CD_ORIGINDEX);
	i=0;
	for(e=bm->edges.first,me=medge;e;e=e->next){
		if(e->tflag2){
			if(e->v1->tflag1 < e->v2->tflag1){
				me->v1 = e->v1->tflag1;
				me->v2 = e->v2->tflag1;
			}
			else{
				me->v1 = e->v2->tflag1;
				me->v2 = e->v1->tflag1;
			}
		
			me->crease = (char)(255.0*e->crease);
			me->bweight = (char)(255.0*e->bweight);
			me->flag = e->flag;
			CustomData_from_bmesh_block(&bm->edata, &result->edgeData, &e->data, i);
			origindex[i] = ORIGINDEX_NONE;
			me++;
			i++;
		}
	}
	if(totface){
		mface = CDDM_get_faces(result);
		origindex = result->getFaceDataArray(result, CD_ORIGINDEX);
		/*make faces*/
		for(i=0,f=bm->polys.first;f;f=f->next){
			mf = &mface[i];
			len = BME_cycle_length(f->loopbase);
			if(len==3 || len==4){
				mf->v1 = f->loopbase->v->tflag1;
				mf->v2 = f->loopbase->next->v->tflag1;
				mf->v3 = f->loopbase->next->next->v->tflag1;
				if(len == 4){
					mf->v4 = f->loopbase->prev->v->tflag1;
				}
				/* test and rotate indexes if necessary so that verts 3 and 4 aren't index 0 */
				if(mf->v3 == 0 || (len == 4 && mf->v4 == 0)){
					test_index_face(mf, NULL, i, len);
				}
				mf->mat_nr = (unsigned char)f->mat_nr;
				mf->flag = (unsigned char)f->flag;
				CustomData_from_bmesh_block(&bm->pdata, &result->faceData, &f->data, i);
				BME_DMloops_to_corners(bm, &result->faceData, i, f,numCol,numTex);
				origindex[i] = ORIGINDEX_NONE;
				i++;
			}
		}
	}
	BLI_edgehash_free(edge_hash, NULL);
	return result;
}
Example #8
0
/* adds the geometry in the bmesh to editMesh (does not free editMesh)
 * if td != NULL, the transdata will be mapped to the EditVert's co */
void BME_bmesh_to_editmesh(BME_Mesh *bm, BME_TransData_Head *td, EditMesh *em) {
	BME_Vert *v1;
	BME_Edge *e;
	BME_Poly *f;
	
	BME_TransData *vtd;

	EditVert *eve1, *eve2, *eve3, *eve4, **evlist;
	EditEdge *eed;
	EditFace *efa;

	int totvert, len, i, numTex, numCol;

	if (em == NULL) return;

	CustomData_copy(&bm->vdata, &em->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&bm->edata, &em->edata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_copy(&bm->pdata, &em->fdata, CD_MASK_BMESH, CD_CALLOC, 0);
	CustomData_from_bmeshpoly(&em->fdata, &bm->pdata, &bm->ldata,0);
	numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
	numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);


	/* convert to EditMesh */
	/* make editverts */
	totvert = BLI_countlist(&(bm->verts));
	evlist= (EditVert **)MEM_mallocN(totvert*sizeof(void *),"evlist");
	for (i=0,v1=bm->verts.first;v1;v1=v1->next,i++) {
		v1->tflag1 = i;
		eve1 = NULL; //XXX addvertlist(v1->co,NULL);
		if (td && (vtd = BME_get_transdata(td,v1))) {
			vtd->loc = eve1->co;
		}
		eve1->keyindex = i;
		evlist[i]= eve1;
		eve1->f = (unsigned char)v1->flag;
		eve1->h = (unsigned char)v1->h;
		eve1->bweight = v1->bweight;
		CustomData_em_copy_data(&bm->vdata, &em->vdata, v1->data, &eve1->data);
	}
	
	/* make edges */
	for (e=bm->edges.first;e;e=e->next) {
		if(0) { //XXX if(!(findedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1]))){
			eed= NULL; //XXX addedgelist(evlist[e->v1->tflag1], evlist[e->v2->tflag1], NULL);
			eed->crease = e->crease;
			eed->bweight = e->bweight;
			if(e->flag & ME_SEAM) eed->seam = 1;
			if(e->flag & ME_SHARP) eed->sharp = 1;
			if(e->flag & SELECT) eed->f |= SELECT;
			//XXX if(e->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
			if(e->flag & ME_HIDE) eed->h |= 1;
			if(em->selectmode==SCE_SELECT_EDGE) { 
				; //XXX EM_select_edge(eed, eed->f & SELECT);
			}
			CustomData_em_copy_data(&bm->edata, &em->edata, e->data, &eed->data);
		}
	}

	/* make faces */
	for (f=bm->polys.first;f;f=f->next) {
		len = BME_cycle_length(f->loopbase);
		if (len==3 || len==4) {
			eve1= evlist[f->loopbase->v->tflag1];
			eve2= evlist[f->loopbase->next->v->tflag1];
			eve3= evlist[f->loopbase->next->next->v->tflag1];
			if (len == 4) {
				eve4= evlist[f->loopbase->prev->v->tflag1];
			}
			else {
				eve4= NULL;
			}

			efa = NULL; //XXX addfacelist(eve1, eve2, eve3, eve4, NULL, NULL);
			efa->mat_nr = (unsigned char)f->mat_nr;
			efa->flag= f->flag & ~ME_HIDE;
			if(f->flag & ME_FACE_SEL) {
				efa->f |= SELECT;
			}
			if(f->flag & ME_HIDE) efa->h= 1;
			// XXX flag depricated
			// if((G.f & G_FACESELECT) && (efa->f & SELECT))
				//XXX EM_select_face(efa, 1); /* flush down */
			CustomData_em_copy_data(&bm->pdata, &em->fdata, f->data, &efa->data);
			BME_loops_to_corners(bm, &em->fdata, efa->data, f,numCol,numTex);
		}
	}

	MEM_freeN(evlist);

}
Example #9
0
BME_Poly *BME_JFKE(BME_Mesh *bm, BME_Poly *f1, BME_Poly *f2, BME_Edge *e)
{
	
	BME_Loop *curloop, *f1loop=NULL, *f2loop=NULL;
	int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok;
	
	if(f1 == f2) return NULL; //can't join a face to itself
	/*verify that e is in both f1 and f2*/
	f1len = BME_cycle_length(f1->loopbase);
	f2len = BME_cycle_length(f2->loopbase);
	for(i=0, curloop = f1->loopbase; i < f1len; i++, curloop = curloop->next){
		if(curloop->e == e){ 
			f1loop = curloop;
			break;
		}
	}
	for(i=0, curloop = f2->loopbase; i < f2len; i++, curloop = curloop->next){
		if(curloop->e==e){
			f2loop = curloop;
			break;
		}
	}
	if(!(f1loop && f2loop)) return NULL;
	
	/*validate that edge is 2-manifold edge*/
	radlen = BME_cycle_length(&(f1loop->radial));
	if(radlen != 2) return NULL;

	/*validate direction of f2's loop cycle is compatible.*/
	if(f1loop->v == f2loop->v) return NULL;
	
	/*
		Finally validate that for each face, each vertex has another edge in its disk cycle that is 
		not e, and not shared.
	*/
	if(BME_radial_find_face(f1loop->next->e,f2)) return NULL;
	if(BME_radial_find_face(f1loop->prev->e,f2)) return NULL;
	if(BME_radial_find_face(f2loop->next->e,f1)) return NULL;
	if(BME_radial_find_face(f2loop->prev->e,f1)) return NULL;
	
	/*join the two loops*/
	f1loop->prev->next = f2loop->next;
	f2loop->next->prev = f1loop->prev;
	
	f1loop->next->prev = f2loop->prev;
	f2loop->prev->next = f1loop->next;
	
	/*if f1loop was baseloop, give f1loop->next the base.*/
	if(f1->loopbase == f1loop) f1->loopbase = f1loop->next;
	
	/*validate the new loop*/
	loopok = BME_cycle_validate((f1len+f2len)-2, f1->loopbase);
	if(!loopok) BME_error();
	
	/*make sure each loop points to the proper face*/
	newlen = BME_cycle_length(f1->loopbase);
	for(i = 0, curloop = f1->loopbase; i < newlen; i++, curloop = curloop->next) curloop->f = f1;
	
	f1->len = newlen;
	
	edok = BME_cycle_validate(f1->len, f1->loopbase);
	if(!edok) BME_error();
	
	/*remove edge from the disk cycle of its two vertices.*/
	BME_disk_remove_edge(f1loop->e, f1loop->e->v1);
	BME_disk_remove_edge(f1loop->e, f1loop->e->v2);
	
	/*deallocate edge and its two loops as well as f2*/
	BLI_remlink(&(bm->edges), f1loop->e);
	BLI_remlink(&(bm->polys), f2);
	BME_free_edge(bm, f1loop->e);
	BME_free_loop(bm, f1loop);
	BME_free_loop(bm, f2loop);
	BME_free_poly(bm, f2);	
	return f1;
}
Example #10
0
/**
 *			BME_JEKV
 *
 *	JOIN EDGE KILL VERT:
 *	Takes a an edge and pointer to one of its vertices and collapses
 *	the edge on that vertex.
 *	
 *	Before:    OE      KE
 *             	 ------- -------
 *               |     ||      |
 *		OV     KV      TV
 *
 *
 *   After:             OE      
 *             	 ---------------
 *               |             |
 *		OV             TV
 *
 *
 *	Restrictions:
 *	KV is a vertex that must have a valance of exactly two. Furthermore
 *  both edges in KV's disk cycle (OE and KE) must be unique (no double
 *  edges).
 *
 *	It should also be noted that this euler has the possibility of creating
 *	faces with just 2 edges. It is up to the caller to decide what to do with
 *  these faces.
 *
 *  Returns -
 *	1 for success, 0 for failure.
 */
int BME_JEKV(BME_Mesh *bm, BME_Edge *ke, BME_Vert *kv)
{
	BME_Edge *oe;
	BME_Vert *ov, *tv;
	BME_CycleNode *diskbase;
	BME_Loop *killoop,*nextl;
	int len,radlen=0, halt = 0, i, valance1, valance2,edok;
	
	if(BME_vert_in_edge(ke,kv) == 0) return 0;
	diskbase = BME_disk_getpointer(kv->edge, kv);
	len = BME_cycle_length(diskbase);
	
	if(len == 2){
		oe = BME_disk_nextedge(ke, kv);
		tv = BME_edge_getothervert(ke, kv);
		ov = BME_edge_getothervert(oe, kv);		
		halt = BME_verts_in_edge(kv, tv, oe); //check for double edges
		
		if(halt) return 0;
		else{
			
			/*For verification later, count valance of ov and tv*/
			diskbase = BME_disk_getpointer(ov->edge, ov);
			valance1 = BME_cycle_length(diskbase);
			diskbase = BME_disk_getpointer(tv->edge, tv);
			valance2 = BME_cycle_length(diskbase);
			
			/*remove oe from kv's disk cycle*/
			BME_disk_remove_edge(oe,kv);
			/*relink oe->kv to be oe->tv*/
			BME_edge_swapverts(oe, kv, tv);
			/*append oe to tv's disk cycle*/
			BME_disk_append_edge(oe, tv);
			/*remove ke from tv's disk cycle*/
			BME_disk_remove_edge(ke, tv);
		
			

			/*deal with radial cycle of ke*/
			if(ke->loop){
				/*first step, fix the neighboring loops of all loops in ke's radial cycle*/
				radlen = BME_cycle_length(&(ke->loop->radial));
				for(i=0,killoop = ke->loop; i<radlen; i++, killoop = BME_radial_nextloop(killoop)){
					/*relink loops and fix vertex pointer*/
					killoop->next->prev = killoop->prev;
					killoop->prev->next = killoop->next;
					if(killoop->next->v == kv) killoop->next->v = tv;
					
					/*fix len attribute of face*/
					killoop->f->len--;
					if(killoop->f->loopbase == killoop) killoop->f->loopbase = killoop->next;
				}
				/*second step, remove all the hanging loops attached to ke*/
				killoop = ke->loop;
				radlen = BME_cycle_length(&(ke->loop->radial));
				/*make sure we have enough room in bm->lpar*/
				if(bm->lparlen < radlen){
					MEM_freeN(bm->lpar);
					bm->lpar = MEM_callocN(sizeof(BME_Loop *)* radlen, "BMesh Loop pointer array");
					bm->lparlen = bm->lparlen * radlen;
				}
				/*this should be wrapped into a bme_free_radial function to be used by BME_KF as well...*/
				i=0;
				while(i<radlen){
					bm->lpar[i] = killoop;
					killoop = killoop->radial.next->data;
					i++;
				}
				i=0;
				while(i<radlen){
					BME_free_loop(bm,bm->lpar[i]);
					i++;
				}
				/*Validate radial cycle of oe*/
				edok = BME_cycle_validate(radlen,&(oe->loop->radial));
				
			}
			

			/*Validate disk cycles*/
			diskbase = BME_disk_getpointer(ov->edge,ov);
			edok = BME_cycle_validate(valance1, diskbase);
			if(!edok) BME_error();
			diskbase = BME_disk_getpointer(tv->edge,tv);
			edok = BME_cycle_validate(valance2, diskbase);
			if(!edok) BME_error();
			
			/*Validate loop cycle of all faces attached to oe*/
			for(i=0,nextl = oe->loop; i<radlen; i++, nextl = BME_radial_nextloop(nextl)){
				edok = BME_cycle_validate(nextl->f->len,nextl->f->loopbase);
				if(!edok) BME_error();
			}
			/*deallocate edge*/
			BLI_remlink(&(bm->edges), ke);
			BME_free_edge(bm, ke);
			/*deallocate vertex*/
			BLI_remlink(&(bm->verts), kv);
			BME_free_vert(bm, kv);	
			return 1;
		}
	}
	return 0;
}
Example #11
0
BME_Vert *BME_SEMV(BME_Mesh *bm, BME_Vert *tv, BME_Edge *e, BME_Edge **re){
	BME_Vert *nv, *ov;
	BME_CycleNode *diskbase;
	BME_Edge *ne;
	int i, edok, valance1=0, valance2=0;
	
	if(BME_vert_in_edge(e,tv) == 0) return NULL;
	ov = BME_edge_getothervert(e,tv);
	//v2 = tv;

	/*count valance of v1*/
	diskbase = BME_disk_getpointer(e, ov);
	valance1 = BME_cycle_length(diskbase);
	/*count valance of v2*/
	diskbase = BME_disk_getpointer(e, tv);
	valance2 = BME_cycle_length(diskbase);
	
	nv = BME_addvertlist(bm, tv);
	ne = BME_addedgelist(bm, nv, tv, e);
	
	//e->v2 = nv;
	/*remove e from v2's disk cycle*/
	BME_disk_remove_edge(e, tv);
	/*swap out tv for nv in e*/
	BME_edge_swapverts(e, tv, nv);
	/*add e to nv's disk cycle*/
	BME_disk_append_edge(e, nv);
	/*add ne to nv's disk cycle*/
	BME_disk_append_edge(ne, nv);
	/*add ne to tv's disk cycle*/
	BME_disk_append_edge(ne, tv);
	/*verify disk cycles*/
	diskbase = BME_disk_getpointer(ov->edge,ov);
	edok = BME_cycle_validate(valance1, diskbase);
	if(!edok) BME_error();
	diskbase = BME_disk_getpointer(tv->edge,tv);
	edok = BME_cycle_validate(valance2, diskbase);
	if(!edok) BME_error();
	diskbase = BME_disk_getpointer(nv->edge,nv);
	edok = BME_cycle_validate(2, diskbase);
	if(!edok) BME_error();
	
	/*Split the radial cycle if present*/
	if(e->loop){
		BME_Loop *nl,*l;
		BME_CycleNode *radEBase=NULL, *radNEBase=NULL;
		int radlen = BME_cycle_length(&(e->loop->radial));
		/*Take the next loop. Remove it from radial. Split it. Append to appropriate radials.*/
		while(e->loop){
			l=e->loop;
			l->f->len++;
			BME_radial_remove_loop(l,e);
			
			nl = BME_create_loop(bm,NULL,NULL,l->f,l);
			nl->prev = l;
			nl->next = l->next;
			nl->prev->next = nl;
			nl->next->prev = nl;
			nl->v = nv;
			
			/*assign the correct edge to the correct loop*/
			if(BME_verts_in_edge(nl->v, nl->next->v, e)){
				nl->e = e;
				l->e = ne;
				
				/*append l into ne's rad cycle*/
				if(!radNEBase){
					radNEBase = &(l->radial);
					radNEBase->next = NULL;
					radNEBase->prev = NULL;
				}
				
				if(!radEBase){
					radEBase = &(nl->radial);
					radEBase->next = NULL;
					radEBase->prev = NULL;
				}
				
				BME_cycle_append(radEBase,&(nl->radial));
				BME_cycle_append(radNEBase,&(l->radial));
					
			}
			else if(BME_verts_in_edge(nl->v,nl->next->v,ne)){
				nl->e = ne;
				l->e = e;
				
				if(!radNEBase){
					radNEBase = &(nl->radial);
					radNEBase->next = NULL;
					radNEBase->prev = NULL;
				}
				if(!radEBase){
					radEBase = &(l->radial);
					radEBase->next = NULL;
					radEBase->prev = NULL;
				}
				BME_cycle_append(radEBase,&(l->radial));
				BME_cycle_append(radNEBase,&(nl->radial));
			}
					
		}
		
		e->loop = radEBase->data;
		ne->loop = radNEBase->data;
		
		/*verify length of radial cycle*/
		edok = BME_cycle_validate(radlen,&(e->loop->radial));
		if(!edok) BME_error();
		edok = BME_cycle_validate(radlen,&(ne->loop->radial));
		if(!edok) BME_error();
		
		/*verify loop->v and loop->next->v pointers for e*/
		for(i=0,l=e->loop; i < radlen; i++, l = l->radial.next->data){
			if(!(l->e == e)) BME_error();
			if(!(l->radial.data == l)) BME_error();
			if(l->prev->e != ne && l->next->e != ne) BME_error();
			edok = BME_verts_in_edge(l->v, l->next->v, e);
			if(!edok) BME_error();
			if(l->v == l->next->v) BME_error();
			if(l->e == l->next->e) BME_error();
			/*verify loop cycle for kloop->f*/
			edok = BME_cycle_validate(l->f->len, l->f->loopbase);
			if(!edok) BME_error();
		}
		/*verify loop->v and loop->next->v pointers for ne*/
		for(i=0,l=ne->loop; i < radlen; i++, l = l->radial.next->data){
			if(!(l->e == ne)) BME_error();
			if(!(l->radial.data == l)) BME_error();
			if(l->prev->e != e && l->next->e != e) BME_error();
			edok = BME_verts_in_edge(l->v, l->next->v, ne);
			if(!edok) BME_error();
			if(l->v == l->next->v) BME_error();
			if(l->e == l->next->e) BME_error();
			/*verify loop cycle for kloop->f. Redundant*/
			edok = BME_cycle_validate(l->f->len, l->f->loopbase);
			if(!edok) BME_error();
		}
	}
	
	if(re) *re = ne;
	return nv;
}
Example #12
0
BME_Poly *BME_MF(BME_Mesh *bm, BME_Vert *v1, BME_Vert *v2, BME_Edge **elist, int len)
{
	BME_Poly *f = NULL;
	BME_Edge *curedge;
	BME_Vert *curvert, *tv, **vlist;
	int i, j, done, cont, edok;
	
	if(len < 2) return NULL;
	
	/*make sure that v1 and v2 are in elist[0]*/
	if(BME_verts_in_edge(v1,v2,elist[0]) == 0) return NULL;
	
	/*clear euler flags*/
	for(i=0;i<len;i++) elist[i]->eflag1=elist[i]->eflag2 = 0;
	for(i=0;i<len;i++){
		elist[i]->eflag1 |= MF_CANDIDATE;
		
		/*if elist[i] has a loop, count its radial length*/
		if(elist[i]->loop) elist[i]->eflag2 = BME_cycle_length(&(elist[i]->loop->radial));
		else elist[i]->eflag2 = 0;
	}
	
	/*	For each vertex in each edge, it must have exactly two MF_CANDIDATE edges attached to it
		Note that this does not gauruntee that face is a single closed loop. At best it gauruntees
		that elist contains a finite number of seperate closed loops.
	*/
	for(i=0; i<len; i++){
		edok = BME_disk_count_edgeflag(elist[i]->v1, MF_CANDIDATE, 0);
		if(edok != 2) return NULL;
		edok = BME_disk_count_edgeflag(elist[i]->v2, MF_CANDIDATE, 0);
		if(edok != 2) return NULL;
	}
	
	/*set start edge, start vert and target vert for our loop traversal*/
	curedge = elist[0];
	tv = v1;
	curvert = v2;
	
	if(bm->vtarlen < len){
		MEM_freeN(bm->vtar);
		bm->vtar = MEM_callocN(sizeof(BME_Vert *)* len, "BMesh Vert pointer array");
		bm->vtarlen = len;
	}
	/*insert tv into vlist since its the first vertex in face*/
	i=0;
	vlist=bm->vtar;
	vlist[i] = tv;

	/*	Basic procedure: Starting with curv we find the edge in it's disk cycle which hasn't 
		been visited yet. When we do, we put curv in a linked list and find the next MF_CANDIDATE
		edge, loop until we find TV. We know TV is reachable because of test we did earlier.
	*/
	done=0;
	while(!done){
		/*add curvert to vlist*/
		/*insert some error cheking here for overflows*/
		i++;
		vlist[i] = curvert;
		
		/*mark curedge as visited*/
		curedge->eflag1 |= MF_VISITED;
		
		/*find next edge and vert*/
		curedge = BME_disk_next_edgeflag(curedge, curvert, MF_CANDIDATE, 0);
		curvert = BME_edge_getothervert(curedge, curvert);
		if(curvert == tv){
			curedge->eflag1 |= MF_VISITED;
			done=1;
		}
	}

	/*	Verify that all edges have been visited It's possible that we did reach tv 
		from sv, but that several unconnected loops were passed in via elist.
	*/
	cont=1;
	for(i=0; i<len; i++){
		if((elist[i]->eflag1 & MF_VISITED) == 0) cont = 0;
	}
	
	/*if we get this far, its ok to allocate the face and add the loops*/
	if(cont){
		BME_Loop *l;
		BME_Edge *e;
		f = BME_addpolylist(bm, NULL);
		f->len = len;
		for(i=0;i<len;i++){
			curvert = vlist[i];
			l = BME_create_loop(bm,curvert,NULL,f,NULL);
			if(!(f->loopbase)) f->loopbase = l;
			BME_cycle_append(f->loopbase, l);
		}
		
		/*take care of edge pointers and radial cycle*/
		for(i=0, l = f->loopbase; i<len; i++, l=l->next){
			e = NULL;
			if(l == f->loopbase) e = elist[0]; /*first edge*/
			
			else{/*search elist for others*/
				for(j=1; j<len; j++){
					edok = BME_verts_in_edge(l->v, l->next->v, elist[j]);
					if(edok){ 
						e = elist[j];
						break;
					}
				}
			}
			l->e = e; /*set pointer*/
			BME_radial_append(e, l); /*append into radial*/
		}

		f->len = len;
		
		/*Validation Loop cycle*/
		edok = BME_cycle_validate(len, f->loopbase);
		if(!edok) BME_error();
		for(i=0, l = f->loopbase; i<len; i++, l=l->next){
			/*validate loop vert pointers*/
			edok = BME_verts_in_edge(l->v, l->next->v, l->e);
			if(!edok) BME_error();
			/*validate the radial cycle of each edge*/
			edok = BME_cycle_length(&(l->radial));
			if(edok != (l->e->eflag2 + 1)) BME_error();
		}
	}
	return f;
}
Example #13
0
int BME_validate_mesh(struct BME_Mesh *bm, int halt)
{
	BME_Vert *v;
	BME_Edge *e;
	BME_Poly *f;
	BME_Loop *l;
	BME_CycleNode *diskbase;
	int i, ok;
	
	/*Simple edge verification*/
	for(e=bm->edges.first; e; e=e->next){
		if(e->v1 == e->v2) VHALT(halt);
		/*validate e->d1.data and e->d2.data*/
		if(e->d1.data != e || e->d2.data != e) VHALT(halt);
		/*validate e->loop->e*/
		if(e->loop){
			if(e->loop->e != e) VHALT(halt);
		}
	}
	
	/*calculate disk cycle lengths*/
	for(v=bm->verts.first; v; v=v->next) v->tflag1 = v->tflag2 = 0;
	for(e=bm->edges.first; e; e=e->next){ 
		e->v1->tflag1++;
		e->v2->tflag1++;
	}
	/*Validate vertices and disk cycle*/
	for(v=bm->verts.first; v; v=v->next){
		/*validate v->edge pointer*/
		if(v->tflag1){
			if(v->edge){
				ok = BME_vert_in_edge(v->edge,v);
				if(!ok) VHALT(halt);
				/*validate length of disk cycle*/
				diskbase = BME_disk_getpointer(v->edge, v);
				ok = BME_cycle_validate(v->tflag1, diskbase);
				if(!ok) VHALT(halt);
				/*validate that each edge in disk cycle contains V*/
				for(i=0, e=v->edge; i < v->tflag1; i++, e = BME_disk_nextedge(e,v)){
					ok = BME_vert_in_edge(e, v);
					if(!ok) VHALT(halt);
				}
			}
			else VHALT(halt);
		}
	}
	/*validate edges*/
	for(e=bm->edges.first; e; e=e->next){
		/*seperate these into BME_disk_hasedge (takes pointer to edge)*/
		/*search v1 disk cycle for edge*/
		ok = BME_disk_hasedge(e->v1,e);
		if(!ok) VHALT(halt);
		/*search v2 disk cycle for edge*/
		ok = BME_disk_hasedge(e->v2,e);
		if(!ok) VHALT(halt);
	}
	
	for(e=bm->edges.first; e; e=e->next) e->tflag2 = 0; //store incident faces
	/*Validate the loop cycle integrity.*/
	for(f=bm->polys.first; f; f=f->next){
		ok = BME_cycle_length(f->loopbase);
		if(ok > 1){
			f->tflag1 = ok;
		}
		else VHALT(halt);
		for(i=0, l=f->loopbase; i < f->tflag1; i++, l=l->next){
			/*verify loop->v pointers*/
			ok = BME_verts_in_edge(l->v, l->next->v, l->e);
			if(!ok) VHALT(halt);
			/*verify radial node data pointer*/
			if(l->radial.data != l) VHALT(halt);
			/*validate l->e->loop poitner*/
			if(l->e->loop == NULL) VHALT(halt);
			/*validate l->f pointer*/
			if(l->f != f) VHALT(halt);
			/*see if l->e->loop is actually in radial cycle*/
			
			l->e->tflag2++;
		 }
	}
	
	/*validate length of radial cycle*/
	for(e=bm->edges.first; e; e=e->next){
		if(e->loop){
			ok = BME_cycle_validate(e->tflag2,&(e->loop->radial));
			if(!ok) VHALT(halt);
		}
	}
	
	/*validate that EIDs are within range... if not indicates corrupted mem*/

	/*if we get this far, pretty safe to return 1*/
	return 1;
}
/**
 *			BME_bevel_initialize
 *
 *	Prepare the mesh for beveling:
 *
 *	Sets the tflag1's of the mesh elements based on the options passed.
 *
 *	Returns -
 *  A BME_Mesh pointer to the BMesh passed as a parameter.
*/
static BME_Mesh *BME_bevel_initialize(BME_Mesh *bm, int options, int UNUSED(defgrp_index), float angle, BME_TransData_Head *td) {
	BME_Vert *v;
	BME_Edge *e;
	BME_Poly *f;
	BME_TransData *vtd;
	MDeformVert *dvert;
	MDeformWeight *dw;
	int len;
	float weight, threshold;

	/* vert pass */
	for (v=bm->verts.first; v; v=v->next) {
		dvert = NULL;
		dw = NULL;
		v->tflag1 = BME_BEVEL_ORIG;
		/* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if
		 * the vert is manifold (or is shared by only two edges - wire bevel)
		 * BME_BEVEL_SELECT is passed and the vert has v->flag&SELECT or
		 * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight
		 * BME_BEVEL_ANGLE is not passed
		 * BME_BEVEL_EWEIGHT is not passed
		 */
		/* originally coded, a vertex gets tagged with BME_BEVEL_NONMAN in this pass if
		 * the vert is loose, shared by multiple regions, or is shared by wire edges
		 * note: verts belonging to edges of open meshes are not tagged with BME_BEVEL_NONMAN
		 */
		/* originally coded, a vertex gets a transform weight set in this pass if
		 * BME_BEVEL_VWEIGHT is passed, and the vert has a defgrp and weight
		 */

		/* get disk cycle length */
		if (v->edge == NULL) {
			len = 0;
		}
		else {
			len = BME_cycle_length(BME_disk_getpointer(v->edge,v));
			/* we'll assign a default transform data to every vert (except the loose ones) */
			vtd = BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 0, -1, -1, NULL);
		}

		/* check for non-manifold vert */
		if (BME_is_nonmanifold_vert(bm,v)) {
			v->tflag1 |= BME_BEVEL_NONMAN;
		}

		/* BME_BEVEL_BEVEL tests */
		if ((v->tflag1 & BME_BEVEL_NONMAN) == 0 || len == 2) { /* either manifold vert, or wire vert */
			if (((options & BME_BEVEL_SELECT) && (v->flag & SELECT))
				|| ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT)) /* use weights for verts */
				|| ((options & BME_BEVEL_ANGLE) == 0
					&& (options & BME_BEVEL_SELECT) == 0
					&& (options & BME_BEVEL_WEIGHT) == 0))
			{
				if (options & BME_BEVEL_WEIGHT) {
					/* do vert weight stuff */
					//~ dvert = CustomData_em_get(&bm->vdata,v->data,CD_MDEFORMVERT);
					//~ if (!dvert) continue;
					//~ for (i = 0; i < dvert->totweight; ++i) {
						//~ if(dvert->dw[i].def_nr == defgrp_index) {
							//~ dw = &dvert->dw[i];
							//~ break;
						//~ }
					//~ }
					//~ if (!dw || dw->weight == 0.0) continue;
					if (v->bweight == 0.0) continue;
					vtd = BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, v->bweight, -1, NULL);
					v->tflag1 |= BME_BEVEL_BEVEL;
				}
				else {
					vtd = BME_assign_transdata(td, bm, v, v->co, v->co, NULL, NULL, 1.0, 1.0, -1, NULL);
					v->tflag1 |= BME_BEVEL_BEVEL;
				}
			}
		}
	}

	/* edge pass */
	threshold = (float)cos((angle + 0.001) * M_PI / 180.0);
	for (e=bm->edges.first; e; e=e->next) {
		e->tflag1 = BME_BEVEL_ORIG;
		weight = 0.0;
		/* originally coded, an edge gets tagged with BME_BEVEL_BEVEL in this pass if
		 * BME_BEVEL_VERT is not set
		 * the edge is manifold (shared by exactly two faces)
		 * BME_BEVEL_SELECT is passed and the edge has e->flag&SELECT or
		 * BME_BEVEL_EWEIGHT is passed, and the edge has the crease set or
		 * BME_BEVEL_ANGLE is passed, and the edge is sharp enough
		 * BME_BEVEL_VWEIGHT is passed, and both verts are set for bevel
		 */
		/* originally coded, a vertex gets tagged with BME_BEVEL_BEVEL in this pass if
		 * the vert belongs to the edge
		 * the vert is not tagged with BME_BEVEL_NONMAN
		 * the edge is eligible for bevel (even if BME_BEVEL_VERT is set, or the edge is shared by less than 2 faces)
		 */
		/* originally coded, a vertex gets a transform weight set in this pass if
		 * the vert belongs to the edge
		 * the edge has a weight
		 */
		/* note: edge weights are cumulative at the verts,
		 * i.e. the vert's weight is the average of the weights of its weighted edges
		 */

		if (e->loop == NULL) {
			len = 0;
			e->v1->tflag1 |= BME_BEVEL_NONMAN;
			e->v2->tflag1 |= BME_BEVEL_NONMAN;
		}
		else {
			len = BME_cycle_length(&(e->loop->radial));
		}

		if (len > 2) {
			/* non-manifold edge of the worst kind */
			continue;
		}

		if ((options & BME_BEVEL_SELECT) && (e->flag & SELECT)) {
			weight = 1.0;
			/* stupid editmode doesn't always flush selections, or something */
			e->v1->flag |= SELECT;
			e->v2->flag |= SELECT;
		}
		else if ((options & BME_BEVEL_WEIGHT) && (options & BME_BEVEL_VERT) == 0) {
			weight = e->bweight;
		}
		else if (options & BME_BEVEL_ANGLE) {
			if ((e->v1->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v1) < threshold) {
				e->tflag1 |= BME_BEVEL_BEVEL;
				e->v1->tflag1 |= BME_BEVEL_BEVEL;
				BME_bevel_add_vweight(td, bm, e->v1, 1.0, 1.0, options);
			}
			else {
				BME_bevel_add_vweight(td, bm, e->v1, 0.0, 1.0, options);
			}
			if ((e->v2->tflag1 & BME_BEVEL_NONMAN) == 0 && BME_bevel_get_angle(bm,e,e->v2) < threshold) {
				e->tflag1 |= BME_BEVEL_BEVEL;
				e->v2->tflag1 |= BME_BEVEL_BEVEL;
				BME_bevel_add_vweight(td, bm, e->v2, 1.0, 1.0, options);
			}
			else {
				BME_bevel_add_vweight(td, bm, e->v2, 0.0, 1.0, options);
			}
		}
		//~ else if ((options & BME_BEVEL_VWEIGHT) && (options & BME_BEVEL_VERT) == 0) {
			//~ if ((e->v1->tflag1 & BME_BEVEL_BEVEL) && (e->v2->tflag1 & BME_BEVEL_BEVEL)) {
				//~ e->tflag1 |= BME_BEVEL_BEVEL;
			//~ }
		//~ }
		else if ((options & BME_BEVEL_SELECT) == 0
			&& (options & BME_BEVEL_VERT) == 0)
		{
			weight = 1.0;
		}

		if (weight > 0.0) {
			e->tflag1 |= BME_BEVEL_BEVEL;
			BME_bevel_add_vweight(td, bm, e->v1, weight, 1.0, options);
			BME_bevel_add_vweight(td, bm, e->v2, weight, 1.0, options);
		}

		if (len != 2 || options & BME_BEVEL_VERT) {
			e->tflag1 &= ~BME_BEVEL_BEVEL;
		}
	}

	/* face pass */
	for (f=bm->polys.first; f; f=f->next) f->tflag1 = BME_BEVEL_ORIG;

	/*clean up edges with 2 faces that share more than one edge*/
	for (e=bm->edges.first; e; e=e->next){
		if(e->tflag1 & BME_BEVEL_BEVEL){
			int count = 0;
			count = BME_face_sharededges(e->loop->f, ((BME_Loop*)e->loop->radial.next->data)->f);
			if(count > 1){
				e->tflag1 &= ~BME_BEVEL_BEVEL;
			}	
		}
	}

	return bm;
}
static BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int res, int options, int UNUSED(defgrp_index), BME_TransData_Head *td) {
	BME_Vert *v, *nv;
	BME_Edge *e, *oe;
	BME_Loop *l, *l2;
	BME_Poly *f;
	unsigned int i, len;

	for (f=bm->polys.first; f; f=f->next) {
		if(f->tflag1 & BME_BEVEL_ORIG) {
			BME_bevel_poly(bm,f,value,options,td);
		}
	}

	/* here we will loop through all the verts to clean up the left over geometry */
	/* crazy idea. when res == 0, don't remove the original geometry */
	for (v = bm->verts.first; v; /* we may kill v, so increment in-loop */) {
		nv = v->next;
		if ((v->tflag1 & BME_BEVEL_NONMAN) && (v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG)) {
			v = BME_bevel_wire(bm, v, value, res, options, td);
		}
		else if (res && ((v->tflag1 & BME_BEVEL_BEVEL) && (v->tflag1 & BME_BEVEL_ORIG))) {
			int count = 0;
			/* first, make sure we're not sitting on an edge to be removed */
			oe = v->edge;
			e = BME_disk_nextedge(oe,v);
			while ((e->tflag1 & BME_BEVEL_BEVEL) && (e->tflag1 & BME_BEVEL_ORIG)) {
				e = BME_disk_nextedge(e,v);
				if (e == oe) {
					//printf("Something's wrong! We can't remove every edge here!\n");
					break;
				}
			}
			/* look for original edges, and remove them */
			oe = e;
			while ( (e = BME_disk_next_edgeflag(oe, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) ) {
				count++;
				/* join the faces (we'll split them later) */
				f = BME_JFKE_safe(bm,e->loop->f,((BME_Loop*)e->loop->radial.next->data)->f,e);
				if (!f){
					//printf("Non-manifold geometry not getting tagged right?\n");
				}
			}

			/*need to do double check *before* you bevel to make sure that manifold edges are for two faces that share only *one* edge to make sure it doesnt hang here!*/


			/* all original edges marked to be beveled have been removed;
			 * now we need to link up the edges for this "corner" */
			len = BME_cycle_length(BME_disk_getpointer(v->edge, v));
			for (i=0,e=v->edge; i < len; i++,e=BME_disk_nextedge(e,v)) {
				l = e->loop;
				l2 = l->radial.next->data;
				if (l->v != v) l = l->next;
				if (l2->v != v) l2 = l2->next;
				/* look for faces that have had the original edges removed via JFKE */
				if (l->f->len > 3) {
					BME_split_face(bm,l->f,l->next->v,l->prev->v,&l,l->e); /* clip this corner off */
					if (len > 2) {
						l->e->tflag1 |= BME_BEVEL_BEVEL;
					}
				}
				if (l2->f->len > 3) {
					BME_split_face(bm,l2->f,l2->next->v,l2->prev->v,&l,l2->e); /* clip this corner off */
					if (len > 2) {
						l->e->tflag1 |= BME_BEVEL_BEVEL;
					}
				}
			}
			bmesh_dissolve_disk(bm, v);
		}
		v = nv;
	}

	return bm;
}