[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [44704] trunk/blender/source/blender: Knifetool uses direct cutting instead of scanfill: fixes bugs 29908, 28963 , 30333.

Howard Trickey howard.trickey at gmail.com
Wed Mar 7 15:44:50 CET 2012


Revision: 44704
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=44704
Author:   howardt
Date:     2012-03-07 14:44:43 +0000 (Wed, 07 Mar 2012)
Log Message:
-----------
Knifetool uses direct cutting instead of scanfill: fixes bugs 29908, 28963, 30333.

Knifetool accumulates a bunch of proposed cuts and when the user
confirms, it makes them all. The old code did this by using scanfill
to triangulate the cutting edges in their faces, and then merging
triangles where possible. This sometimes ended up with strange
lost faces, and also made it so that when holes were cut, the
surrounding face ended up totally triangulated. But 29908 was
an example of a lost face.

This new code directly finds chains of cutting edges that go from
one side of a face to the other and using BM_edge_split_n to make
the cuts. Holes are handled by finding two good places where
the hole can be connected to the containing face (using two
because I think some other code in bmesh assumes that there are
no edges that appear twice in a face).

The old code is still there with #if SCANFILL_CUTS, so can easily revert
if this proves to be a bad idea.

Also, a small fix to previously added BM_split_n (forgot to
copy face attributes to new face).

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_mods.c
    trunk/blender/source/blender/editors/mesh/knifetool.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_mods.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_mods.c	2012-03-07 13:35:32 UTC (rev 44703)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_mods.c	2012-03-07 14:44:43 UTC (rev 44704)
@@ -417,6 +417,9 @@
 	 * The radial_next is for f and goes from v2 to v1  */
 
 	if (nf) {
+		BM_elem_attrs_copy(bm, bm, f, nf);
+		copy_v3_v3(nf->no, f->no);
+
 		e = (*r_l)->e;
 		for (i = 0; i < n; i++) {
 			newv = bmesh_semv(bm, v2, e, &newe);

Modified: trunk/blender/source/blender/editors/mesh/knifetool.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/knifetool.c	2012-03-07 13:35:32 UTC (rev 44703)
+++ trunk/blender/source/blender/editors/mesh/knifetool.c	2012-03-07 14:44:43 UTC (rev 44704)
@@ -198,6 +198,18 @@
 	BLI_addtail(lst, ref);
 }
 
+static Ref *find_ref(ListBase *lb, void *ref)
+{
+	Ref *ref1;
+
+	for (ref1 = lb->first; ref1; ref1 = ref1->next) {
+		if (ref1->ref == ref)
+			return ref1;
+	}
+
+	return NULL;
+}
+
 static KnifeEdge *new_knife_edge(knifetool_opdata *kcd)
 {
 	kcd->totkedge++;
@@ -213,9 +225,9 @@
 static KnifeVert *new_knife_vert(knifetool_opdata *kcd, float *co, float *cageco)
 {
 	KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
-	
+
 	kcd->totkvert++;
-	
+
 	copy_v3_v3(kfv->co, co);
 	copy_v3_v3(kfv->cageco, cageco);
 	copy_v3_v3(kfv->sco, co);
@@ -229,13 +241,13 @@
 static KnifeVert *get_bm_knife_vert(knifetool_opdata *kcd, BMVert *v)
 {
 	KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
-	
+
 	if (!kfv) {
 		kfv = new_knife_vert(kcd, v->co, kcd->cagecos[BM_elem_index_get(v)]);
 		kfv->v = v;
 		BLI_ghash_insert(kcd->origvertmap, v, kfv);
 	}
-	
+
 	return kfv;
 }
 
@@ -246,7 +258,7 @@
 	if (!kfe) {
 		BMIter iter;
 		BMFace *f;
-		
+	
 		kfe = new_knife_edge(kcd);
 		kfe->e = e;
 		kfe->v1 = get_bm_knife_vert(kcd, e->v1);
@@ -264,7 +276,7 @@
 			knife_get_face_kedges(kcd, f);
 		}
 	}
-	
+
 	return kfe;
 }
 
@@ -278,7 +290,7 @@
 	kcd->is_space = 0;
 	kcd->prevmval[0] = kcd->vc.mval[0];
 	kcd->prevmval[1] = kcd->vc.mval[1];
-	
+
 	copy_v3_v3(kcd->prevco, kcd->vertco);
 	copy_v3_v3(kcd->prevcage, kcd->vertcage);
 
@@ -299,35 +311,23 @@
 	}
 }
 
