| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Nicholas Bishop | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file blender/bmesh/operators/bmo_hull.c
 | 
					
						
							|  |  |  |  *  \ingroup bmesh | 
					
						
							| 
									
										
										
										
											2013-03-30 08:54:50 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Create a convex hull using bullet physics library. | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | #ifdef WITH_BULLET
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | #include "BLI_array.h"
 | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | #include "Bullet-C-Api.h"
 | 
					
						
							| 
									
										
										
										
											2012-07-06 22:48:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | /* XXX: using 128 for totelem and pchunk of mempool, no idea what good
 | 
					
						
							| 
									
										
										
										
											2012-05-01 17:51:03 +00:00
										 |  |  |  * values would be though */ | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "bmesh.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | #include "intern/bmesh_operators_private.h"  /* own include */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | /* Internal operator flags */ | 
					
						
							|  |  |  | typedef enum { | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 	HULL_FLAG_INPUT =           (1 << 0), | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 	HULL_FLAG_INTERIOR_ELE =    (1 << 1), | 
					
						
							|  |  |  | 	HULL_FLAG_OUTPUT_GEOM =     (1 << 2), | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 	HULL_FLAG_DEL =             (1 << 3), | 
					
						
							|  |  |  | 	HULL_FLAG_HOLE =            (1 << 4) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | } HullFlags; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-16 23:23:33 +00:00
										 |  |  | /* Store hull triangles separate from BMesh faces until the end; this
 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  |  * way we don't have to worry about cleaning up extraneous edges or | 
					
						
							|  |  |  |  * incorrectly deleting existing geometry. */ | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | typedef struct HullTriangle { | 
					
						
							|  |  |  | 	BMVert *v[3]; | 
					
						
							|  |  |  | 	float no[3]; | 
					
						
							|  |  |  | 	int skip; | 
					
						
							|  |  |  | } HullTriangle; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*************************** Hull Triangles ***************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-14 20:58:59 +00:00
										 |  |  | static void hull_add_triangle(BMesh *bm, GHash *hull_triangles, BLI_mempool *pool, | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  |                               BMVert *v1, BMVert *v2, BMVert *v3) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	HullTriangle *t; | 
					
						
							| 
									
										
										
										
											2012-05-14 20:58:59 +00:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	t = BLI_mempool_calloc(pool); | 
					
						
							|  |  |  | 	t->v[0] = v1; | 
					
						
							|  |  |  | 	t->v[1] = v2; | 
					
						
							|  |  |  | 	t->v[2] = v3; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-14 20:58:59 +00:00
										 |  |  | 	/* Mark triangles vertices as not interior */ | 
					
						
							|  |  |  | 	for (i = 0; i < 3; i++) | 
					
						
							|  |  |  | 		BMO_elem_flag_disable(bm, t->v[i], HULL_FLAG_INTERIOR_ELE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 	BLI_ghash_insert(hull_triangles, t, NULL); | 
					
						
							|  |  |  | 	normal_tri_v3(t->no, v1->co, v2->co, v3->co); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static BMFace *hull_find_example_face(BMesh *bm, BMEdge *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { | 
					
						
							|  |  |  | 		if (BMO_elem_flag_test(bm, f, HULL_FLAG_INPUT) || | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 		    !BMO_elem_flag_test(bm, f, HULL_FLAG_OUTPUT_GEOM)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			return f; | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	GHashIterator iter; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	GHASH_ITER (iter, hull_triangles) { | 
					
						
							|  |  |  | 		HullTriangle *t = BLI_ghashIterator_getKey(&iter); | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (!t->skip) { | 
					
						
							|  |  |  | 			BMEdge *edges[3] = { | 
					
						
							| 
									
										
										
										
											2012-11-29 16:26:39 +00:00
										 |  |  | 				BM_edge_create(bm, t->v[0], t->v[1], NULL, BM_CREATE_NO_DOUBLE), | 
					
						
							|  |  |  | 				BM_edge_create(bm, t->v[1], t->v[2], NULL, BM_CREATE_NO_DOUBLE), | 
					
						
							|  |  |  | 				BM_edge_create(bm, t->v[2], t->v[0], NULL, BM_CREATE_NO_DOUBLE) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			}; | 
					
						
							|  |  |  | 			BMFace *f, *example = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 00:54:55 +00:00
										 |  |  | 			if (BM_face_exists(t->v, 3, &f)) { | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 				/* If the operator is run with "use_existing_faces"
 | 
					
						
							|  |  |  | 				 * disabled, but an output face in the hull is the | 
					
						
							|  |  |  | 				 * same as a face in the existing mesh, it should not | 
					
						
							|  |  |  | 				 * be marked as unused or interior. */ | 
					
						
							|  |  |  | 				BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM); | 
					
						
							|  |  |  | 				BMO_elem_flag_disable(bm, f, HULL_FLAG_HOLE); | 
					
						
							|  |  |  | 				BMO_elem_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 			else { | 
					
						
							|  |  |  | 				/* Look for an adjacent face that existed before the hull */ | 
					
						
							|  |  |  | 				for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 					if (!example) | 
					
						
							|  |  |  | 						example = hull_find_example_face(bm, edges[i]); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 				/* Create new hull face */ | 
					
						
							| 
									
										
										
										
											2013-08-21 07:51:47 +00:00
										 |  |  | 				f = BM_face_create_verts(bm, t->v, 3, example, BM_CREATE_NO_DOUBLE, true); | 
					
						
							| 
									
										
										
										
											2013-08-18 11:44:51 +00:00
										 |  |  | 				BM_face_copy_shared(bm, f, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 			/* Mark face for 'geom.out' slot and select */ | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			BMO_elem_flag_enable(bm, f, HULL_FLAG_OUTPUT_GEOM); | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 			BM_face_select_set(bm, f, true); | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 			/* Mark edges for 'geom.out' slot */ | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 				BMO_elem_flag_enable(bm, edges[i], HULL_FLAG_OUTPUT_GEOM); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 			/* Mark input edges for 'geom.out' slot */ | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 			for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 				const int next = (i == 2 ? 0 : i + 1); | 
					
						
							|  |  |  | 				BMEdge *e = BM_edge_exists(t->v[i], t->v[next]); | 
					
						
							|  |  |  | 				if (e && | 
					
						
							| 
									
										
										
										
											2013-03-01 14:47:06 +00:00
										 |  |  | 				    BMO_elem_flag_test(bm, e, HULL_FLAG_INPUT) && | 
					
						
							|  |  |  | 				    !BMO_elem_flag_test(bm, e, HULL_FLAG_HOLE)) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 					BMO_elem_flag_enable(bm, e, HULL_FLAG_OUTPUT_GEOM); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 		/* Mark verts for 'geom.out' slot */ | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 		for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 			BMO_elem_flag_enable(bm, t->v[i], HULL_FLAG_OUTPUT_GEOM); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /***************************** Final Edges ****************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	GHash *edges; | 
					
						
							|  |  |  | 	BLI_mempool *base_pool, *link_pool; | 
					
						
							|  |  |  | } HullFinalEdges; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static LinkData *final_edges_find_link(ListBase *adj, BMVert *v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	LinkData *link; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (link = adj->first; link; link = link->next) { | 
					
						
							|  |  |  | 		if (link->data == v) | 
					
						
							|  |  |  | 			return link; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int hull_final_edges_lookup(HullFinalEdges *final_edges, | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  |                                    BMVert *v1, BMVert *v2) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ListBase *adj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Use lower vertex pointer for hash key */ | 
					
						
							|  |  |  | 	if (v1 > v2) | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 		SWAP(BMVert *, v1, v2); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	adj = BLI_ghash_lookup(final_edges->edges, v1); | 
					
						
							|  |  |  | 	if (!adj) | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return !!final_edges_find_link(adj, v2); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Used for checking whether a pre-existing edge lies on the hull */ | 
					
						
							|  |  |  | static HullFinalEdges *hull_final_edges(GHash *hull_triangles) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	HullFinalEdges *final_edges; | 
					
						
							|  |  |  | 	GHashIterator iter; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	final_edges = MEM_callocN(sizeof(HullFinalEdges), "HullFinalEdges"); | 
					
						
							| 
									
										
										
										
											2012-05-16 00:51:36 +00:00
										 |  |  | 	final_edges->edges = BLI_ghash_ptr_new("final edges ghash"); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 	final_edges->base_pool = BLI_mempool_create(sizeof(ListBase), 128, 128, 0); | 
					
						
							|  |  |  | 	final_edges->link_pool = BLI_mempool_create(sizeof(LinkData), 128, 128, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GHASH_ITER (iter, hull_triangles) { | 
					
						
							|  |  |  | 		LinkData *link; | 
					
						
							|  |  |  | 		int i; | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		for (i = 0; i < 3; i++) { | 
					
						
							|  |  |  | 			HullTriangle *t = BLI_ghashIterator_getKey(&iter); | 
					
						
							|  |  |  | 			BMVert *v1 = t->v[i]; | 
					
						
							|  |  |  | 			BMVert *v2 = t->v[(i + 1) % 3]; | 
					
						
							|  |  |  | 			ListBase *adj; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Use lower vertex pointer for hash key */ | 
					
						
							|  |  |  | 			if (v1 > v2) | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 				SWAP(BMVert *, v1, v2); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			adj = BLI_ghash_lookup(final_edges->edges, v1); | 
					
						
							|  |  |  | 			if (!adj) { | 
					
						
							|  |  |  | 				adj = BLI_mempool_calloc(final_edges->base_pool); | 
					
						
							|  |  |  | 				BLI_ghash_insert(final_edges->edges, v1, adj); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (!final_edges_find_link(adj, v2)) { | 
					
						
							|  |  |  | 				link = BLI_mempool_calloc(final_edges->link_pool); | 
					
						
							|  |  |  | 				link->data = v2; | 
					
						
							|  |  |  | 				BLI_addtail(adj, link); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return final_edges; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hull_final_edges_free(HullFinalEdges *final_edges) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BLI_ghash_free(final_edges->edges, NULL, NULL); | 
					
						
							|  |  |  | 	BLI_mempool_destroy(final_edges->base_pool); | 
					
						
							|  |  |  | 	BLI_mempool_destroy(final_edges->link_pool); | 
					
						
							|  |  |  | 	MEM_freeN(final_edges); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**************************** Final Output ****************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles, | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  |                                     HullFinalEdges *final_edges) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	GHashIterator hull_iter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GHASH_ITER (hull_iter, hull_triangles) { | 
					
						
							|  |  |  | 		HullTriangle *t = BLI_ghashIterator_getKey(&hull_iter); | 
					
						
							|  |  |  | 		BMIter bm_iter1, bm_iter2; | 
					
						
							|  |  |  | 		BMFace *f; | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 		bool f_on_hull; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		BM_ITER_ELEM (f, &bm_iter1, t->v[0], BM_FACES_OF_VERT) { | 
					
						
							|  |  |  | 			BMEdge *e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Check that all the face's edges are on the hull,
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 			 * otherwise can't reuse it */ | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 			f_on_hull = true; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			BM_ITER_ELEM (e, &bm_iter2, f, BM_EDGES_OF_FACE) { | 
					
						
							|  |  |  | 				if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 					f_on_hull = false; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			/* Note: can't change ghash while iterating, so mark
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 			 * with 'skip' flag rather than deleting triangles */ | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			if (BM_vert_in_face(f, t->v[1]) && | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 			    BM_vert_in_face(f, t->v[2]) && f_on_hull) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 				t->skip = true; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 				BMO_elem_flag_disable(bm, f, HULL_FLAG_INTERIOR_ELE); | 
					
						
							|  |  |  | 				BMO_elem_flag_enable(bm, f, HULL_FLAG_HOLE); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hull_mark_interior_elements(BMesh *bm, BMOperator *op, | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  |                                         HullFinalEdges *final_edges) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMEdge *e; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Check for interior edges too */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		if (!hull_final_edges_lookup(final_edges, e->v1, e->v2)) | 
					
						
							|  |  |  | 			BMO_elem_flag_enable(bm, e, HULL_FLAG_INTERIOR_ELE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Mark all input faces as interior, some may be unmarked in
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 	 * hull_remove_overlapping() */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		BMO_elem_flag_enable(bm, f, HULL_FLAG_INTERIOR_ELE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hull_tag_unused(BMesh *bm, BMOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	BMVert *v; | 
					
						
							|  |  |  | 	BMEdge *e; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Mark vertices, edges, and faces that are already marked
 | 
					
						
							| 
									
										
										
										
											2012-05-16 23:37:23 +00:00
										 |  |  | 	 * interior (i.e. were already part of the input, but not part of | 
					
						
							|  |  |  | 	 * the hull), but that aren't also used by elements outside the | 
					
						
							|  |  |  | 	 * input set */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		if (BMO_elem_flag_test(bm, v, HULL_FLAG_INTERIOR_ELE)) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 			bool del = true; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 			BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 				if (!BMO_elem_flag_test(bm, e, HULL_FLAG_INPUT)) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 					del = false; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 			BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 				if (!BMO_elem_flag_test(bm, f, HULL_FLAG_INPUT)) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 					del = false; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (del) | 
					
						
							|  |  |  | 				BMO_elem_flag_enable(bm, v, HULL_FLAG_DEL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		if (BMO_elem_flag_test(bm, e, HULL_FLAG_INTERIOR_ELE)) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 			bool del = true; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 			BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 				if (!BMO_elem_flag_test(bm, f, HULL_FLAG_INPUT)) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 					del = false; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (del) | 
					
						
							|  |  |  | 				BMO_elem_flag_enable(bm, e, HULL_FLAG_DEL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		if (BMO_elem_flag_test(bm, f, HULL_FLAG_INTERIOR_ELE)) | 
					
						
							|  |  |  | 			BMO_elem_flag_enable(bm, f, HULL_FLAG_DEL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-15 01:52:28 +00:00
										 |  |  | static void hull_tag_holes(BMesh *bm, BMOperator *op) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 	BMEdge *e; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Unmark any hole faces if they are isolated or part of a
 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 	 * border */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (f, &oiter, op->slots_in, "input", BM_FACE) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		if (BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) { | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 			BM_ITER_ELEM (e, &iter, f, BM_EDGES_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2012-11-12 04:50:45 +00:00
										 |  |  | 				if (BM_edge_is_boundary(e)) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 					BMO_elem_flag_disable(bm, f, HULL_FLAG_HOLE); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 	/* Mark edges too if all adjacent faces are holes and the edge is
 | 
					
						
							|  |  |  | 	 * not already isolated */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (e, &oiter, op->slots_in, "input", BM_EDGE) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 		bool hole = true; | 
					
						
							|  |  |  | 		bool any_faces = false; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 		BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 			any_faces = true; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			if (!BMO_elem_flag_test(bm, f, HULL_FLAG_HOLE)) { | 
					
						
							| 
									
										
										
										
											2013-01-14 16:42:43 +00:00
										 |  |  | 				hole = false; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 		if (hole && any_faces) | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 			BMO_elem_flag_enable(bm, e, HULL_FLAG_HOLE); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | static int hull_input_vert_count(BMOperator *op) | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	BMVert *v; | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 		count++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | static BMVert **hull_input_verts_copy(BMOperator *op, | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  |                                       const int num_input_verts) | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	BMVert *v; | 
					
						
							|  |  |  | 	BMVert **input_verts = MEM_callocN(sizeof(*input_verts) * | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  | 	                                   num_input_verts, AT); | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 	int i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 		input_verts[i++] = v; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return input_verts; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static float (*hull_verts_for_bullet(BMVert **input_verts, | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  |                                      const int num_input_verts))[3] | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, AT); | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < num_input_verts; i++) { | 
					
						
							|  |  |  | 		copy_v3_v3(coords[i], input_verts[i]->co); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return coords; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static BMVert **hull_verts_from_bullet(plConvexHull hull, | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  |                                        BMVert **input_verts, | 
					
						
							|  |  |  |                                        const int num_input_verts) | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	const int num_verts = plConvexHullNumVertices(hull); | 
					
						
							|  |  |  | 	BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  | 	                                  num_verts, AT); | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < num_verts; i++) { | 
					
						
							|  |  |  | 		float co[3]; | 
					
						
							|  |  |  | 		int original_index; | 
					
						
							|  |  |  | 		plConvexHullGetVertex(hull, i, co, &original_index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (original_index >= 0 && original_index < num_input_verts) { | 
					
						
							|  |  |  | 			hull_verts[i] = input_verts[original_index]; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			BLI_assert(!"Unexpected new vertex in hull output"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return hull_verts; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void hull_from_bullet(BMesh *bm, BMOperator *op, | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  |                              GHash *hull_triangles, | 
					
						
							|  |  |  |                              BLI_mempool *pool) | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int *fvi = NULL; | 
					
						
							|  |  |  | 	BLI_array_declare(fvi); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BMVert **input_verts; | 
					
						
							|  |  |  | 	float (*coords)[3]; | 
					
						
							|  |  |  | 	BMVert **hull_verts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	plConvexHull hull; | 
					
						
							|  |  |  | 	int i, count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	const int num_input_verts = hull_input_vert_count(op); | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	input_verts = hull_input_verts_copy(op, num_input_verts); | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 	coords = hull_verts_for_bullet(input_verts, num_input_verts); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hull = plConvexHullCompute(coords, num_input_verts); | 
					
						
							|  |  |  | 	hull_verts = hull_verts_from_bullet(hull, input_verts, num_input_verts); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	count = plConvexHullNumFaces(hull); | 
					
						
							|  |  |  | 	for (i = 0; i < count; i++) { | 
					
						
							|  |  |  | 		const int len = plConvexHullGetFaceSize(hull, i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (len > 2) { | 
					
						
							|  |  |  | 			BMVert *fv[3]; | 
					
						
							|  |  |  | 			int j; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Get face vertex indices */ | 
					
						
							|  |  |  | 			BLI_array_empty(fvi); | 
					
						
							|  |  |  | 			BLI_array_grow_items(fvi, len); | 
					
						
							|  |  |  | 			plConvexHullGetFaceVertices(hull, i, fvi); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* Note: here we throw away any NGons from Bullet and turn
 | 
					
						
							|  |  |  | 			 * them into triangle fans. Would be nice to use these | 
					
						
							|  |  |  | 			 * directly, but will have to wait until HullTriangle goes | 
					
						
							|  |  |  | 			 * away (TODO) */ | 
					
						
							|  |  |  | 			fv[0] = hull_verts[fvi[0]]; | 
					
						
							|  |  |  | 			for (j = 2; j < len; j++) { | 
					
						
							|  |  |  | 				fv[1] = hull_verts[fvi[j - 1]]; | 
					
						
							|  |  |  | 				fv[2] = hull_verts[fvi[j]]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				hull_add_triangle(bm, hull_triangles, pool, | 
					
						
							| 
									
										
										
										
											2012-11-09 09:33:28 +00:00
										 |  |  | 				                  fv[0], fv[1], fv[2]); | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_array_free(fvi); | 
					
						
							|  |  |  | 	MEM_freeN(hull_verts); | 
					
						
							|  |  |  | 	MEM_freeN(coords); | 
					
						
							|  |  |  | 	MEM_freeN(input_verts); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | /* Check that there are at least three vertices in the input */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | static int hull_num_input_verts_is_ok(BMOperator *op) | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	BMVert *v; | 
					
						
							|  |  |  | 	int partial_num_verts = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (v, &oiter, op->slots_in, "input", BM_VERT) { | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 		partial_num_verts++; | 
					
						
							|  |  |  | 		if (partial_num_verts >= 3) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return (partial_num_verts >= 3); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	HullFinalEdges *final_edges; | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 	BLI_mempool *hull_pool; | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 	BMElemF *ele; | 
					
						
							|  |  |  | 	BMOIter oiter; | 
					
						
							|  |  |  | 	GHash *hull_triangles; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 	/* Verify that at least three verts in the input */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	if (!hull_num_input_verts_is_ok(op)) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		BMO_error_raise(bm, op, BMERR_CONVEX_HULL_FAILED, | 
					
						
							| 
									
										
										
										
											2012-10-25 04:08:51 +00:00
										 |  |  | 		                "Requires at least three vertices"); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Tag input elements */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	BMO_ITER (ele, &oiter, op->slots_in, "input", BM_ALL) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		BMO_elem_flag_enable(bm, ele, HULL_FLAG_INPUT); | 
					
						
							| 
									
										
										
										
											2012-05-14 20:58:59 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		/* Mark all vertices as interior to begin with */ | 
					
						
							|  |  |  | 		if (ele->head.htype == BM_VERT) | 
					
						
							|  |  |  | 			BMO_elem_flag_enable(bm, ele, HULL_FLAG_INTERIOR_ELE); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	hull_pool = BLI_mempool_create(sizeof(HullTriangle), 128, 128, 0); | 
					
						
							| 
									
										
										
										
											2012-05-16 00:51:36 +00:00
										 |  |  | 	hull_triangles = BLI_ghash_ptr_new("hull_triangles"); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 	hull_from_bullet(bm, op, hull_triangles, hull_pool); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	final_edges = hull_final_edges(hull_triangles); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-05-14 20:58:59 +00:00
										 |  |  | 	hull_mark_interior_elements(bm, op, final_edges); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Remove hull triangles covered by an existing face */ | 
					
						
							| 
									
										
										
										
											2012-11-19 14:58:31 +00:00
										 |  |  | 	if (BMO_slot_bool_get(op->slots_in, "use_existing_faces")) { | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 		hull_remove_overlapping(bm, hull_triangles, final_edges); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hull_tag_holes(bm, op); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Done with edges */ | 
					
						
							|  |  |  | 	hull_final_edges_free(final_edges); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Convert hull triangles to BMesh faces */ | 
					
						
							|  |  |  | 	hull_output_triangles(bm, hull_triangles); | 
					
						
							|  |  |  | 	BLI_mempool_destroy(hull_pool); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_ghash_free(hull_triangles, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hull_tag_unused(bm, op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Output slot of input elements that ended up inside the hull
 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 	 * rather than part of it */ | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 	BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_interior.out", | 
					
						
							| 
									
										
										
										
											2012-11-28 00:16:06 +00:00
										 |  |  | 	                                  BM_ALL_NOLOOP, HULL_FLAG_INTERIOR_ELE); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Output slot of input elements that ended up inside the hull and
 | 
					
						
							|  |  |  | 	 * are are unused by other geometry. */ | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 	BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_unused.out", | 
					
						
							| 
									
										
										
										
											2012-11-28 00:16:06 +00:00
										 |  |  | 	                                  BM_ALL_NOLOOP, HULL_FLAG_DEL); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Output slot of faces and edges that were in the input and on
 | 
					
						
							| 
									
										
										
										
											2012-04-30 10:39:35 +00:00
										 |  |  | 	 * the hull (useful for cases like bridging where you want to | 
					
						
							|  |  |  | 	 * delete some input geometry) */ | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 	BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_holes.out", | 
					
						
							| 
									
										
										
										
											2012-11-28 00:16:06 +00:00
										 |  |  | 	                                  BM_ALL_NOLOOP, HULL_FLAG_HOLE); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Output slot of all hull vertices, faces, and edges */ | 
					
						
							| 
									
										
										
										
											2012-11-20 05:50:19 +00:00
										 |  |  | 	BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", | 
					
						
							| 
									
										
										
										
											2012-11-28 00:16:06 +00:00
										 |  |  | 	                                  BM_ALL_NOLOOP, HULL_FLAG_OUTPUT_GEOM); | 
					
						
							| 
									
										
										
										
											2012-04-29 16:09:40 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-10-23 23:54:15 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #endif  /* WITH_BULLET */
 |