[Bf-blender-cvs] [bbc33e9] bmesh-boolean-experiment: basic intersection boolean now works

Campbell Barton noreply at git.blender.org
Tue Oct 27 18:17:24 CET 2015


Commit: bbc33e9c24a42dcce3d9ba66f5d70d4d6f7fdfd4
Author: Campbell Barton
Date:   Sat Nov 22 19:47:23 2014 +0100
Branches: bmesh-boolean-experiment
https://developer.blender.org/rBbbc33e9c24a42dcce3d9ba66f5d70d4d6f7fdfd4

basic intersection boolean now works

===================================================================

M	source/blender/bmesh/intern/bmesh_core.c
M	source/blender/bmesh/intern/bmesh_core.h
M	source/blender/bmesh/tools/bmesh_intersect.c
M	source/blender/bmesh/tools/bmesh_intersect.h
M	source/blender/editors/mesh/editmesh_intersect.c
M	source/blender/modifiers/intern/MOD_boolean.c

===================================================================

diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c
index e67aa1d..1e80962 100644
--- a/source/blender/bmesh/intern/bmesh_core.c
+++ b/source/blender/bmesh/intern/bmesh_core.c
@@ -805,6 +805,66 @@ void BM_face_kill(BMesh *bm, BMFace *f)
 
 	bm_kill_only_face(bm, f);
 }
+
+
+void BM_face_kill_loose(BMesh *bm, BMFace *f)
+{
+#ifdef USE_BMESH_HOLES
+	BMLoopList *ls, *ls_next;
+#endif
+
+	BM_CHECK_ELEMENT(f);
+
+#ifdef USE_BMESH_HOLES
+	for (ls = f->loops.first; ls; ls = ls_next)
+#else
+	if (f->l_first)
+#endif
+	{
+		BMLoop *l_iter, *l_next, *l_first;
+
+#ifdef USE_BMESH_HOLES
+		ls_next = ls->next;
+		l_iter = l_first = ls->first;
+#else
+		l_iter = l_first = f->l_first;
+#endif
+
+		do {
+			BMEdge *e;
+			l_next = l_iter->next;
+
+			e = l_iter->e;
+			bmesh_radial_loop_remove(l_iter, e);
+			bm_kill_only_loop(bm, l_iter);
+
+			if (e->l == NULL) {
+				BMVert *v1 = e->v1, *v2 = e->v2;
+
+				bmesh_disk_edge_remove(e, e->v1);
+				bmesh_disk_edge_remove(e, e->v2);
+				bm_kill_only_edge(bm, e);
+
+				if (v1->e == NULL) {
+					bm_kill_only_vert(bm, v1);
+				}
+				if (v2->e == NULL) {
+					bm_kill_only_vert(bm, v2);
+				}
+			}
+		} while ((l_iter = l_next) != l_first);
+
+#ifdef USE_BMESH_HOLES
+		BLI_mempool_free(bm->looplistpool, ls);
+#endif
+	}
+
+	bm_kill_only_face(bm, f);
+}
+
+
+
+
 /**
  * kills \a e and all faces that use it.
  */
diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h
index 2b100eb..2292259 100644
--- a/source/blender/bmesh/intern/bmesh_core.h
+++ b/source/blender/bmesh/intern/bmesh_core.h
@@ -58,6 +58,8 @@ BMFace *BM_face_create_verts(
 void    BM_face_edges_kill(BMesh *bm, BMFace *f);
 void    BM_face_verts_kill(BMesh *bm, BMFace *f);
 
+void    BM_face_kill_loose(BMesh *bm, BMFace *f);
+
 void    BM_face_kill(BMesh *bm, BMFace *f);
 void    BM_edge_kill(BMesh *bm, BMEdge *e);
 void    BM_vert_kill(BMesh *bm, BMVert *v);
diff --git a/source/blender/bmesh/tools/bmesh_intersect.c b/source/blender/bmesh/tools/bmesh_intersect.c
index 8b36b43..969cda5 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.c
+++ b/source/blender/bmesh/tools/bmesh_intersect.c
@@ -870,9 +870,10 @@ static void raycast_callback(void *userdata,
 	}
 }
 