-static Ref *find_ref(ListBase *lb, void *ref)
-{
-	Ref *ref1;
-	
-	for (ref1 = lb->first; ref1; ref1 = ref1->next) {
-		if (ref1->ref == ref)
-			return ref1;
-	}
-	
-	return NULL;
-}
-
 static ListBase *knife_get_face_kedges(knifetool_opdata *kcd, BMFace *f)
 {
 	ListBase *lst = BLI_ghash_lookup(kcd->kedgefacemap, f);
-	
+
 	if (!lst) {
 		BMIter iter;
 		BMEdge *e;
-		
+
 		lst = knife_empty_list(kcd);
 		
 		BM_ITER(e, &iter, kcd->em->bm, BM_EDGES_OF_FACE, f) {
 			knife_append_list(kcd, lst, get_bm_knife_edge(kcd, e));
 		}
-		
+
 		BLI_ghash_insert(kcd->kedgefacemap, f, lst);
 	}
-	
+
 	return lst;
 }
 
@@ -336,7 +336,7 @@
 {
 	if (!kfe->basef) {
 		Ref *r1, *r2, *r3, *r4;
-		
+
 		if (kfe->v1->isface || kfe->v2->isface) {
 			if (kfe->v2->isface)
 				kfe->basef = kcd->curbmface;
@@ -373,69 +373,69 @@
 {
 	KnifeEdge *newkfe = new_knife_edge(kcd);
 	Ref *ref;
-	float perc, cageco[3];
-	
-	perc = len_v3v3(co, kfe->v1->co) / len_v3v3(kfe->v1->co, kfe->v2->co);
-	interp_v3_v3v3(cageco, kfe->v1->cageco, kfe->v2->cageco, perc);
-	
+	float perc, cageco[3], l12;
+
+	l12 = len_v3v3(kfe->v1->co, kfe->v2->co);
+	if (l12 < FLT_EPSILON * 80) {
+		copy_v3_v3(cageco, kfe->v1->cageco);
+	} else {
+		perc = len_v3v3(co, kfe->v1->co) / l12;
+		interp_v3_v3v3(cageco, kfe->v1->cageco, kfe->v2->cageco, perc);
+	}
+
 	newkfe->v1 = kfe->v1;
 	newkfe->v2 = new_knife_vert(kcd, co, cageco);
 	newkfe->v2->draw = 1;
 	newkfe->basef = kfe->basef;
-	
+
 	ref = find_ref(&kfe->v1->edges, kfe);
 	BLI_remlink(&kfe->v1->edges, ref);
-	
+
 	kfe->v1 = newkfe->v2;
 	BLI_addtail(&kfe->v1->edges, ref);
-	
+
 	for (ref = kfe->faces.first; ref; ref = ref->next)
 		knife_edge_append_face(kcd, newkfe, ref->ref);
 
 	knife_add_to_vert_edges(kcd, newkfe);
-	
+
 	newkfe->draw = kfe->draw;
 	newkfe->e = kfe->e;
-	
+
 	*newkfe_out = newkfe;
-			
+
 	return newkfe->v2;
 }
 
 static void knife_add_single_cut(knifetool_opdata *kcd)
 {
 	KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL;
-	
+
 	if (kcd->prevvert && kcd->prevvert == kcd->curvert)
 		return;
 	if (kcd->prevedge && kcd->prevedge == kcd->curedge)
 		return;
-	
+
 	kfe->draw = 1;
 
 	if (kcd->prevvert) {
 		kfe->v1 = kcd->prevvert;
-	}
-	else if (kcd->prevedge) {
+	} else if (kcd->prevedge) {
 		kfe->v1 = knife_split_edge(kcd, kcd->prevedge, kcd->prevco, &kfe2);
-	}
-	else {
+	} else {
 		kfe->v1 = new_knife_vert(kcd, kcd->prevco, kcd->prevco);
 		kfe->v1->draw = kfe->draw = !kcd->prev_is_space;
 		kfe->v1->inspace = kcd->prev_is_space;
 		kfe->draw = !kcd->prev_is_space;
 		kfe->v1->isface = 1;
 	}
-	
+
 	if (kcd->curvert) {
 		kfe->v2 = kcd->curvert;
-	}
-	else if (kcd->curedge) {
+	} else if (kcd->curedge) {
 		kfe->v2 = knife_split_edge(kcd, kcd->curedge, kcd->vertco, &kfe3);
-	
 		kcd->curvert = kfe->v2;
-	}
-	else {
+	} else {
 		kfe->v2 = new_knife_vert(kcd, kcd->vertco, kcd->vertco);
 		kfe->v2->draw = !kcd->is_space;
 		kfe->v2->isface = 1;
@@ -446,11 +446,11 @@
 
 		kcd->curvert = kfe->v2;
 	}
-	
+
 	knife_find_basef(kcd, kfe);
-	
+
 	knife_add_to_vert_edges(kcd, kfe);
-	
+
 	if (kfe->basef && !find_ref(&kfe->faces, kfe->basef))
 		knife_edge_append_face(kcd, kfe, kfe->basef);
 
@@ -466,7 +466,7 @@
 			}
 		}
 	}
-		
+
 	/* set up for next cut */
 	kcd->prevbmface = kcd->curbmface;
 	kcd->prevvert = kcd->curvert;
@@ -657,29 +657,26 @@
 
 static void knife_add_cut(knifetool_opdata *kcd)
 {
-	/* BMEditMesh *em = kcd->em;*/ /* UNUSED */
 	knifetool_opdata oldkcd = *kcd;
-	
+
 	if (kcd->cut_through) {
 		knife_cut_through(kcd);
-	}
-	else if (kcd->linehits) {
+	} else if (kcd->linehits) {
 		BMEdgeHit *lh, *lastlh, *firstlh;
 		int i;
-		
+
 		qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
-		
+
 		lh = kcd->linehits;
 		lastlh = firstlh = NULL;
 		for (i = 0; i < kcd->totlinehit; i++, (lastlh = lh), lh++) {
 			BMFace *f = lastlh ? lastlh->f : lh->f;
-			
+
 			if (lastlh && len_v3v3(lastlh->hit, lh->hit) == 0.0f) {
 				if (!firstlh)
 					firstlh = lastlh;
 				continue;
-			}
-			else if (lastlh && firstlh) {
+			} else if (lastlh && firstlh) {
 				if (firstlh->v || lastlh->v) {
 					KnifeVert *kfv = firstlh->v ? firstlh->v : lastlh->v;
 					
@@ -691,21 +688,22 @@
 				}
 				lastlh = firstlh = NULL;
 			}
-			
+
 			if (len_v3v3(kcd->prevcage, lh->realhit) < FLT_EPSILON * 80)
 				continue;
 			if (len_v3v3(kcd->vertcage, lh->realhit) < FLT_EPSILON * 80)
 				continue;
-			
+
 			if (kcd->prev_is_space) {
 				kcd->prev_is_space = 0;
 				copy_v3_v3(kcd->prevco, lh->hit);
 				copy_v3_v3(kcd->prevcage, lh->cagehit);
+				kcd->prevvert = NULL;
 				kcd->prevedge = lh->kfe;
 				kcd->prevbmface = lh->f;
 				continue;
 			}			
-			
+
 			kcd->is_space = 0;
 			kcd->curedge = lh->kfe;
 			kcd->curbmface = lh->f;
@@ -715,7 +713,7 @@
 
 			knife_add_single_cut(kcd);
 		}
-		
+
 		if (oldkcd.is_space) {
 			kcd->prevbmface = oldkcd.curbmface;
 			kcd->prevvert = oldkcd.curvert;
@@ -730,10 +728,10 @@
 			kcd->is_space = oldkcd.is_space;
 			copy_v3_v3(kcd->vertco, oldkcd.vertco);
 			copy_v3_v3(kcd->vertcage, oldkcd.vertcage);
-			
+		
 			knife_add_single_cut(kcd);
 		}
-		
+
 		MEM_freeN(kcd->linehits);
 		kcd->linehits = NULL;
 		kcd->totlinehit = 0;
@@ -991,30 +989,6 @@
 	glEnable(GL_DEPTH_TEST);
 }
 
-/* do we need to keep these functions? - campbell */
-
-static int UNUSED_FUNCTION(kfe_vert_in_edge)(KnifeEdge *e, KnifeVert *v)
-{
-	return e->v1 == v || e->v2 == v;
-}
-
-static int UNUSED_FUNCTION(point_on_line)(float p[3], float v1[3], float v2[3])
-{
-	float d = dist_to_line_segment_v3(p, v1, v2);
-	if (d < 0.01) {
-		d = len_v3v3(v1, v2);
-		if (d == 0.0)
-			return 0;
-		
-		d = len_v3v3(p, v1) / d;
-		
-		if (d >= -FLT_EPSILON * 10 || d <= 1.0 + FLT_EPSILON * 10)
-			return 1;
-	}
-	
-	return 0;
-}
-
 static float len_v3_tri_side_max(const float v1[3], const float v2[3], const float v3[3])
 {
 	const float s1 = len_v3v3(v1, v2);
@@ -1181,36 +1155,36 @@
 	SmallHash hash, *ehash = &hash;
 	float v1[3], v2[3], v3[3], v4[4], s1[3], s2[3];
 	int i, c1, c2;
-		
+	
 	knife_bgl_get_mats(kcd, &mats);
-	
+
 	if (kcd->linehits) {
 		MEM_freeN(kcd->linehits);
 		kcd->linehits = NULL;
 		kcd->totlinehit = 0;
 	}
-	
+
 	copy_v3_v3(v1, kcd->prevcage);
 	copy_v3_v3(v2, kcd->vertcage);
-	
+
 	/* project screen line's 3d coordinates back into 2d */
 	knife_project_v3(kcd, v1, s1);
 	knife_project_v3(kcd, v2, s2);
-	
+
 	if (len_v2v2(s1, s2) < 1)
 		return;
 
 	/* unproject screen line */
 	ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s1, v1, v3);
 	ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s2, v2, v4);
-		
+
 	mul_m4_v3(kcd->ob->imat, v1);
 	mul_m4_v3(kcd->ob->imat, v2);
 	mul_m4_v3(kcd->ob->imat, v3);
 	mul_m4_v3(kcd->ob->imat, v4);
-	
+
 	BLI_smallhash_init(ehash);
-	
+
 	/* test two triangles of sceen line's plane */
 	e1 = knife_edge_tri_isect(kcd, kcd->bmbvh, v1, v2, v3, ehash, &mats, &c1);
 	e2 = knife_edge_tri_isect(kcd, kcd->bmbvh, v2, v3, v4, ehash, &mats, &c2);
@@ -1222,17 +1196,17 @@
 	else if (c2) {
 		e1 = e2;
 	}
-	
+
 	kcd->linehits = e1;
 	kcd->totlinehit = c1 + c2;
 
 	/* find position along screen line, used for sorting */
 	for (i = 0; i < kcd->totlinehit; i++) {
 		BMEdgeHit *lh = e1 + i;
-		
+
 		lh->l = len_v2v2(lh->schit, s1) / len_v2v2(s2, s1);
 	}
-	
+
 	BLI_smallhash_release(ehash);
 }
 
