[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [40503] branches/bmesh/blender/source/ blender/bmesh/intern: Port jfke and jekv euler functions to new bmesh structures

Andrew Wiggin ender79bl at gmail.com
Fri Sep 23 16:38:46 CEST 2011


Revision: 40503
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=40503
Author:   ender79
Date:     2011-09-23 14:38:45 +0000 (Fri, 23 Sep 2011)
Log Message:
-----------
Port jfke and jekv euler functions to new bmesh structures

Modified Paths:
--------------
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_private.h
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_structure.c
    branches/bmesh/blender/source/blender/bmesh/intern/bmesh_structure.h

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c
===================================================================
--- branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c	2011-09-23 14:09:26 UTC (rev 40502)
+++ branches/bmesh/blender/source/blender/bmesh/intern/bmesh_newcore.c	2011-09-23 14:38:45 UTC (rev 40503)
@@ -1035,16 +1035,16 @@
 	BMLoop *nextl;
 	BMEdge *ne;
 	BMVert *nv, *ov;
-	int i, edok, valance1=0, valance2=0;
+	int i, edok, valence1=0, valence2=0;
 
 	if(bmesh_vert_in_edge(e,tv) == 0) return NULL;
 	ov = bmesh_edge_getothervert(e,tv);
 
-	/*count valance of v1*/
-	valance1 = bmesh_disk_count(ov);
+	/*count valence of v1*/
+	valence1 = bmesh_disk_count(ov);
 
-	/*count valance of v2*/
-	valance2 = bmesh_disk_count(tv);
+	/*count valence of v2*/
+	valence2 = bmesh_disk_count(tv);
 
 	nv = BM_Make_Vert(bm, tv->co, tv);
 	ne = BM_Make_Edge(bm, nv, tv, e, 0);
@@ -1068,9 +1068,9 @@
 	bmesh_disk_append_edge(ne, tv);
 
 	/*verify disk cycles*/
-	edok = bmesh_disk_validate(valance1, ov->e, ov);
+	edok = bmesh_disk_validate(valence1, ov->e, ov);
 	if(!edok) bmesh_error();
-	edok = bmesh_disk_validate(valance2, tv->e, tv);
+	edok = bmesh_disk_validate(valence2, tv->e, tv);
 	if(!edok) bmesh_error();
 	edok = bmesh_disk_validate(2, nv->e, nv);
 	if(!edok) bmesh_error();
@@ -1178,9 +1178,296 @@
 
 	CHECK_ELEMENT(bm, ne);
 	CHECK_ELEMENT(bm, nv);
+	CHECK_ELEMENT(bm, ov);
 	CHECK_ELEMENT(bm, e);
 	CHECK_ELEMENT(bm, tv);
 
 	if(re) *re = ne;
 	return nv;
 }
