diff options
Diffstat (limited to 'source/blender/bmesh/tools')
-rw-r--r-- | source/blender/bmesh/tools/BME_bevel.c | 2 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 19 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_edgesplit.c | 170 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_edgesplit.h | 32 |
4 files changed, 213 insertions, 10 deletions
diff --git a/source/blender/bmesh/tools/BME_bevel.c b/source/blender/bmesh/tools/BME_bevel.c index 3f2ca21bcee..5e1d58150fa 100644 --- a/source/blender/bmesh/tools/BME_bevel.c +++ b/source/blender/bmesh/tools/BME_bevel.c @@ -965,7 +965,7 @@ static BMesh *BME_bevel_initialize(BMesh *bm, int options, BMIter iter; int /* wire, */ len; - /* tag non-manifold geometr */ + /* tag non-manifold geometry */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BMO_elem_flag_enable(bm, v, BME_BEVEL_ORIG); if (v->e) { diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 9125800d3e8..cc472e4a501 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -37,6 +37,7 @@ #include "BKE_customdata.h" #include "bmesh.h" +#include "./intern/bmesh_private.h" @@ -263,14 +264,12 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMF } else { int i; - BMEdge **ee = NULL; - BLI_array_fixedstack_declare(ee, BM_DEFAULT_NGON_STACK_SIZE, totv, __func__); + BMEdge **ee = BLI_array_alloca(ee, totv); for (i = 0; i < totv; i++) { ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, BM_CREATE_NO_DOUBLE); } f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, 0); - BLI_array_fixedstack_free(ee); } if (facerep && f) { int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); @@ -1137,7 +1136,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) /* Make center ngon if odd number of segments and fully beveled */ if (ns % 2 == 1 && vm->count == bv->selcount) { BMVert **vv = NULL; - BLI_array_declare(vv); + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); v = vm->boundstart; do { @@ -1155,7 +1154,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) if (vm->count > bv->selcount) { int j; BMVert **vv = NULL; - BLI_array_declare(vv); + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); v = vm->boundstart; f = boundvert_rep_face(v); @@ -1217,7 +1216,7 @@ static BMFace *bevel_build_poly_ex(BMesh *bm, BevVert *bv) VMesh *vm = bv->vmesh; BoundVert *v; BMVert **vv = NULL; - BLI_array_declare(vv); + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); v = vm->boundstart; n = 0; @@ -1477,9 +1476,9 @@ static void build_vmesh(MemArena *mem_arena, BMesh *bm, BevVert *bv) } /* take care, this flag isn't cleared before use, it just so happens that its not set */ -#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_elem_flag_enable( (bme)->l, BM_ELEM_TAG) -#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_elem_flag_disable( (bme)->l, BM_ELEM_TAG) -#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_elem_flag_test( (bme)->l, BM_ELEM_TAG) +#define BM_BEVEL_EDGE_TAG_ENABLE(bme) BM_ELEM_API_FLAG_ENABLE( (bme), _FLAG_OVERLAP) +#define BM_BEVEL_EDGE_TAG_DISABLE(bme) BM_ELEM_API_FLAG_DISABLE( (bme), _FLAG_OVERLAP) +#define BM_BEVEL_EDGE_TAG_TEST(bme) BM_ELEM_API_FLAG_TEST( (bme), _FLAG_OVERLAP) /* * Construction around the vertex @@ -1506,6 +1505,8 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) nsel++; } ntot++; + + BM_BEVEL_EDGE_TAG_DISABLE(bme); } if (nsel == 0) { diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c new file mode 100644 index 00000000000..b6a8c7985d6 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -0,0 +1,170 @@ +/* + * ***** 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): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/tools/bmesh_edgesplit.c + * \ingroup bmesh + * + * Edge-Split. + * + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "bmesh.h" + +#include "bmesh_edgesplit.h" /* own include */ + + +/** + * Remove the BM_ELEM_TAG flag for edges we cant split + * + * un-tag edges not connected to other tagged edges, + * unless they are on a boundary + */ +static void bm_edgesplit_validate_seams(BMesh *bm) +{ + BMIter iter; + BMEdge *e; + + unsigned char *vtouch; + unsigned char *vt; + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + vtouch = MEM_callocN(sizeof(char) * bm->totvert, __func__); + + /* tag all boundary verts so as not to untag an edge which is inbetween only 2 faces [] */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + + /* unrelated to flag assignment in this function - since this is the + * only place we loop over all edges, disable tag */ + BM_elem_flag_disable(e, BM_ELEM_INTERNAL_TAG); + + if (e->l == NULL) { + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + else if (BM_edge_is_boundary(e)) { + vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; + vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; + + /* while the boundary verts need to be tagged, + * the edge its self can't be split */ + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + } + + /* single marked edges unconnected to any other marked edges + * are illegal, go through and unmark them */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + /* lame, but we don't want the count to exceed 255, + * so just count to 2, its all we need */ + unsigned char *vt; + vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; + vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; + } + } + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + if (vtouch[BM_elem_index_get(e->v1)] == 1 && + vtouch[BM_elem_index_get(e->v2)] == 1) + { + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + } + } + + MEM_freeN(vtouch); +} + +void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only) +{ + BMIter iter; + BMEdge *e; + + + if (tag_only == FALSE) { + BM_mesh_elem_hflag_enable_all(bm, BM_EDGE | (use_verts ? BM_VERT : 0), BM_ELEM_TAG, FALSE); + } + + if (use_verts) { + /* prevent one edge having both verts unflagged + * we could alternately disable these edges, either way its a corner case. + * + * This is needed so we don't split off the edge but then none of its verts which + * would leave a duplicate edge. + */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + if (UNLIKELY(((BM_elem_flag_test(e->v1, BM_ELEM_TAG) == FALSE) && + (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == FALSE)))) + { + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + } + } + } + } + + bm_edgesplit_validate_seams(bm); + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + /* this flag gets copied so we can be sure duplicate edges get it too (important) */ + BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG); + + /* keep splitting until each loop has its own edge */ + do { + bmesh_edge_separate(bm, e, e->l); + } while (!BM_edge_is_boundary(e)); + + BM_elem_flag_enable(e->v1, BM_ELEM_TAG); + BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + } + } + + if (use_verts) { + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e->v1, BM_ELEM_TAG) == FALSE) { + BM_elem_flag_disable(e->v1, BM_ELEM_TAG); + } + if (BM_elem_flag_test(e->v2, BM_ELEM_TAG) == FALSE) { + BM_elem_flag_disable(e->v2, BM_ELEM_TAG); + } + } + } + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { + if (BM_elem_flag_test(e->v1, BM_ELEM_TAG)) { + BM_elem_flag_disable(e->v1, BM_ELEM_TAG); + bmesh_vert_separate(bm, e->v1, NULL, NULL); + } + if (BM_elem_flag_test(e->v2, BM_ELEM_TAG)) { + BM_elem_flag_disable(e->v2, BM_ELEM_TAG); + bmesh_vert_separate(bm, e->v2, NULL, NULL); + } + } + } +} diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.h b/source/blender/bmesh/tools/bmesh_edgesplit.h new file mode 100644 index 00000000000..687fdac0e00 --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_edgesplit.h @@ -0,0 +1,32 @@ +/* + * ***** 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): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BMESH_EDGESPLIT_H__ +#define __BMESH_EDGESPLIT_H__ + +/** \file blender/bmesh/tools/bmesh_edgesplit.h + * \ingroup bmesh + */ + +void BM_mesh_edgesplit(BMesh *bm, const int use_verts, const int tag_only); + +#endif /* __BMESH_EDGESPLIT_H__ */ |