[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [49307] trunk/blender/source/blender/ editors/mesh/editmesh_knife.c: Fixed some knife cut failures.

Howard Trickey howard.trickey at gmail.com
Fri Jul 27 22:12:31 CEST 2012


Revision: 49307
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=49307
Author:   howardt
Date:     2012-07-27 20:12:29 +0000 (Fri, 27 Jul 2012)
Log Message:
-----------
Fixed some knife cut failures.
Fixes #31391.  Some cases still fail but these
changes are good because they fix a bogus
calculation of the 'basef' of some cut segments.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/mesh/editmesh_knife.c

Modified: trunk/blender/source/blender/editors/mesh/editmesh_knife.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_knife.c	2012-07-27 19:38:31 UTC (rev 49306)
+++ trunk/blender/source/blender/editors/mesh/editmesh_knife.c	2012-07-27 20:12:29 UTC (rev 49307)
@@ -84,6 +84,7 @@
 typedef struct KnifeVert {
 	BMVert *v; /* non-NULL if this is an original vert */
 	ListBase edges;
+	ListBase faces;
 
 	float co[3], cageco[3], sco[3]; /* sco is screen coordinates for cageco */
 	short flag, draw, isface, inspace;
@@ -277,6 +278,32 @@
 	knife_append_list(kcd, &kfe->v2->edges, kfe);
 }
 
+/* Add faces of an edge to a KnifeVert's faces list.  No checks for dups. */
+static void knife_add_edge_faces_to_vert(KnifeTool_OpData *kcd, KnifeVert *kfv, BMEdge *e)
+{
+	BMIter bmiter;
+	BMFace *f;
+
+	BM_ITER_ELEM(f, &bmiter, e, BM_FACES_OF_EDGE) {
+		knife_append_list(kcd, &kfv->faces, f);
+	}
+}
+
+/* Find a face in common in the two faces lists.
+   If more than one, return the first; if none, return NULL */
+static BMFace* knife_find_common_face(ListBase *faces1, ListBase *faces2)
+{
+	Ref *ref1, *ref2;
+
+	for (ref1 = faces1->first; ref1; ref1 = ref1->next) {
+		for (ref2 = faces2->first; ref2; ref2 = ref2->next) {
+			if (ref1->ref == ref2->ref)
+				return (BMFace*)(ref1->ref);
+		}
+	}
+	return NULL;
+}
+
 static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], float *cageco)
 {
 	KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
@@ -298,9 +325,15 @@
 	KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
 
 	if (!kfv) {
+		BMIter bmiter;
+		BMFace *f;
+
 		kfv = new_knife_vert(kcd, v->co, kcd->cagecos[BM_elem_index_get(v)]);
 		kfv->v = v;
 		BLI_ghash_insert(kcd->origvertmap, v, kfv);
+		BM_ITER_ELEM(f, &bmiter, v, BM_FACES_OF_VERT) {
+			knife_append_list(kcd, &kfv->faces, f);
+		}
 	}
 
 	return kfv;
@@ -389,35 +422,9 @@
 }
 
 /* finds the proper face to restrict face fill to */
-static void knife_find_basef(KnifeTool_OpData *kcd, KnifeEdge *kfe)
+static void knife_find_basef(KnifeEdge *kfe)
 {
-	if (!kfe->basef) {
-		Ref *r1, *r2, *r3, *r4;
-
-		if (kfe->v1->isface || kfe->v2->isface) {
-			if (kfe->v2->isface)
-				kfe->basef = kcd->cur.bmface;
-			else
-				kfe->basef = kcd->prev.bmface;
-		}
-		else {
-			for (r1 = kfe->v1->edges.first; r1 && !kfe->basef; r1 = r1->next) {
-				KnifeEdge *ke1 = r1->ref;
-				for (r2 = ke1->faces.first; r2 && !kfe->basef; r2 = r2->next) {
-					for (r3 = kfe->v2->edges.first; r3 && !kfe->basef; r3 = r3->next) {
-						KnifeEdge *ke2 = r3->ref;
-
-						for (r4 = ke2->faces.first; r4 && !kfe->basef; r4 = r4->next) {
-							if (r2->ref == r4->ref) {
-								kfe->basef = r2->ref;
-							}
-						}
-					}
-				}
-			}
-		}
-		/* ok, at this point kfe->basef should be set if any valid possibility exists */
-	}
+	kfe->basef = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces);
 }
 
 static void knife_edge_append_face(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMFace *f)
@@ -430,6 +437,7 @@
 {
 	KnifeEdge *newkfe = new_knife_edge(kcd);
 	Ref *ref;
+	BMFace *f;
 	float perc, cageco[3], l12;
 
 	l12 = len_v3v3(kfe->v1->co, kfe->v2->co);
@@ -444,6 +452,16 @@
 	newkfe->v1 = kfe->v1;
 	newkfe->v2 = new_knife_vert(kcd, co, cageco);
 	newkfe->v2->draw = 1;
+	if (kfe->e) {
+		knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e);
+	} else {
+		/* kfe cuts across an existing face.
+		   If v1 and v2 are in multiple faces together (e.g., if they
+		   are in doubled polys) then this arbitrarily chooses one of them */
+		f = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces);
+		if (f)
+			knife_append_list(kcd, &newkfe->v2->faces, f);
+	}
 	newkfe->basef = kfe->basef;
 
 	ref = find_ref(&kfe->v1->edges, kfe);
@@ -490,6 +508,8 @@
 		kfe->v1->inspace = kcd->prev.is_space;
 		kfe->draw = !kcd->prev.is_space;
 		kfe->v1->isface = 1;
+		if (kfe->v1->draw && kcd->prev.bmface)
+			knife_append_list(kcd, &kfe->v1->faces, kcd->prev.bmface);
 	}
 
 	if (kcd->cur.vert) {
@@ -504,6 +524,8 @@
 		kfe->v2->draw = !kcd->cur.is_space;
 		kfe->v2->isface = 1;
 		kfe->v2->inspace = kcd->cur.is_space;
+		if (kfe->v2->draw && kcd->cur.bmface)
+			knife_append_list(kcd, &kfe->v2->faces, kcd->cur.bmface);
 
 		if (kcd->cur.is_space)
 			kfe->draw = 0;
@@ -511,7 +533,7 @@
 		kcd->cur.vert = kfe->v2;
 	}
 
-	knife_find_basef(kcd, kfe);
+	knife_find_basef(kfe);
 
 	knife_add_to_vert_edges(kcd, kfe);
 
@@ -716,6 +738,7 @@
 		BMEdgeHit *lh, *lastlh, *firstlh;
 		int i;
 
+		/* TODO: not a stable sort! need to figure out what to do for equal lambdas */
 		qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
 
 		lh = kcd->linehits;
@@ -1153,7 +1176,7 @@
 						hit.kfe = kfe;
 						hit.v = NULL;
 
-						knife_find_basef(kcd, kfe);
+						knife_find_basef(kfe);
 						hit.f = kfe->basef;
 						hit.perc = len_v3v3(p, kfe->v1->cageco) / len_v3v3(kfe->v1->cageco, kfe->v2->cageco);
 						copy_v3_v3(hit.cagehit, p);




More information about the Bf-blender-cvs mailing list