+
+/**
+ *			bmesh_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 bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv)
+{
+	BMEdge *oe;
+	BMVert *ov, *tv;
+	BMLoop *killoop, *l;
+	int len,radlen=0, halt = 0, i, valence1, valence2,edok;
+	BMLoop **loops = NULL;
+	BLI_array_staticdeclare(loops, 256);
+
+	if(bmesh_vert_in_edge(ke,kv) == 0) return 0;
+	len = bmesh_disk_count(kv);
+	
+	if(len == 2){
+		oe = bmesh_disk_nextedge(ke, kv);
+		tv = bmesh_edge_getothervert(ke, kv);
+		ov = bmesh_edge_getothervert(oe, kv);		
+		halt = bmesh_verts_in_edge(kv, tv, oe); /*check for double edges*/
+		
+		if(halt) return 0;
+		else{
+			/*For verification later, count valence of ov and tv*/
+			valence1 = bmesh_disk_count(ov);
+			valence2 = bmesh_disk_count(tv);
+			
+			/*remove oe from kv's disk cycle*/
+			bmesh_disk_remove_edge(oe,kv);
+			/*relink oe->kv to be oe->tv*/
+			bmesh_edge_swapverts(oe, kv, tv);
+			/*append oe to tv's disk cycle*/
+			bmesh_disk_append_edge(oe, tv);
+			/*remove ke from tv's disk cycle*/
+			bmesh_disk_remove_edge(ke, tv);
+		
+			/*deal with radial cycle of ke*/
+			radlen = bmesh_radial_length(ke->l);
+			if(ke->l){
+				/*first step, fix the neighboring loops of all loops in ke's radial cycle*/
+				for(i=0,killoop = ke->l; i<radlen; i++, killoop = bmesh_radial_nextloop(killoop)){
+					/*relink loops and fix vertex pointer*/
+					if( killoop->next->v == kv ) killoop->next->v = tv;
+
+					killoop->next->prev = killoop->prev;
+					killoop->prev->next = killoop->next;
+					if (bm_firstfaceloop(killoop->f) == killoop)
+						bm_firstfaceloop(killoop->f) = killoop->next;
+					killoop->next = NULL;
+					killoop->prev = NULL;
+
+					/*fix len attribute of face*/
+					killoop->f->len--;
+				}
+				/*second step, remove all the hanging loops attached to ke*/
+				killoop = ke->l;
+				radlen = bmesh_radial_length(ke->l);
+				/*this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well...*/
+				for (i=0;i<radlen;i++) {
+					BLI_array_growone(loops);
+					loops[BLI_array_count(loops)-1] = killoop;
+					killoop = bmesh_radial_nextloop(killoop);
+				}
+				for (i=0;i<radlen;i++) {
+					bm->totloop--;
+					BLI_mempool_free(bm->lpool, loops[i]);
+				}
+				/*Validate radial cycle of oe*/
+				edok = bmesh_radial_validate(radlen,oe->l);
+				if(!edok) bmesh_error();
+			}
+
+			/*deallocate edge*/
+			BM_remove_selection(bm, ke);
+			BLI_mempool_free(bm->toolflagpool, ke->head.flags);
+			BLI_mempool_free(bm->epool, ke);
+			bm->totedge--;
+			/*deallocate vertex*/
+			BM_remove_selection(bm, kv);
+			BLI_mempool_free(bm->toolflagpool, kv->head.flags);
+			BLI_mempool_free(bm->vpool, kv);
+			bm->totvert--;
+
+			/*Validate disk cycle lengths of ov,tv are unchanged*/
+			edok = bmesh_disk_validate(valence1, ov->e, ov);
+			if(!edok) bmesh_error();
+			edok = bmesh_disk_validate(valence2, tv->e, tv);
+			if(!edok) bmesh_error();
+
+			/*Validate loop cycle of all faces attached to oe*/
+			for(i=0,l = oe->l; i<radlen; i++, l = bmesh_radial_nextloop(l)){
+				if(l->e != oe) bmesh_error();
+				edok = bmesh_verts_in_edge(l->v, l->next->v, oe);
+				if(!edok) bmesh_error();
+				edok = bmesh_loop_validate(l->f);
+				if(!edok) bmesh_error();
+
+				CHECK_ELEMENT(bm, l);
+				CHECK_ELEMENT(bm, l->v);
+				CHECK_ELEMENT(bm, l->e);
+				CHECK_ELEMENT(bm, l->f);
+			}
+
+			CHECK_ELEMENT(bm, ov);
+			CHECK_ELEMENT(bm, tv);
+			CHECK_ELEMENT(bm, oe);
+
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/**
+ *			bmesh_JFKE
+ *
+ *	JOIN FACE KILL EDGE:
+ *	
+ *	Takes two faces joined by a single 2-manifold edge and fuses them togather.
+ *	The edge shared by the faces must not be connected to any other edges which have
+ *	Both faces in its radial cycle
+ *
+ *	Examples:
+ *	
+ *        A                   B
+ *	 ----------           ----------
+ *	 |		  |           |        | 
+ *	 |   f1   |           |   f1   |
+ *	v1========v2 = Ok!    v1==V2==v3 == Wrong!
+ *	 |   f2   |           |   f2   |
+ *	 |        |           |        |
+ *	 ----------           ---------- 
+ *
+ *	In the example A, faces f1 and f2 are joined by a single edge, and the euler can safely be used.
+ *	In example B however, f1 and f2 are joined by multiple edges and will produce an error. The caller
+ *	in this case should call bmesh_JEKV on the extra edges before attempting to fuse f1 and f2.
+ *
+ *	Also note that the order of arguments decides whether or not certain per-face attributes are present
+ *	in the resultant face. For instance vertex winding, material index, smooth flags, ect are inherited
+ *	from f1, not f2.
+ *
+ *  Returns -
+ *	A BMFace pointer
+*/
+BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e)
+{
+	BMLoop *curloop, *f1loop=NULL, *f2loop=NULL;
+	int loopok = 0, newlen = 0,i, f1len=0, f2len=0, radlen=0, edok, shared;
+	BMIter iter;
+
+	/*can't join a face to itself*/
+	if(f1 == f2) return NULL;
+	/*verify that e is in both f1 and f2*/
+	f1len = f1->len;
+	f2len = f2->len;
+	BM_ITER(curloop, &iter, bm, BM_LOOPS_OF_FACE, f1) {
+		if(curloop->e == e){ 
+			f1loop = curloop;
+			break;
+		}
+	}
+	BM_ITER(curloop, &iter, bm, BM_LOOPS_OF_FACE, f2) {
+		if(curloop->e == e){
+			f2loop = curloop;
+			break;
+		}
+	}
+	if (!(f1loop && f2loop)) return NULL;
+	
+	/*validate that edge is 2-manifold edge*/
+	radlen = bmesh_radial_length(f1loop);
+	if(radlen != 2) return NULL;
+
+	/*validate direction of f2's loop cycle is compatible.*/
+	if(f1loop->v == f2loop->v) return NULL;
+	
+	/*
+		validate that for each face, each vertex has another edge in its disk cycle that is 
+		not e, and not shared.
+	*/
+	if(bmesh_radial_find_face(f1loop->next->e,f2)) return NULL;
+	if(bmesh_radial_find_face(f1loop->prev->e,f2)) return NULL;
+	if(bmesh_radial_find_face(f2loop->next->e,f1)) return NULL;
+	if(bmesh_radial_find_face(f2loop->prev->e,f1)) return NULL;
+	
+	/*validate only one shared edge*/
+	shared = BM_Face_Sharededges(f1,f2);
+	if(shared > 1) return NULL;
+
+	/*validate no internal joins*/
+	for(i=0, curloop = bm_firstfaceloop(f1); i < f1len; i++, curloop = curloop->next)
+		bmesh_api_setindex(curloop->v, 0);
+	for(i=0, curloop = bm_firstfaceloop(f2); i < f2len; i++, curloop = curloop->next)
+		bmesh_api_setindex(curloop->v, 0);
+
+	for(i=0, curloop = bm_firstfaceloop(f1); i < f1len; i++, curloop = curloop->next) {
+		if (curloop != f1loop)
+			bmesh_api_setindex(curloop->v, bmesh_api_getindex(curloop->v) + 1);
+	}
+	for(i=0, curloop = bm_firstfaceloop(f2); i < f2len; i++, curloop = curloop->next) {
+		if (curloop != f2loop)
+			bmesh_api_setindex(curloop->v, bmesh_api_getindex(curloop->v) + 1);
+	}
+
+	for(i=0, curloop = bm_firstfaceloop(f1); i < f1len; i++, curloop = curloop->next) {
+		if (bmesh_api_getindex(curloop->v) > 1)
+			return NULL;
+	}
+	
+	for(i=0, curloop = bm_firstfaceloop(f2); i < f2len; i++, curloop = curloop->next) {
+		if (bmesh_api_getindex(curloop->v) > 1)
+			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, make f1loop->next the base.*/
+	if(bm_firstfaceloop(f1) == f1loop)
+		bm_firstfaceloop(f1) = f1loop->next;
+
+	/*increase length of f1*/
+	f1->len += (f2->len - 2);
+
+	/*make sure each loop points to the proper face*/
+	newlen = f1->len;
+	for(i = 0, curloop = bm_firstfaceloop(f1); i < newlen; i++, curloop = curloop->next)
+		curloop->f = f1;
+	
+	/*remove edge from the disk cycle of its two vertices.*/
+	bmesh_disk_remove_edge(f1loop->e, f1loop->e->v1);
+	bmesh_disk_remove_edge(f1loop->e, f1loop->e->v2);
+	
+	/*deallocate edge and its two loops as well as f2*/
+	BLI_mempool_free(bm->toolflagpool, f1loop->e->head.flags);
+	BLI_mempool_free(bm->epool, f1loop->e);
+	bm->totedge--;
+	BLI_mempool_free(bm->lpool, f1loop);
+	bm->totloop--;
+	BLI_mempool_free(bm->lpool, f2loop);
+	bm->totloop--;
+	BLI_mempool_free(bm->toolflagpool, f2->head.flags);
+	BLI_mempool_free(bm->fpool, f2);
+	bm->totface--;
+
+	CHECK_ELEMENT(bm, f1);
+
+	/*validate the new loop cycle*/
+	edok = bmesh_loop_validate(f1);
+	if(!edok) bmesh_error();
+	
+	return f1;
+}

Modified: branches/bmesh/blender/source/blender/bmesh/intern/bmesh_private.h

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list