diff options
Diffstat (limited to 'source/blender/bmesh')
22 files changed, 724 insertions, 507 deletions
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index 2a23658f5d0..c41b0703240 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -111,6 +111,8 @@ set(SRC tools/bmesh_decimate_dissolve.c tools/bmesh_decimate_unsubdivide.c tools/bmesh_decimate.h + tools/bmesh_edgesplit.c + tools/bmesh_edgesplit.h bmesh.h bmesh_class.h diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript index 6765d57cb3e..722b7518630 100644 --- a/source/blender/bmesh/SConscript +++ b/source/blender/bmesh/SConscript @@ -1,4 +1,30 @@ -#!/usr/bin/python +#!/usr/bin/env python +# +# ***** 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. +# +# The Original Code is Copyright (C) 2006, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Nathan Letwory. +# +# ***** END GPL LICENSE BLOCK ***** + Import ('env') cflags='' diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index bcd6780b675..a2613f46bf8 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -187,8 +187,9 @@ typedef struct BMesh { /*element pools*/ struct BLI_mempool *vpool, *epool, *lpool, *fpool; - /*operator api stuff*/ - struct BLI_mempool *toolflagpool; + /*operator api stuff (must be all NULL or all alloc'd)*/ + struct BLI_mempool *vtoolflagpool, *etoolflagpool, *ftoolflagpool; + int stackdepth; struct BMOperator *currentop; @@ -277,5 +278,6 @@ enum { * but should not error on valid cases */ #define BM_LOOP_RADIAL_MAX 10000 #define BM_NGON_MAX 100000 +#define BM_OMP_LIMIT 10000 #endif /* __BMESH_CLASS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index 50f02b12dca..229a7caebfd 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -173,15 +173,17 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) */ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, const int create_flag) { - BMEdge **edges2 = NULL; - BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE); - BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); + BMEdge **edges2 = BLI_array_alloca_and_count(edges2, len); + BMVert **verts = BLI_array_alloca_and_count(verts, len + 1); + int e2_index = 0; + int v_index = 0; + BMFace *f = NULL; BMEdge *e; BMVert *v, *ev1, *ev2; int i, /* j, */ v1found, reverse; + /* this code is hideous, yeek. I'll have to think about ways of * cleaning it up. basically, it now combines the old BM_face_create_ngon * _and_ the old bmesh_mf functions, so its kindof smashed together @@ -207,14 +209,14 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i SWAP(BMVert *, ev1, ev2); } - BLI_array_append(verts, ev1); + verts[v_index++] = ev1; v = ev2; e = edges[0]; do { BMEdge *e2 = e; - BLI_array_append(verts, v); - BLI_array_append(edges2, e); + verts[v_index++] = v; + edges2[e2_index++] = e; /* we only flag the verts to check if they are in the face more then once */ BM_ELEM_API_FLAG_ENABLE(v, _FLAG_MV); @@ -289,9 +291,6 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i BM_ELEM_API_FLAG_DISABLE(edges2[i], _FLAG_MF); } - BLI_array_free(verts); - BLI_array_free(edges2); - return f; err: @@ -303,9 +302,6 @@ err: } } - BLI_array_free(verts); - BLI_array_free(edges2); - return NULL; } diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 14fab7abdc9..ea9ab364b84 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -78,9 +78,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons copy_v3_v3(v->co, co); } - /* allocate flag */ - if (bm->toolflagpool) { - v->oflags = BLI_mempool_calloc(bm->toolflagpool); + /* allocate flags */ + if (bm->vtoolflagpool) { + v->oflags = BLI_mempool_calloc(bm->vtoolflagpool); } if (!(create_flag & BM_CREATE_SKIP_CD)) { @@ -132,9 +132,9 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, e->head.htype = BM_EDGE; - /* allocate flag */ - if (bm->toolflagpool) { - e->oflags = BLI_mempool_calloc(bm->toolflagpool); + /* allocate flags */ + if (bm->etoolflagpool) { + e->oflags = BLI_mempool_calloc(bm->etoolflagpool); } e->v1 = v1; @@ -211,10 +211,8 @@ static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges) { - BMVert **verts = NULL; - BMEdge **edges = NULL; - BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); - BLI_array_fixedstack_declare(edges, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); + BMVert **verts = BLI_array_alloca(verts, f->len); + BMEdge **edges = BLI_array_alloca(edges, f->len); BMLoop *l_iter; BMLoop *l_first; BMLoop *l_copy; @@ -267,9 +265,6 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co l_copy = l_copy->next; } while ((l_iter = l_iter->next) != l_first); - BLI_array_fixedstack_free(verts); - BLI_array_fixedstack_free(edges); - return f_copy; } @@ -295,9 +290,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag creat f->head.htype = BM_FACE; - /* allocate flag */ - if (bm->toolflagpool) { - f->oflags = BLI_mempool_calloc(bm->toolflagpool); + /* allocate flags */ + if (bm->ftoolflagpool) { + f->oflags = BLI_mempool_calloc(bm->ftoolflagpool); } if (!(create_flag & BM_CREATE_SKIP_CD)) { @@ -321,7 +316,7 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int i, overlap; if (len == 0) { - /* just return NULL for no */ + /* just return NULL for now */ return NULL; } @@ -517,8 +512,8 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v) if (v->head.data) CustomData_bmesh_free_block(&bm->vdata, &v->head.data); - if (bm->toolflagpool) { - BLI_mempool_free(bm->toolflagpool, v->oflags); + if (bm->vtoolflagpool) { + BLI_mempool_free(bm->vtoolflagpool, v->oflags); } BLI_mempool_free(bm->vpool, v); } @@ -537,8 +532,8 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e) if (e->head.data) CustomData_bmesh_free_block(&bm->edata, &e->head.data); - if (bm->toolflagpool) { - BLI_mempool_free(bm->toolflagpool, e->oflags); + if (bm->etoolflagpool) { + BLI_mempool_free(bm->etoolflagpool, e->oflags); } BLI_mempool_free(bm->epool, e); } @@ -560,8 +555,8 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f) if (f->head.data) CustomData_bmesh_free_block(&bm->pdata, &f->head.data); - if (bm->toolflagpool) { - BLI_mempool_free(bm->toolflagpool, f->oflags); + if (bm->ftoolflagpool) { + BLI_mempool_free(bm->ftoolflagpool, f->oflags); } BLI_mempool_free(bm->fpool, f); } @@ -585,22 +580,19 @@ static void bm_kill_only_loop(BMesh *bm, BMLoop *l) */ void BM_face_edges_kill(BMesh *bm, BMFace *f) { - BMEdge **edges = NULL; - BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); + BMEdge **edges = BLI_array_alloca_and_count(edges, f->len); BMLoop *l_iter; BMLoop *l_first; - int i; + int i = 0; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - BLI_array_append(edges, l_iter->e); + edges[i++] = l_iter->e; } while ((l_iter = l_iter->next) != l_first); for (i = 0; i < BLI_array_count(edges); i++) { BM_edge_kill(bm, edges[i]); } - - BLI_array_free(edges); } /** @@ -609,22 +601,19 @@ void BM_face_edges_kill(BMesh *bm, BMFace *f) */ void BM_face_verts_kill(BMesh *bm, BMFace *f) { - BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); + BMVert **verts = BLI_array_alloca_and_count(verts, f->len); BMLoop *l_iter; BMLoop *l_first; - int i; + int i = 0; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - BLI_array_append(verts, l_iter->v); + verts[i++] = l_iter->v; } while ((l_iter = l_iter->next) != l_first); for (i = 0; i < BLI_array_count(verts); i++) { BM_vert_kill(bm, verts[i]); } - - BLI_array_free(verts); } /** @@ -761,8 +750,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f const int len = f->len; const int do_disps = CustomData_has_layer(&bm->ldata, CD_MDISPS); BMLoop *l_iter, *oldprev, *oldnext; - BMEdge **edar = NULL; - BLI_array_fixedstack_declare(edar, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); + BMEdge **edar = BLI_array_alloca(edar, len); int i, j, edok; for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { @@ -814,11 +802,11 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f } } } - /* rebuild radia */ + /* rebuild radial */ for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) bmesh_radial_append(l_iter->e, l_iter); - /* validate radia */ + /* validate radial */ for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { BM_CHECK_ELEMENT(l_iter); BM_CHECK_ELEMENT(l_iter->e); @@ -826,8 +814,6 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f BM_CHECK_ELEMENT(l_iter->f); } - BLI_array_fixedstack_free(edar); - BM_CHECK_ELEMENT(f); return 1; @@ -1068,7 +1054,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del } while (l2 != l_iter); if (l2 != l_iter) { - /* I think this is correct */ + /* I think this is correct? */ if (l2->v != l_iter->v) { l2 = l2->next; } @@ -1080,7 +1066,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del BM_elem_attrs_copy(bm, bm, faces[0], newf); #ifdef USE_BMESH_HOLES - /* add hole */ + /* add holes */ BLI_movelisttolist(&newf->loops, &holes); #endif @@ -1396,7 +1382,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) /* add ne to tv's disk cycle */ bmesh_disk_edge_append(ne, tv); - /* verify disk cycle */ + /* verify disk cycles */ edok = bmesh_disk_validate(valence1, ov->e, ov); BMESH_ASSERT(edok != FALSE); edok = bmesh_disk_validate(valence2, tv->e, tv); @@ -1483,7 +1469,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) BMESH_ASSERT(l->v != l->next->v); BMESH_ASSERT(l->e != l->next->e); - /* verify loop cycle for kloop-> */ + /* verify loop cycle for kloop->f */ BM_CHECK_ELEMENT(l); BM_CHECK_ELEMENT(l->v); BM_CHECK_ELEMENT(l->e); @@ -1564,7 +1550,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou oe = bmesh_disk_edge_next(ke, kv); tv = bmesh_edge_other_vert_get(ke, kv); ov = bmesh_edge_other_vert_get(oe, kv); - halt = bmesh_verts_in_edge(kv, tv, oe); /* check for double edge */ + halt = bmesh_verts_in_edge(kv, tv, oe); /* check for double edges */ if (halt) { return NULL; @@ -1572,7 +1558,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou else { BMEdge *e_splice; - /* For verification later, count valence of ov and t */ + /* For verification later, count valence of ov and tv */ valence1 = bmesh_disk_count(ov); valence2 = bmesh_disk_count(tv); @@ -1614,8 +1600,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou radlen = bmesh_radial_length(ke->l); if (LIKELY(radlen)) { - BMLoop **loops = NULL; - BLI_array_fixedstack_declare(loops, BM_DEFAULT_NGON_STACK_SIZE, radlen, __func__); + BMLoop **loops = BLI_array_alloca(loops, radlen); killoop = ke->l; @@ -1628,7 +1613,6 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou bm->totloop--; BLI_mempool_free(bm->lpool, loops[i]); } - BLI_array_fixedstack_free(loops); } /* Validate radial cycle of oe */ @@ -1801,8 +1785,8 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2); /* deallocate edge and its two loops as well as f2 */ - if (bm->toolflagpool) { - BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + if (bm->etoolflagpool) { + BLI_mempool_free(bm->etoolflagpool, f1loop->e->oflags); } BLI_mempool_free(bm->epool, f1loop->e); bm->totedge--; @@ -1810,8 +1794,8 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) bm->totloop--; BLI_mempool_free(bm->lpool, f2loop); bm->totloop--; - if (bm->toolflagpool) { - BLI_mempool_free(bm->toolflagpool, f2->oflags); + if (bm->ftoolflagpool) { + BLI_mempool_free(bm->ftoolflagpool, f2->oflags); } BLI_mempool_free(bm->fpool, f2); bm->totface--; @@ -1895,7 +1879,7 @@ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) int bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len) { BMEdge **stack = NULL; - BLI_array_declare(stack); + BLI_array_staticdeclare(stack, BM_DEFAULT_ITER_STACK_SIZE); BMVert **verts = NULL; GHash *visithash; BMIter eiter, liter; diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index caf9f3c70d5..df58b90bc03 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -172,11 +172,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source) BMLoop *l_iter; BMLoop *l_first; - void **blocks = NULL; - float (*cos)[3] = NULL, *w = NULL; - BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); + void **blocks = BLI_array_alloca(blocks, source->len); + float (*cos)[3] = BLI_array_alloca(cos, source->len); + float *w = BLI_array_alloca(w, source->len); int i; BM_elem_attrs_copy(bm, bm, source, target); @@ -196,10 +194,6 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source) CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, l_iter->head.data); i++; } while ((l_iter = l_iter->next) != l_first); - - BLI_array_fixedstack_free(cos); - BLI_array_fixedstack_free(w); - BLI_array_fixedstack_free(blocks); } /** @@ -609,14 +603,12 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, { BMLoop *l_iter; BMLoop *l_first; - void **blocks = NULL; - void **vblocks = NULL; - float (*cos)[3] = NULL, co[3], *w = NULL; + void **vblocks = BLI_array_alloca(vblocks, do_vertex ? source->len : 0); + void **blocks = BLI_array_alloca(blocks, source->len); + float (*cos)[3] = BLI_array_alloca(cos, source->len); + float *w = BLI_array_alloca(w, source->len); + float co[3]; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(vblocks, BM_DEFAULT_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); int i, ax, ay; BM_elem_attrs_copy(bm, bm, source, target->f); @@ -667,13 +659,8 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, CustomData_bmesh_interp(&bm->ldata, blocks, w, NULL, source->len, target->head.data); if (do_vertex) { CustomData_bmesh_interp(&bm->vdata, vblocks, w, NULL, source->len, target->v->head.data); - BLI_array_fixedstack_free(vblocks); } - BLI_array_fixedstack_free(cos); - BLI_array_fixedstack_free(w); - BLI_array_fixedstack_free(blocks); - if (do_multires) { if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) { bm_loop_interp_mdisps(bm, target, source); @@ -686,12 +673,10 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source) { BMLoop *l_iter; BMLoop *l_first; - void **blocks = NULL; - float (*cos)[3] = NULL, *w = NULL; + void **blocks = BLI_array_alloca(blocks, source->len); + float (*cos)[3] = BLI_array_alloca(cos, source->len); + float *w = BLI_array_alloca(w, source->len); float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_DEFAULT_NGON_STACK_SIZE, source->len, __func__); int i; i = 0; @@ -718,10 +703,6 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source) /* interpolate */ interp_weights_poly_v3(w, cos, source->len, v->co); CustomData_bmesh_interp(&bm->vdata, blocks, w, NULL, source->len, v->head.data); - - BLI_array_fixedstack_free(cos); - BLI_array_fixedstack_free(w); - BLI_array_fixedstack_free(blocks); } static void update_data_blocks(BMesh *bm, CustomData *olddata, CustomData *data) diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 9af65d7dd7e..b1ec4cde44b 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -44,8 +44,6 @@ static void recount_totsels(BMesh *bm) { - BMIter iter; - BMElem *ele; const char iter_types[3] = {BM_VERTS_OF_MESH, BM_EDGES_OF_MESH, BM_FACES_OF_MESH}; @@ -58,11 +56,16 @@ static void recount_totsels(BMesh *bm) tots[1] = &bm->totedgesel; tots[2] = &bm->totfacesel; +#pragma omp parallel for schedule(dynamic) for (i = 0; i < 3; i++) { - ele = BM_iter_new(&iter, bm, iter_types[i], NULL); - for ( ; ele; ele = BM_iter_step(&iter)) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) *tots[i] += 1; + BMIter iter; + BMElem *ele; + int count = 0; + + BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) count += 1; } + *tots[i] = count; } } @@ -161,34 +164,45 @@ void BM_mesh_deselect_flush(BMesh *bm) int ok; - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (!(BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && - BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && - !BM_elem_flag_test(e, BM_ELEM_HIDDEN))) + /* we can use 2 sections here because the second loop isnt checking edge selection */ +#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section { - BM_elem_flag_disable(e, BM_ELEM_SELECT); + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (!(BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && + BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && + !BM_elem_flag_test(e, BM_ELEM_HIDDEN))) + { + BM_elem_flag_disable(e, BM_ELEM_SELECT); + } + } } - } - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - ok = TRUE; - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { +#pragma omp section + { + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + ok = TRUE; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { + ok = FALSE; + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + else { ok = FALSE; - break; } - } while ((l_iter = l_iter->next) != l_first); - } - else { - ok = FALSE; - } - if (ok == FALSE) { - BM_elem_flag_disable(f, BM_ELEM_SELECT); + if (ok == FALSE) { + BM_elem_flag_disable(f, BM_ELEM_SELECT); + } + } } } + /* end sections */ /* Remove any deselected elements from the BMEditSelection */ BM_select_history_validate(bm); @@ -212,32 +226,42 @@ void BM_mesh_select_flush(BMesh *bm) int ok; - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && - BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && - !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) + /* we can use 2 sections here because the second loop isnt checking edge selection */ +#pragma omp parallel sections if (bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section { - BM_elem_flag_enable(e, BM_ELEM_SELECT); + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e->v1, BM_ELEM_SELECT) && + BM_elem_flag_test(e->v2, BM_ELEM_SELECT) && + !BM_elem_flag_test(e, BM_ELEM_HIDDEN)) + { + BM_elem_flag_enable(e, BM_ELEM_SELECT); + } + } } - } - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - ok = TRUE; - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { +#pragma omp section + { + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + ok = TRUE; + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (!BM_elem_flag_test(l_iter->v, BM_ELEM_SELECT)) { + ok = FALSE; + break; + } + } while ((l_iter = l_iter->next) != l_first); + } + else { ok = FALSE; - break; } - } while ((l_iter = l_iter->next) != l_first); - } - else { - ok = FALSE; - } - if (ok) { - BM_elem_flag_enable(f, BM_ELEM_SELECT); + if (ok) { + BM_elem_flag_enable(f, BM_ELEM_SELECT); + } + } } } @@ -810,8 +834,6 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl const char flag_types[3] = {BM_VERT, BM_EDGE, BM_FACE}; - BMIter iter; - BMElem *ele; int i; if (hflag & BM_ELEM_SELECT) { @@ -825,16 +847,25 @@ void BM_mesh_elem_hflag_disable_test(BMesh *bm, const char htype, const char hfl { /* fast path for deselect all, avoid topology loops * since we know all will be de-selected anyway. */ + +#pragma omp parallel for schedule(dynamic) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) for (i = 0; i < 3; i++) { + BMIter iter; + BMElem *ele; + ele = BM_iter_new(&iter, bm, iter_types[i], NULL); for ( ; ele; ele = BM_iter_step(&iter)) { BM_elem_flag_disable(ele, BM_ELEM_SELECT); } } + bm->totvertsel = bm->totedgesel = bm->totfacesel = 0; } else { for (i = 0; i < 3; i++) { + BMIter iter; + BMElem *ele; + if (htype & flag_types[i]) { ele = BM_iter_new(&iter, bm, iter_types[i], NULL); for ( ; ele; ele = BM_iter_step(&iter)) { diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 590edc45d07..015c040dc95 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -63,40 +63,62 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) void BM_mesh_elem_toolflags_ensure(BMesh *bm) { - if (bm->toolflagpool == NULL) { - const int totflagpool_size = max_ii(512, bm->totvert + bm->totedge + bm->totface); - BLI_mempool *toolflagpool; - - BMIter iter; - BMElemF *ele; - const char iter_types[3] = {BM_VERTS_OF_MESH, - BM_EDGES_OF_MESH, - BM_FACES_OF_MESH}; - - int i; - - BLI_assert(bm->totflags == 0); - - /* allocate one flag pool that we don't get rid of. */ - toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), totflagpool_size, 512, 0); - + if (bm->vtoolflagpool && bm->etoolflagpool && bm->ftoolflagpool) { + return; + } - for (i = 0; i < 3; i++) { - BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totvert), 512, 0); + bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totedge), 512, 0); + bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), max_ii(512, bm->totface), 512, 0); + +#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section + { + BLI_mempool *toolflagpool = bm->vtoolflagpool; + BMIter iter; + BMElemF *ele; + BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { + ele->oflags = BLI_mempool_calloc(toolflagpool); + } + } +#pragma omp section + { + BLI_mempool *toolflagpool = bm->etoolflagpool; + BMIter iter; + BMElemF *ele; + BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { + ele->oflags = BLI_mempool_calloc(toolflagpool); + } + } +#pragma omp section + { + BLI_mempool *toolflagpool = bm->ftoolflagpool; + BMIter iter; + BMElemF *ele; + BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { ele->oflags = BLI_mempool_calloc(toolflagpool); } } - - bm->toolflagpool = toolflagpool; - bm->totflags = 1; } + + + bm->totflags = 1; } void BM_mesh_elem_toolflags_clear(BMesh *bm) { - if (bm->toolflagpool) { - BLI_mempool_destroy(bm->toolflagpool); - bm->toolflagpool = NULL; + if (bm->vtoolflagpool) { + BLI_mempool_destroy(bm->vtoolflagpool); + bm->vtoolflagpool = NULL; + } + if (bm->etoolflagpool) { + BLI_mempool_destroy(bm->etoolflagpool); + bm->etoolflagpool = NULL; + } + if (bm->ftoolflagpool) { + BLI_mempool_destroy(bm->ftoolflagpool); + bm->ftoolflagpool = NULL; } } @@ -446,50 +468,58 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag) BM_ELEM_INDEX_VALIDATE(bm, "Should Never Fail!", __func__); #endif - if (hflag & BM_VERT) { - if (bm->elem_index_dirty & BM_VERT) { - int index = 0; - BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_index_set(ele, index); /* set_ok */ - index++; +#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section + { + if (hflag & BM_VERT) { + if (bm->elem_index_dirty & BM_VERT) { + int index; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, index) { + BM_elem_index_set(ele, index); /* set_ok */ + } + BLI_assert(index == bm->totvert); + } + else { + // printf("%s: skipping vert index calc!\n", __func__); + } } - bm->elem_index_dirty &= ~BM_VERT; - BLI_assert(index == bm->totvert); } - else { - // printf("%s: skipping vert index calc!\n", __func__); - } - } - if (hflag & BM_EDGE) { - if (bm->elem_index_dirty & BM_EDGE) { - int index = 0; - BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - BM_elem_index_set(ele, index); /* set_ok */ - index++; +#pragma omp section + { + if (hflag & BM_EDGE) { + if (bm->elem_index_dirty & BM_EDGE) { + int index; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, index) { + BM_elem_index_set(ele, index); /* set_ok */ + } + BLI_assert(index == bm->totedge); + } + else { + // printf("%s: skipping edge index calc!\n", __func__); + } } - bm->elem_index_dirty &= ~BM_EDGE; - BLI_assert(index == bm->totedge); - } - else { - // printf("%s: skipping edge index calc!\n", __func__); } - } - if (hflag & BM_FACE) { - if (bm->elem_index_dirty & BM_FACE) { - int index = 0; - BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - BM_elem_index_set(ele, index); /* set_ok */ - index++; +#pragma omp section + { + if (hflag & BM_FACE) { + if (bm->elem_index_dirty & BM_FACE) { + int index; + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, index) { + BM_elem_index_set(ele, index); /* set_ok */ + } + BLI_assert(index == bm->totface); + } + else { + // printf("%s: skipping face index calc!\n", __func__); + } } - bm->elem_index_dirty &= ~BM_FACE; - BLI_assert(index == bm->totface); - } - else { - // printf("%s: skipping face index calc!\n", __func__); } } + + bm->elem_index_dirty &= ~hflag; } diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 89516061f91..9a99d5b96d1 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -152,14 +152,14 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) return TRUE; } else if (keepedge == NULL && len == 2) { - /* collapse the verte */ + /* collapse the vertex */ e = BM_vert_collapse_faces(bm, v->e, v, 1.0, TRUE, TRUE); if (!e) { return FALSE; } - /* handle two-valenc */ + /* handle two-valence */ f = e->l->f; f2 = e->l->radial_next->f; @@ -205,12 +205,12 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) return FALSE; } - /* get remaining two face */ + /* get remaining two faces */ f = e->l->f; f2 = e->l->radial_next->f; if (f != f2) { - /* join two remaining face */ + /* join two remaining faces */ if (!BM_faces_join_pair(bm, f, f2, e, TRUE)) { return FALSE; } @@ -343,7 +343,7 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l BLI_assert(v1 != v2); - /* do we have a multires layer */ + /* do we have a multires layer? */ if (has_mdisp) { of = BM_face_copy(bm, f, FALSE, FALSE); } @@ -641,7 +641,6 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce BMFace **oldfaces = NULL; BMEdge *e_dummy; BLI_array_staticdeclare(oldfaces, 32); - SmallHash hash; const int do_mdisp = (e->l && CustomData_has_layer(&bm->ldata, CD_MDISPS)); /* we need this for handling multi-res */ @@ -649,7 +648,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce r_e = &e_dummy; } - /* do we have a multi-res layer */ + /* do we have a multi-res layer? */ if (do_mdisp) { BMLoop *l; int i; @@ -660,12 +659,11 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce l = l->radial_next; } while (l != e->l); - /* create a hash so we can differentiate oldfaces from new face */ - BLI_smallhash_init(&hash); - + /* flag existing faces so we can differentiate oldfaces from new faces */ for (i = 0; i < BLI_array_count(oldfaces); i++) { + BM_ELEM_API_FLAG_ENABLE(oldfaces[i], _FLAG_OVERLAP); oldfaces[i] = BM_face_copy(bm, oldfaces[i], TRUE, TRUE); - BLI_smallhash_insert(&hash, (intptr_t)oldfaces[i], NULL); + BM_ELEM_API_FLAG_DISABLE(oldfaces[i], _FLAG_OVERLAP); } } @@ -689,7 +687,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce if (do_mdisp) { int i, j; - /* interpolate new/changed loop data from copied old face */ + /* interpolate new/changed loop data from copied old faces */ for (j = 0; j < 2; j++) { for (i = 0; i < BLI_array_count(oldfaces); i++) { BMEdge *e1 = j ? *r_e : e; @@ -703,7 +701,8 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce } do { - if (!BLI_smallhash_haskey(&hash, (intptr_t)l->f)) { + /* check this is an old face */ + if (BM_ELEM_API_FLAG_TEST(l->f, _FLAG_OVERLAP)) { BMLoop *l2_first; l2 = l2_first = BM_FACE_FIRST_LOOP(l->f); @@ -716,7 +715,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce } } - /* destroy the old face */ + /* destroy the old faces */ for (i = 0; i < BLI_array_count(oldfaces); i++) { BM_face_verts_kill(bm, oldfaces[i]); } @@ -741,7 +740,6 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce #endif BLI_array_free(oldfaces); - BLI_smallhash_release(&hash); } return nv; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 58c6e051e48..3a7a1c4eaaa 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -339,7 +339,7 @@ static BMOpDefine bmo_automerge_def = { static BMOpDefine bmo_collapse_def = { "collapse", /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -374,7 +374,7 @@ static BMOpDefine bmo_pointmerge_facedata_def = { static BMOpDefine bmo_average_vert_facedata_def = { "average_vert_facedata", /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -390,7 +390,7 @@ static BMOpDefine bmo_average_vert_facedata_def = { static BMOpDefine bmo_pointmerge_def = { "pointmerge", /* slots_in */ - {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertice */ + {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input vertices */ {"merge_co", BMO_OP_SLOT_VEC}, {{'\0'}}, }, @@ -407,7 +407,7 @@ static BMOpDefine bmo_pointmerge_def = { static BMOpDefine bmo_collapse_uvs_def = { "collapse_uvs", /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ {{'\0'}}, }, {{{'\0'}}}, /* no output */ @@ -513,7 +513,7 @@ static BMOpDefine bmo_contextual_create_def = { static BMOpDefine bmo_bridge_loops_def = { "bridge_loops", /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ {"use_merge", BMO_OP_SLOT_BOOL}, {"merge_factor", BMO_OP_SLOT_FLT}, {{'\0'}}, @@ -534,7 +534,7 @@ static BMOpDefine bmo_bridge_loops_def = { static BMOpDefine bmo_edgenet_fill_def = { "edgenet_fill", /* slots_in */ - {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edge */ + {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ /* restricts edges to groups. maps edges to integer */ {"restrict", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_BOOL}}, {"use_restrict", BMO_OP_SLOT_BOOL}, @@ -547,7 +547,7 @@ static BMOpDefine bmo_edgenet_fill_def = { /* slots_out */ /* maps new faces to the group numbers they came from */ {{"face_groupmap.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, - {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new face */ + {"faces.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* new faces */ {{'\0'}}, }, bmo_edgenet_fill_exec, @@ -962,7 +962,7 @@ static BMOpDefine bmo_subdivide_edges_def = { {/* these next three can have multiple types of elements in them */ {"geom_inner.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, {"geom_split.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, - {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometr */ + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* contains all output geometry */ {{'\0'}}, }, bmo_subdivide_edges_exec, diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 5e51f5a5ada..fbf51b7dfdf 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -599,6 +599,7 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty BMElemF *ele; int i; +#pragma omp parallel for schedule(dynamic) if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) for (i = 0; i < 3; i++) { if (htype & flag_types[i]) { BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { @@ -1159,100 +1160,161 @@ void BMO_slot_buffer_flag_disable(BMesh *bm, */ static void bmo_flag_layer_alloc(BMesh *bm) { - BMElemF *ele; /* set the index values since we are looping over all data anyway, * may save time later on */ - int i; - BMIter iter; - BLI_mempool *oldpool = bm->toolflagpool; /* old flag pool */ - BLI_mempool *newpool; - void *oldflags; + BLI_mempool *voldpool = bm->vtoolflagpool; /* old flag pool */ + BLI_mempool *eoldpool = bm->etoolflagpool; /* old flag pool */ + BLI_mempool *foldpool = bm->ftoolflagpool; /* old flag pool */ /* store memcpy size for reuse */ const size_t old_totflags_size = (bm->totflags * sizeof(BMFlagLayer)); - BLI_assert(oldpool != NULL); - bm->totflags++; - /* allocate new flag poo */ - bm->toolflagpool = newpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, 512, 512, 0); - - /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */ - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, old_totflags_size); - BM_elem_index_set(ele, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, old_totflags_size); - BM_elem_index_set(ele, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, old_totflags_size); - BM_elem_index_set(ele, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + bm->vtoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, max_ii(512, bm->totvert), 512, 0); + bm->etoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, max_ii(512, bm->totedge), 512, 0); + bm->ftoolflagpool = BLI_mempool_create(sizeof(BMFlagLayer) * bm->totflags, max_ii(512, bm->totface), 512, 0); + +#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section + { + BMIter iter; + BMElemF *ele; + int i; + + BLI_mempool *newpool = bm->vtoolflagpool; + + /* now go through and memcpy all the flags. Loops don't get a flag layer at this time.. */ + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { + void *oldflags = ele->oflags; + ele->oflags = BLI_mempool_calloc(newpool); + memcpy(ele->oflags, oldflags, old_totflags_size); + BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + } + } +#pragma omp section + { + BMIter iter; + BMElemF *ele; + int i; + + BLI_mempool *newpool = bm->etoolflagpool; + + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { + void *oldflags = ele->oflags; + ele->oflags = BLI_mempool_calloc(newpool); + memcpy(ele->oflags, oldflags, old_totflags_size); + BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + } + } +#pragma omp section + { + BMIter iter; + BMElemF *ele; + int i; + + BLI_mempool *newpool = bm->ftoolflagpool; + + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { + void *oldflags = ele->oflags; + ele->oflags = BLI_mempool_calloc(newpool); + memcpy(ele->oflags, oldflags, old_totflags_size); + BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + } + } } + BLI_mempool_destroy(voldpool); + BLI_mempool_destroy(eoldpool); + BLI_mempool_destroy(foldpool); + bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); - BLI_mempool_destroy(oldpool); + } static void bmo_flag_layer_free(BMesh *bm) { - BMElemF *ele; /* set the index values since we are looping over all data anyway, * may save time later on */ - int i; - BMIter iter; - BLI_mempool *oldpool = bm->toolflagpool; - BLI_mempool *newpool; - void *oldflags; - + BLI_mempool *voldpool = bm->vtoolflagpool; + BLI_mempool *eoldpool = bm->etoolflagpool; + BLI_mempool *foldpool = bm->ftoolflagpool; + /* store memcpy size for reuse */ const size_t new_totflags_size = ((bm->totflags - 1) * sizeof(BMFlagLayer)); /* de-increment the totflags first.. */ bm->totflags--; - /* allocate new flag poo */ - bm->toolflagpool = newpool = BLI_mempool_create(new_totflags_size, 512, 512, 0); - - /* now go through and memcpy all the flag */ - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, new_totflags_size); - BM_elem_index_set(ele, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, new_totflags_size); - BM_elem_index_set(ele, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); - } - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - oldflags = ele->oflags; - ele->oflags = BLI_mempool_calloc(newpool); - memcpy(ele->oflags, oldflags, new_totflags_size); - BM_elem_index_set(ele, i); /* set_inline */ - BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + + bm->vtoolflagpool = BLI_mempool_create(new_totflags_size, bm->totvert, 512, 0); + bm->etoolflagpool = BLI_mempool_create(new_totflags_size, bm->totedge, 512, 0); + bm->ftoolflagpool = BLI_mempool_create(new_totflags_size, bm->totface, 512, 0); + +#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + { +#pragma omp section + { + BMIter iter; + BMElemF *ele; + int i; + + BLI_mempool *newpool = bm->vtoolflagpool; + + /* now go through and memcpy all the flag */ + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { + void *oldflags = ele->oflags; + ele->oflags = BLI_mempool_calloc(newpool); + memcpy(ele->oflags, oldflags, new_totflags_size); + BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + } + } +#pragma omp section + { + BMIter iter; + BMElemF *ele; + int i; + + BLI_mempool *newpool = bm->etoolflagpool; + + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { + void *oldflags = ele->oflags; + ele->oflags = BLI_mempool_calloc(newpool); + memcpy(ele->oflags, oldflags, new_totflags_size); + BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + } + } +#pragma omp section + { + BMIter iter; + BMElemF *ele; + int i; + + BLI_mempool *newpool = bm->ftoolflagpool; + + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { + void *oldflags = ele->oflags; + ele->oflags = BLI_mempool_calloc(newpool); + memcpy(ele->oflags, oldflags, new_totflags_size); + BM_elem_index_set(ele, i); /* set_inline */ + BM_ELEM_API_FLAG_CLEAR((BMElemF *)ele); + } + } } - bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); + BLI_mempool_destroy(voldpool); + BLI_mempool_destroy(eoldpool); + BLI_mempool_destroy(foldpool); - BLI_mempool_destroy(oldpool); + bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } static void bmo_flag_layer_clear(BMesh *bm) @@ -1261,22 +1323,35 @@ static void bmo_flag_layer_clear(BMesh *bm) /* set the index values since we are looping over all data anyway, * may save time later on */ int i; + const BMFlagLayer zero_flag = {0}; BMIter iter; const int totflags_offset = bm->totflags - 1; - /* now go through and memcpy all the flag */ - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { - memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer)); - BM_elem_index_set(ele, i); /* set_inline */ - } - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { - memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer)); - BM_elem_index_set(ele, i); /* set_inline */ - } - BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { - memset(ele->oflags + totflags_offset, 0, sizeof(BMFlagLayer)); - BM_elem_index_set(ele, i); /* set_inline */ +#pragma omp parallel sections if (bm->totvert + bm->totedge + bm->totface >= BM_OMP_LIMIT) + { + /* now go through and memcpy all the flag */ +#pragma omp section + { + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(ele, i); /* set_inline */ + } + } +#pragma omp section + { + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(ele, i); /* set_inline */ + } + } +#pragma omp section + { + BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, i) { + ele->oflags[totflags_offset] = zero_flag; + BM_elem_index_set(ele, i); /* set_inline */ + } + } } bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1364,7 +1439,7 @@ void *BMO_iter_step(BMOIter *iter) return NULL; } -/* used for iterating over mapping */ +/* used for iterating over mappings */ void *BMO_iter_map_value(BMOIter *iter) { return iter->val; @@ -1380,7 +1455,7 @@ float BMO_iter_map_value_f(BMOIter *iter) return *((float *)iter->val); } -/* error syste */ +/* error system */ typedef struct BMOpError { struct BMOpError *next, *prev; int errorcode; @@ -1562,7 +1637,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v goto error; \ } (void)0 - /* we muck around in here, so dup i */ + /* we muck around in here, so dup it */ fmt = ofmt = BLI_strdup(_fmt); /* find operator name */ @@ -1589,11 +1664,11 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v while (*fmt) { if (state) { - /* jump past leading whitespac */ + /* jump past leading whitespace */ i = strspn(fmt, " "); fmt += i; - /* ignore trailing whitespac */ + /* ignore trailing whitespace */ if (!fmt[i]) break; diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 2e0471863d4..953e7f4d20c 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -157,13 +157,11 @@ float BM_face_calc_area(BMFace *f) { BMLoop *l; BMIter iter; - float (*verts)[3]; + float (*verts)[3] = BLI_array_alloca(verts, f->len); float normal[3]; float area; int i; - BLI_array_fixedstack_declare(verts, BM_DEFAULT_NGON_STACK_SIZE, f->len, __func__); - BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) { copy_v3_v3(verts[i], l->v->co); } @@ -179,8 +177,6 @@ float BM_face_calc_area(BMFace *f) area = area_poly_v3(f->len, verts, normal); } - BLI_array_fixedstack_free(verts); - return area; } @@ -855,8 +851,8 @@ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], const s BMLoop *newl; BMLoop *l_iter; BMLoop *l_first; - float *abscoss = NULL; - BLI_array_fixedstack_declare(abscoss, 16, f->len, "BM_face_triangulate: temp absolute cosines of face corners"); + /* BM_face_triangulate: temp absolute cosines of face corners */ + float *abscoss = BLI_array_alloca(abscoss, f->len); /* copy vertex coordinates to vertspace area */ i = 0; @@ -940,11 +936,10 @@ void BM_face_triangulate(BMesh *bm, BMFace *f, float (*projectverts)[3], const s } #endif - BLI_array_fixedstack_free(abscoss); - /* NULL-terminate */ - if (newfaces) + if (newfaces) { newfaces[nf_i] = NULL; + } } /** @@ -961,13 +956,10 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) BMLoop *l; float v1[3], v2[3], v3[3] /*, v4[3 */, no[3], mid[3], *p1, *p2, *p3, *p4; float out[3] = {-FLT_MAX, -FLT_MAX, 0.0f}; - float (*projverts)[3]; - float (*edgeverts)[3]; + float (*projverts)[3] = BLI_array_alloca(projverts, f->len); + float (*edgeverts)[3] = BLI_array_alloca(edgeverts, len * 2); float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f; int i, j, a = 0, clen; - - BLI_array_fixedstack_declare(projverts, BM_DEFAULT_NGON_STACK_SIZE, f->len, "projvertsb"); - BLI_array_fixedstack_declare(edgeverts, BM_DEFAULT_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); i = 0; l = BM_iter_new(&iter, bm, BM_LOOPS_OF_FACE, f); @@ -1042,7 +1034,7 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) } } - /* do line crossing test */ + /* do line crossing tests */ for (i = 0; i < f->len; i++) { p1 = projverts[i]; p2 = projverts[(i + 1) % f->len]; @@ -1085,7 +1077,4 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) } } } - - BLI_array_fixedstack_free(projverts); - BLI_array_fixedstack_free(edgeverts); } diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 195c60c5a9c..5f5c60dde3f 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1113,6 +1113,40 @@ float BM_vert_calc_shell_factor(BMVert *v) return 1.0f; } } +/* alternate version of #BM_vert_calc_shell_factor which only + * uses 'hflag' faces, but falls back to all if none found. */ +float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag) +{ + BMIter iter; + BMLoop *l; + float accum_shell = 0.0f; + float accum_angle = 0.0f; + int tot_sel = 0, tot = 0; + + BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) { + if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */ + const float face_angle = BM_loop_calc_face_angle(l); + accum_shell += shell_angle_to_dist(angle_normalized_v3v3(v->no, l->f->no)) * face_angle; + accum_angle += face_angle; + tot_sel++; + } + tot++; + } + + if (accum_angle != 0.0f) { + return accum_shell / accum_angle; + } + else { + /* other main difference from BM_vert_calc_shell_factor! */ + if (tot != 0 && tot_sel == 0) { + /* none selected, so use all */ + return BM_vert_calc_shell_factor(v); + } + else { + return 1.0f; + } + } +} /** * \note quite an obscure function. @@ -1415,8 +1449,7 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) /* same as 'BM_face_exists_multi' but built vert array from edges */ int BM_face_exists_multi_edge(BMEdge **earr, int len) { - BMVert **varr; - BLI_array_fixedstack_declare(varr, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); + BMVert **varr = BLI_array_alloca(varr, len); int ok; int i, i_next; @@ -1432,14 +1465,11 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len) if (ok == FALSE) { BMESH_ASSERT(0); - BLI_array_fixedstack_free(varr); return FALSE; } ok = BM_face_exists_multi(varr, earr, len); - BLI_array_fixedstack_free(varr); - return ok; } diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 7a18f69371e..9af792417bf 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -69,6 +69,7 @@ void BM_edge_calc_face_tangent(BMEdge *e, BMLoop *e_loop, float r_tangent[3]) float BM_vert_calc_edge_angle(BMVert *v); float BM_vert_calc_shell_factor(BMVert *v); +float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag); float BM_vert_calc_mean_tagged_edge_length(BMVert *v); BMLoop *BM_face_find_shortest_loop(BMFace *f); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index aa69806fb37..2ea5914ca92 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -578,7 +578,7 @@ static void init_rotsys(BMesh *bm, EdgeData *edata, VertData *vdata) //rotsys_fill_faces(bm, edata, vdata); #if 0 - /* create visualizing geometr */ + /* create visualizing geometry */ BMVert *lastv; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BMVert *v2; diff --git a/source/blender/bmesh/operators/bmo_edgesplit.c b/source/blender/bmesh/operators/bmo_edgesplit.c index 9e9e4b8c962..b4b50a60877 100644 --- a/source/blender/bmesh/operators/bmo_edgesplit.c +++ b/source/blender/bmesh/operators/bmo_edgesplit.c @@ -22,152 +22,32 @@ /** \file blender/bmesh/operators/bmo_edgesplit.c * \ingroup bmesh + * + * Just a wrapper around #BM_mesh_edgesplit */ -#include "MEM_guardedalloc.h" - #include "BLI_utildefines.h" #include "bmesh.h" +#include "tools/bmesh_edgesplit.h" #include "intern/bmesh_operators_private.h" /* own include */ -enum { - EDGE_SEAM = 1 -}; - -enum { - VERT_SEAM = 2 -}; - -/** - * Remove the EDGE_SEAM 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, BMOperator *op) -{ - BMOIter siter; - 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) { - BMO_elem_flag_disable(bm, e, EDGE_SEAM); - } - 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 */ - BMO_elem_flag_disable(bm, e, EDGE_SEAM); - } - } - - /* single marked edges unconnected to any other marked edges - * are illegal, go through and unmark them */ - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - /* 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)++; - } - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - if (vtouch[BM_elem_index_get(e->v1)] == 1 && - vtouch[BM_elem_index_get(e->v2)] == 1) - { - BMO_elem_flag_disable(bm, e, EDGE_SEAM); - } - } - - MEM_freeN(vtouch); -} /* keep this operator fast, its used in a modifier */ void bmo_split_edges_exec(BMesh *bm, BMOperator *op) { - BMOIter siter; - BMEdge *e; const int use_verts = BMO_slot_bool_get(op->slots_in, "use_verts"); - BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_SEAM); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, FALSE); if (use_verts) { /* this slows down the operation but its ok because the modifier doesn't use */ - BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_SEAM); - - /* 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. - */ - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - if (UNLIKELY((BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE && - (BMO_elem_flag_test(bm, e->v2, VERT_SEAM) == FALSE)))) - { - BMO_elem_flag_enable(bm, e->v1, VERT_SEAM); - BMO_elem_flag_enable(bm, e->v2, VERT_SEAM); - } - } + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "verts", BM_VERT, BM_ELEM_TAG, FALSE); } - bm_edgesplit_validate_seams(bm, op); - - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { - /* 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) { - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - if (BMO_elem_flag_test(bm, e->v1, VERT_SEAM) == FALSE) { - BM_elem_flag_disable(e->v1, BM_ELEM_TAG); - } - if (BMO_elem_flag_test(bm, e->v2, VERT_SEAM) == FALSE) { - BM_elem_flag_disable(e->v2, BM_ELEM_TAG); - } - } - } - - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - if (BMO_elem_flag_test(bm, e, EDGE_SEAM)) { - 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); - } - } - } + /* this is where everything happens */ + BM_mesh_edgesplit(bm, use_verts, TRUE); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "edges.out", BM_EDGE, BM_ELEM_INTERNAL_TAG); } diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 065a1b57737..bf3bafc57fb 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -600,39 +600,31 @@ static void solidify_add_thickness(BMesh *bm, const float dist) float *vert_accum = vert_angles + bm->totvert; int i, index; - /* array for passing verts to angle_poly_v3 */ - float **verts = NULL; - BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); - /* array for receiving angles from angle_poly_v3 */ - float *face_angles = NULL; - BLI_array_staticdeclare(face_angles, BM_DEFAULT_NGON_STACK_SIZE); - BM_mesh_elem_index_ensure(bm, BM_VERT); BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (!BMO_elem_flag_test(bm, f, FACE_MARK)) { - continue; - } + if (BMO_elem_flag_test(bm, f, FACE_MARK)) { - BLI_array_grow_items(verts, f->len); - BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) { - verts[i] = l->v->co; - } + /* array for passing verts to angle_poly_v3 */ + float *face_angles = BLI_array_alloca(face_angles, f->len); + /* array for receiving angles from angle_poly_v3 */ + float **verts = BLI_array_alloca(verts, f->len); - BLI_array_grow_items(face_angles, f->len); - angle_poly_v3(face_angles, (const float **)verts, f->len); + BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) { + verts[i] = l->v->co; + } - i = 0; - BM_ITER_ELEM (l, &loopIter, f, BM_LOOPS_OF_FACE) { - v = l->v; - index = BM_elem_index_get(v); - vert_accum[index] += face_angles[i]; - vert_angles[index] += shell_angle_to_dist(angle_normalized_v3v3(v->no, f->no)) * face_angles[i]; - i++; - } + angle_poly_v3(face_angles, (const float **)verts, f->len); - BLI_array_empty(verts); - BLI_array_empty(face_angles); + i = 0; + BM_ITER_ELEM (l, &loopIter, f, BM_LOOPS_OF_FACE) { + v = l->v; + index = BM_elem_index_get(v); + vert_accum[index] += face_angles[i]; + vert_angles[index] += shell_angle_to_dist(angle_normalized_v3v3(v->no, f->no)) * face_angles[i]; + i++; + } + } } BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -643,9 +635,6 @@ static void solidify_add_thickness(BMesh *bm, const float dist) } MEM_freeN(vert_angles); - - BLI_array_free(verts); - BLI_array_free(face_angles); } void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op) diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 1e18a83a0a0..45ecdee014e 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -331,13 +331,13 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) } } - /* if l isn't NULL, we broke out of the loo */ + /* if l isn't NULL, we broke out of the loop */ if (l) { break; } } - /* if i isn't 2, we broke out of that loo */ + /* if i isn't 2, we broke out of that loop */ if (i != 2) { continue; } 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__ */ |