-static bool UNUSED_FUNCTION(isect_bvhtree_point_v3)(BVHTree *tree,
-                                                    BMLoop *(*looptris)[3],
-                                                    const float co[3])
+static bool isect_bvhtree_point_v3(
+        BVHTree *tree,
+        BMLoop *(*looptris)[3],
+        const float co[3])
 {
 	RaycastData raycast_data = {
 		looptris,
@@ -884,7 +885,9 @@ static bool UNUSED_FUNCTION(isect_bvhtree_point_v3)(BVHTree *tree,
 		0
 	};
 	BVHTreeRayHit hit = {0};
-	float D[3] = {1.0f, 0.0f, 0.0f};
+	float dir[3] = {1.0f, 0.0f, 0.0f};
+
+	// copy_v3_fl(dir, (float)M_SQRT1_3);
 
 	/* Need to initialize hit even tho it's not used.
 	 * This is to make it so kdotree believes we didn't intersect anything and
@@ -894,7 +897,7 @@ static bool UNUSED_FUNCTION(isect_bvhtree_point_v3)(BVHTree *tree,
 	hit.dist = FLT_MAX;
 
 	BLI_bvhtree_ray_cast(tree,
-	                     co, D,
+	                     co, dir,
 	                     0.0f,
 	                     &hit,
 	                     raycast_callback,
@@ -914,12 +917,14 @@ static bool UNUSED_FUNCTION(isect_bvhtree_point_v3)(BVHTree *tree,
  * leaving the resulting edges tagged.
  *
  * \param test_fn Return value: -1: skip, 0: tree_a, 1: tree_b (use_self == false)
+ * \param boolean_mode 0: no-boolean, 1: intersection... etc.
  */
 bool BM_mesh_intersect(
         BMesh *bm,
         struct BMLoop *(*looptris)[3], const int looptris_tot,
         int (*test_fn)(BMFace *f, void *user_data), void *user_data,
         const bool use_self, const bool use_separate,
+        const int boolean_mode,
         const float eps)
 {
 	struct ISectState s;
@@ -1043,9 +1048,13 @@ bool BM_mesh_intersect(
 		}
 		MEM_freeN(overlap);
 	}
-	BLI_bvhtree_free(tree_a);
-	if (tree_a != tree_b) {
-		BLI_bvhtree_free(tree_b);
+
+	if (boolean_mode == 0) {
+		/* no booleans, just free immediate */
+		BLI_bvhtree_free(tree_a);
+		if (tree_a != tree_b) {
+			BLI_bvhtree_free(tree_b);
+		}
 	}
 
 #else
@@ -1423,6 +1432,79 @@ bool BM_mesh_intersect(
 	(void)use_separate;
 #endif  /* USE_SEPARATE */
 
+	if ((boolean_mode != 0) && BLI_gset_size(s.wire_edges)) {
+
+		{
+			GSetIterator gs_iter;
+
+			/* TODO, avoid calling? */
+			BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false);
+
+			GSET_ITER (gs_iter, s.wire_edges) {
+				BMEdge *e = BLI_gsetIterator_getKey(&gs_iter);
+				BM_elem_flag_enable(e, BM_ELEM_TAG);
+			}
+		}
+
+		{
+			/* group vars */
+			int *groups_array;
+			int (*group_index)[2];
+			int group_tot;
+			int i;
+			bool is_inside;
+			BMFace **ftable;
+
+			BM_mesh_elem_table_ensure(bm, BM_FACE);
+			ftable = bm->ftable;
+
+			groups_array = MEM_mallocN(sizeof(*groups_array) * (size_t)bm->totface, __func__);
+			group_tot = BM_mesh_calc_face_groups(
+			        bm, groups_array, &group_index,
+			        NULL, NULL,
+			        0, BM_EDGE);
+
+			/* first check if island is inside */
+
+			/* TODO, find if islands are inside/outside,
+			 * for now remove alternate islands, as simple testcase */
+
+
+			for (i = 0; i < group_tot; i++) {
+				int fg     = group_index[i][0];
+				int fg_end = group_index[i][1] + fg;
+
+				is_inside = true;
+
+				{
+					/* for now assyme this is an OK face to test with (not degenerate!) */
+					BMFace *f = ftable[groups_array[fg]];
+					float co[3];
+					BM_face_calc_center_mean(f, co);
+					if (isect_bvhtree_point_v3(test_fn(f, user_data) == 1 ? tree_a : tree_b, looptris, co)) {
+						is_inside = false;
+					}
+				}
+
+				if (is_inside) {
+					for (; fg != fg_end; fg++) {
+						BM_face_kill_loose(bm, ftable[groups_array[fg]]);
+					}
+				}
+				is_inside = !is_inside;
+			}
+
+			MEM_freeN(groups_array);
+			MEM_freeN(group_index);
+		}
+
+		/* no booleans, just free immediate */
+		BLI_bvhtree_free(tree_a);
+		if (tree_a != tree_b) {
+			BLI_bvhtree_free(tree_b);
+		}
+	}
+
 	has_isect = (BLI_ghash_size(s.face_edges) != 0);
 
 	/* cleanup */
diff --git a/source/blender/bmesh/tools/bmesh_intersect.h b/source/blender/bmesh/tools/bmesh_intersect.h
index af6e510..543d8a8 100644
--- a/source/blender/bmesh/tools/bmesh_intersect.h
+++ b/source/blender/bmesh/tools/bmesh_intersect.h
@@ -30,6 +30,7 @@ bool BM_mesh_intersect(
         struct BMLoop *(*looptris)[3], const int looptris_tot,
         int (*test_fn)(BMFace *f, void *user_data), void *user_data,
         const bool use_self, const bool use_separate,
+        const int boolean_mode,
         const float eps);
 
 #endif /* __BMESH_INTERSECT_H__ */
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index e2e4638..8f04a5a 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -124,6 +124,7 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
 	        em->looptris, em->tottri,
 	        test_fn, NULL,
 	        use_self, use_separate,
+	        0,
 	        eps);
 
 
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index 87eff87..a52ef3e 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -208,52 +208,13 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
 				        bm,
 				        looptris, tottri,
 				        bm_face_isect_pair, &user_data,
-				        false, true, FLT_EPSILON);
+				        false, true,
+				        1,
+				        FLT_EPSILON);
 
 				MEM_freeN(looptris);
 			}
 
