diff options
Diffstat (limited to 'source/blender/bmesh/tools/bmesh_boolean.c')
-rw-r--r-- | source/blender/bmesh/tools/bmesh_boolean.c | 211 |
1 files changed, 0 insertions, 211 deletions
diff --git a/source/blender/bmesh/tools/bmesh_boolean.c b/source/blender/bmesh/tools/bmesh_boolean.c deleted file mode 100644 index 67bf834be3a..00000000000 --- a/source/blender/bmesh/tools/bmesh_boolean.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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. - */ - -/** \file - * \ingroup bmesh - * - * Main functions for boolean on a BMesh (used by the tool and modifier) - */ - -#include "MEM_guardedalloc.h" - -#include "BLI_boolean.h" -#include "BLI_math.h" - -#include "bmesh.h" -#include "bmesh_boolean.h" - -/* Make a a triangle mesh for input to the Boolean function. - * We take only take triangles from faces f for which test_fn(f, user_data) returns 'side'. - * Caller must call free_trimesh_input when done with the returned value. */ -static Boolean_trimesh_input *trimesh_input_from_bm(BMesh *bm, - struct BMLoop *(*looptris)[3], - const int looptris_tot, - int (*(test_fn))(BMFace *f, void *user_data), - void *user_data, - int side) -{ - int i, in_v_index, in_t_index, bmv_index, looptri_index, tot_in_vert, tot_in_tri; - Boolean_trimesh_input *trimesh; - int *bmv_to_v, *v_to_bmv, *t_to_looptri; - BMFace *f; - - BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE); - BM_mesh_elem_table_ensure(bm, BM_VERT | BM_FACE); - trimesh = MEM_mallocN(sizeof(*trimesh), __func__); - bmv_to_v = MEM_malloc_arrayN(bm->totvert, sizeof(int), __func__); - v_to_bmv = MEM_malloc_arrayN(bm->totvert, sizeof(int), __func__); - t_to_looptri = MEM_malloc_arrayN(looptris_tot, sizeof(int), __func__); - for (i = 0; i < bm->totvert; i++) { - bmv_to_v[i] = -1; - v_to_bmv[i] = -1; - } - in_v_index = 0; - tot_in_tri = 0; - for (looptri_index = 0; looptri_index < looptris_tot; looptri_index++) { - f = looptris[looptri_index][0]->f; - if (test_fn(f, user_data) == side) { - t_to_looptri[tot_in_tri++] = looptri_index; - for (i = 0; i < 3; i++) { - bmv_index = BM_elem_index_get(looptris[looptri_index][i]->v); - if (bmv_to_v[bmv_index] == -1) { - v_to_bmv[in_v_index] = bmv_index; - bmv_to_v[bmv_index] = in_v_index; - in_v_index++; - } - } - } - } - tot_in_vert = in_v_index; - trimesh->vert_len = tot_in_vert; - trimesh->tri_len = tot_in_tri; - trimesh->vert_coord = MEM_malloc_arrayN(tot_in_vert, sizeof(trimesh->vert_coord[0]), __func__); - trimesh->tri = MEM_malloc_arrayN(tot_in_tri, sizeof(trimesh->tri[0]), __func__); - for (in_v_index = 0; in_v_index < tot_in_vert; in_v_index++) { - bmv_index = v_to_bmv[in_v_index]; - BMVert *bmv = BM_vert_at_index(bm, bmv_index); - copy_v3_v3(trimesh->vert_coord[in_v_index], bmv->co); - } - for (in_t_index = 0; in_t_index < tot_in_tri; in_t_index++) { - looptri_index = t_to_looptri[in_t_index]; - for (i = 0; i < 3; i++) { - bmv_index = BM_elem_index_get(looptris[looptri_index][i]->v); - BLI_assert(bmv_to_v[bmv_index] != -1); - trimesh->tri[in_t_index][i] = bmv_to_v[bmv_index]; - } - } - MEM_freeN(bmv_to_v); - MEM_freeN(v_to_bmv); - MEM_freeN(t_to_looptri); - - return trimesh; -} - -static void free_trimesh_input(Boolean_trimesh_input *in) -{ - MEM_freeN(in->vert_coord); - MEM_freeN(in->tri); - MEM_freeN(in); -} - -static void apply_trimesh_output_to_bmesh(BMesh *bm, Boolean_trimesh_output *out) -{ - /* For now, for testing, just create new BMesh elements for returned subdivided mesh and kill old - * mesh. */ - int v, t; - BMIter iter; - BMVert *bmv, *bmv_next; - - BM_ITER_MESH_MUTABLE (bmv, bmv_next, &iter, bm, BM_VERTS_OF_MESH) { - BM_vert_kill(bm, bmv); - } - - if (out->vert_len > 0 && out->tri_len > 0) { - BMVert **new_bmv = MEM_malloc_arrayN(out->vert_len, sizeof(BMVert *), __func__); - for (v = 0; v < out->vert_len; v++) { - new_bmv[v] = BM_vert_create(bm, out->vert_coord[v], NULL, BM_CREATE_NOP); - } - for (t = 0; t < out->tri_len; t++) { - BMVert *v0 = new_bmv[out->tri[t][0]]; - BMVert *v1 = new_bmv[out->tri[t][1]]; - BMVert *v2 = new_bmv[out->tri[t][2]]; - BM_face_create_quad_tri(bm, v0, v1, v2, NULL, NULL, BM_CREATE_NOP); - } - MEM_freeN(new_bmv); - } -} - -/* - * Perform the boolean operation specified by boolean_mode on the mesh bm. - * The inputs to the boolean operation are either one submesh (if use_self is true), - * or two submeshes. The submeshes are specified by providing a test_fn which takes - * a face and the supplied user_data and says with 'side' of the boolean operation - * that face is for: 0 for the first side (side A), 1 for the second side (side B), - * and -1 if the face is to be ignored completely in the boolean operation. - * - * If use_self is true, all operations do the same: the submesh is self-intersected - * and all pieces inside that result are removed. - * Otherwise, the operations can be one of BMESH_ISECT_BOOLEAN_ISECT, BMESH_ISECT_BOOLEAN_UNION, - * or BMESH_ISECT_BOOLEAN_DIFFERENCE. - * - * (The actual library function called to do the boolean is internally capable of handling - * n-ary operands, so maybe in the future we can expose that functionality to users.) - */ -bool BM_mesh_boolean(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 int boolean_mode) -{ - Boolean_trimesh_input *in_a = trimesh_input_from_bm( - bm, looptris, looptris_tot, test_fn, user_data, 0); - Boolean_trimesh_input *in_b = NULL; - if (!use_self) { - in_b = trimesh_input_from_bm(bm, looptris, looptris_tot, test_fn, user_data, 1); - /* The old boolean code does DIFFERENCE as b - a, which is weird, so adapt here - * so the rest of the code is sensible. - */ - SWAP(Boolean_trimesh_input *, in_a, in_b); - } - Boolean_trimesh_output *out = BLI_boolean_trimesh(in_a, in_b, boolean_mode); - BLI_assert(out != NULL); - bool intersections_found = out->tri_len != in_a->tri_len + (in_b ? in_b->tri_len : 0) || - out->vert_len != in_a->vert_len + (in_b ? in_b->vert_len : 0); - apply_trimesh_output_to_bmesh(bm, out); - free_trimesh_input(in_a); - if (in_b) { - free_trimesh_input(in_b); - } - BLI_boolean_trimesh_free(out); - return intersections_found; -} - -/* - * Perform a Knife Intersection operation on the mesh bm. - * There are either one or two operands, the same as described above for BM_mesh_boolean(). - * If use_separate_all is true, each edge that is created from the intersection should - * be used to separate all its incident faces. TODO: implement that. - * TODO: need to ensure that "selected/non-selected" flag of original faces gets propagated - * to the intersection result faces. - */ -bool BM_mesh_boolean_knife(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 UNUSED(use_separate_all)) -{ - Boolean_trimesh_input *in_a = trimesh_input_from_bm( - bm, looptris, looptris_tot, test_fn, user_data, 0); - Boolean_trimesh_input *in_b = NULL; - if (!use_self) { - in_b = trimesh_input_from_bm(bm, looptris, looptris_tot, test_fn, user_data, 1); - } - Boolean_trimesh_output *out = BLI_boolean_trimesh(in_a, in_b, BOOLEAN_NONE); - BLI_assert(out != NULL); - bool intersections_found = out->tri_len != in_a->tri_len + (in_b ? in_b->tri_len : 0) || - out->vert_len != in_a->vert_len + (in_b ? in_b->vert_len : 0); - apply_trimesh_output_to_bmesh(bm, out); - free_trimesh_input(in_a); - if (in_b) { - free_trimesh_input(in_b); - } - BLI_boolean_trimesh_free(out); - return intersections_found; -} |