@@ -1569,12 +1543,12 @@
 		knife_snap_angle(kcd);
 
 	kcd->curvert = NULL; kcd->curedge = NULL; kcd->curbmface = NULL;
-	
+
 	kcd->curvert = knife_find_closest_vert(kcd, kcd->vertco, kcd->vertcage, &kcd->curbmface, &kcd->is_space);
 	if (!kcd->curvert) {
 		kcd->curedge = knife_find_closest_edge(kcd, kcd->vertco, kcd->vertcage, &kcd->curbmface, &kcd->is_space);
 	}
-	
+
 	/* if no hits are found this would normally default to (0,0,0) so instead
 	 * get a point at the mouse ray closest to the previous point.
 	 * Note that drawing lines in `free-space` isn't properly supported
@@ -1602,6 +1576,9 @@
 #define BOUNDARY		128
 #define FACE_NEW		256
 
+#define SCANFILL_CUTS 0
+#if SCANFILL_CUTS
+
 typedef struct facenet_entry {
 	struct facenet_entry *next, *prev;
 	KnifeEdge *kfe;
@@ -1952,12 +1929,612 @@
 	BMO_pop(bm);
 }
 
+#else  /* use direct (non-scanfill) method for cuts */
+
+/* assuming v is on line ab, what fraction of the way is v from a to b? */
+static float frac_along(const float a[3], const float b[3], const float v[3]) {
+	float lab;
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list