-			{
-				/* group vars */
-				int *groups_array;
-				int (*group_index)[2];
-				int group_tot;
-				int i;
-				bool is_inside;
-				BMFace **ftable;
-
-				BM_mesh_elem_table_ensure(bm, BM_FACE);
-				ftable = bm->ftable;
-
-				groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totface, __func__);
-				group_tot = BM_mesh_calc_face_groups(
-				        bm, groups_array, &group_index,
-				        NULL, NULL,
-				        0, BM_EDGE);
-
-				/* first check if island is inside */
-
-				/* TODO, find if islands are inside/outside,
-				 * for now remove alternate islands, as simple testcase */
-				is_inside = false;
-
-
-				for (i = 0; i < group_tot; i++) {
-					int fg     = group_index[i][0];
-					int fg_end = group_index[i][1] + fg;
-
-					if (is_inside) {
-						for (; fg != fg_end; fg++) {
-							BM_face_kill(bm, ftable[groups_array[fg]]);
-						}
-					}
-					is_inside = !is_inside;
-				}
-
-				MEM_freeN(groups_array);
-				MEM_freeN(group_index);
-			}
-
 			result = CDDM_from_bmesh(bm, true);
 
 			BM_mesh_free(bm);
@@ -297,12 +258,12 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
 		result = get_quick_derivedMesh(derivedData, dm, bmd->operation);
 
 		if (result == NULL) {
-			// TIMEIT_START(NewBooleanDerivedMesh)
+			TIMEIT_START(NewBooleanDerivedMesh);
 
 			result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
 			                               1 + bmd->operation);
 
-			// TIMEIT_END(NewBooleanDerivedMesh)
+			TIMEIT_END(NewBooleanDerivedMesh);
 		}
 
 		/* if new mesh returned, return it; otherwise there was




More information about the Bf-blender-cvs mailing list