diff options
author | Jason Wilkins <Jason.A.Wilkins@gmail.com> | 2012-11-27 05:18:54 +0400 |
---|---|---|
committer | Jason Wilkins <Jason.A.Wilkins@gmail.com> | 2012-11-27 05:18:54 +0400 |
commit | ff7c690e4064bbb1d6180668625d7b414000e9ea (patch) | |
tree | 4ac96ca8ed5a4e6a7ab1104d0271aba02266ace6 /source/blender/bmesh/intern | |
parent | 6b65102c20e9bdafd90f55f60c2a2084d873e809 (diff) | |
parent | 9b32776be349f5e738b449ca1298e65ce1b69d33 (diff) |
Merge w/ trunk: r52086-r52534 (As with last time, the game engine was not merged)soc-2012-swiss_cheese
Diffstat (limited to 'source/blender/bmesh/intern')
20 files changed, 1086 insertions, 2250 deletions
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index eae78c6cc25..770196108f0 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -99,7 +99,7 @@ BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFa if (nodouble) { /* check if face exists or overlaps */ - is_overlap = BM_face_exists(bm, verts, len, &f); + is_overlap = BM_face_exists(verts, len, &f); } /* make new face */ @@ -174,9 +174,9 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble) { BMEdge **edges2 = NULL; - BLI_array_staticdeclare(edges2, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges2, BM_DEFAULT_NGON_STACK_SIZE); BMVert **verts = NULL; - BLI_array_staticdeclare(verts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMFace *f = NULL; BMEdge *e; BMVert *v, *ev1, *ev2; @@ -187,8 +187,10 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, i * _and_ the old bmesh_mf functions, so its kindof smashed together * - joeedh */ - if (!len || !v1 || !v2 || !edges || !bm) + if (!len || !v1 || !v2 || !edges || !bm) { + BLI_assert(0); return NULL; + } /* put edges in correct order */ for (i = 0; i < len; i++) { diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 0910dd82701..03094873e25 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -76,7 +76,9 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example) } /* allocate flag */ - v->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + v->oflags = BLI_mempool_calloc(bm->toolflagpool); + } CustomData_bmesh_set_default(&bm->vdata, &v->head.data); @@ -125,12 +127,14 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, e->head.htype = BM_EDGE; /* allocate flag */ - e->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + e->oflags = BLI_mempool_calloc(bm->toolflagpool); + } e->v1 = v1; e->v2 = v2; - BM_elem_flag_enable(e, BM_ELEM_SMOOTH); + BM_elem_flag_enable(e, BM_ELEM_SMOOTH | BM_ELEM_DRAW); CustomData_bmesh_set_default(&bm->edata, &e->head.data); @@ -195,8 +199,8 @@ BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short co { BMVert **verts = NULL; BMEdge **edges = NULL; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); - BLI_array_fixedstack_declare(edges, BM_NGON_STACK_SIZE, f->len, __func__); + 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__); BMLoop *l_iter; BMLoop *l_first; BMLoop *l_copy; @@ -278,7 +282,9 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm) f->head.htype = BM_FACE; /* allocate flag */ - f->oflags = BLI_mempool_calloc(bm->toolflagpool); + if (bm->toolflagpool) { + f->oflags = BLI_mempool_calloc(bm->toolflagpool); + } CustomData_bmesh_set_default(&bm->pdata, &f->head.data); @@ -305,7 +311,7 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, if (nodouble) { /* Check if face already exists */ - overlap = BM_face_exists(bm, verts, len, &f); + overlap = BM_face_exists(verts, len, &f); if (overlap) { return f; } @@ -495,7 +501,9 @@ static void bm_kill_only_vert(BMesh *bm, BMVert *v) if (v->head.data) CustomData_bmesh_free_block(&bm->vdata, &v->head.data); - BLI_mempool_free(bm->toolflagpool, v->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, v->oflags); + } BLI_mempool_free(bm->vpool, v); } @@ -513,7 +521,9 @@ static void bm_kill_only_edge(BMesh *bm, BMEdge *e) if (e->head.data) CustomData_bmesh_free_block(&bm->edata, &e->head.data); - BLI_mempool_free(bm->toolflagpool, e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, e->oflags); + } BLI_mempool_free(bm->epool, e); } @@ -534,7 +544,9 @@ static void bm_kill_only_face(BMesh *bm, BMFace *f) if (f->head.data) CustomData_bmesh_free_block(&bm->pdata, &f->head.data); - BLI_mempool_free(bm->toolflagpool, f->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f->oflags); + } BLI_mempool_free(bm->fpool, f); } @@ -558,7 +570,7 @@ 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_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -582,7 +594,7 @@ 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_NGON_STACK_SIZE); + BLI_array_staticdeclare(verts, BM_DEFAULT_NGON_STACK_SIZE); BMLoop *l_iter; BMLoop *l_first; int i; @@ -734,7 +746,7 @@ static int bm_loop_reverse_loop(BMesh *bm, BMFace *f 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_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(edar, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int i, j, edok; for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { @@ -937,9 +949,9 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const short do_del BMEdge **edges = NULL; BMEdge **deledges = NULL; BMVert **delverts = NULL; - BLI_array_staticdeclare(edges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(deledges, BM_NGON_STACK_SIZE); - BLI_array_staticdeclare(delverts, BM_NGON_STACK_SIZE); + BLI_array_staticdeclare(edges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(deledges, BM_DEFAULT_NGON_STACK_SIZE); + BLI_array_staticdeclare(delverts, BM_DEFAULT_NGON_STACK_SIZE); BMVert *v1 = NULL, *v2 = NULL; const char *err = NULL; int i, tote = 0; @@ -1587,7 +1599,7 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const short check_edge_dou if (LIKELY(radlen)) { BMLoop **loops = NULL; - BLI_array_fixedstack_declare(loops, BM_NGON_STACK_SIZE, radlen, __func__); + BLI_array_fixedstack_declare(loops, BM_DEFAULT_NGON_STACK_SIZE, radlen, __func__); killoop = ke->l; @@ -1773,14 +1785,18 @@ 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 */ - BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f1loop->e->oflags); + } BLI_mempool_free(bm->epool, f1loop->e); bm->totedge--; BLI_mempool_free(bm->lpool, f1loop); bm->totloop--; BLI_mempool_free(bm->lpool, f2loop); bm->totloop--; - BLI_mempool_free(bm->toolflagpool, f2->oflags); + if (bm->toolflagpool) { + BLI_mempool_free(bm->toolflagpool, f2->oflags); + } BLI_mempool_free(bm->fpool, f2); bm->totface--; /* account for both above */ @@ -1808,23 +1824,28 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) */ int BM_vert_splice(BMesh *bm, BMVert *v, BMVert *v_target) { - BMEdge *e; - + void *loops_stack[BM_DEFAULT_ITER_STACK_SIZE]; BMLoop **loops; int i, loops_tot; + BMEdge *e; + /* verts already spliced */ if (v == v_target) { return FALSE; } /* we can't modify the vert while iterating so first allocate an array of loops */ - loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot); - if (loops) { + loops = BM_iter_as_arrayN(bm, BM_LOOPS_OF_VERT, v, &loops_tot, + loops_stack, BM_DEFAULT_ITER_STACK_SIZE); + + if (LIKELY(loops != NULL)) { for (i = 0; i < loops_tot; i++) { loops[i]->v = v_target; } - MEM_freeN(loops); + if (loops != (BMLoop **)loops_stack) { + MEM_freeN(loops); + } } /* move all the edges from v's disk to vtarget's disk */ diff --git a/source/blender/bmesh/intern/bmesh_decimate.h b/source/blender/bmesh/intern/bmesh_decimate.h deleted file mode 100644 index 04dc0cfd2ea..00000000000 --- a/source/blender/bmesh/intern/bmesh_decimate.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * ***** 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 ***** - */ - -#ifndef __BMESH_DECIMATE_H__ -#define __BMESH_DECIMATE_H__ - -/** \file blender/bmesh/intern/bmesh_decimate.h - * \ingroup bmesh - */ - -void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate); - -void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only); -void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations); - -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, - BMVert **vinput_arr, const int vinput_len, - BMEdge **einput_arr, const int einput_len); -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries); - - -#endif /* __BMESH_DECIMATE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c deleted file mode 100644 index 74792d1d558..00000000000 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ /dev/null @@ -1,1044 +0,0 @@ -/* - * ***** 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/intern/bmesh_decimate_collapse.c - * \ingroup bmesh - * - * BMesh decimator that uses an edge collapse method. - */ - -#include <stddef.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_scene_types.h" - -#include "BLI_math.h" -#include "BLI_quadric.h" -#include "BLI_heap.h" - -#include "BKE_customdata.h" - -#include "bmesh.h" -#include "bmesh_structure.h" -#include "bmesh_decimate.h" /* own include */ - -/* defines for testing */ -#define USE_CUSTOMDATA -#define USE_TRIANGULATE -#define USE_VERT_NORMAL_INTERP /* has the advantage that flipped faces don't mess up vertex normals */ - -/* these checks are for rare cases that we can't avoid since they are valid meshes still */ -#define USE_SAFETY_CHECKS - -#define BOUNDARY_PRESERVE_WEIGHT 100.0f -#define OPTIMIZE_EPS 0.01f /* FLT_EPSILON is too small, see [#33106] */ -#define COST_INVALID FLT_MAX - -typedef enum CD_UseFlag { - CD_DO_VERT = (1 << 0), - CD_DO_EDGE = (1 << 1), - CD_DO_LOOP = (1 << 2) -} CD_UseFlag; - - -/* BMesh Helper Functions - * ********************** */ - -/** - * \param vquadrics must be calloc'd - */ -static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) -{ - BMIter iter; - BMFace *f; - BMEdge *e; - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_first; - BMLoop *l_iter; - - const float *co = BM_FACE_FIRST_LOOP(f)->v->co; - const float *no = f->no; - const float offset = -dot_v3v3(no, co); - Quadric q; - - BLI_quadric_from_v3_dist(&q, no, offset); - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(l_iter->v)], &q); - } while ((l_iter = l_iter->next) != l_first); - } - - /* boundary edges */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - if (UNLIKELY(BM_edge_is_boundary(e))) { - float edge_vector[3]; - float edge_cross[3]; - sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co); - f = e->l->f; - cross_v3_v3v3(edge_cross, edge_vector, f->no); - - if (normalize_v3(edge_cross) > FLT_EPSILON) { - Quadric q; - BLI_quadric_from_v3_dist(&q, edge_cross, -dot_v3v3(edge_cross, e->v1->co)); - BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT); - - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q); - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v2)], &q); - } - } - } -} - - -static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], - const Quadric *vquadrics) -{ - /* compute an edge contration target for edge 'e' - * this is computed by summing it's vertices quadrics and - * optimizing the result. */ - Quadric q; - - BLI_quadric_add_qu_ququ(&q, - &vquadrics[BM_elem_index_get(e->v1)], - &vquadrics[BM_elem_index_get(e->v2)]); - - - if (BLI_quadric_optimize(&q, optimize_co, OPTIMIZE_EPS)) { - return; /* all is good */ - } - else { - mid_v3_v3v3(optimize_co, e->v1->co, e->v2->co); - } -} - -static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) -{ - BMIter liter; - BMLoop *l; - unsigned int i; - - for (i = 0; i < 2; i++) { - /* loop over both verts */ - BMVert *v = *((&e->v1) + i); - - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - if (l->e != e && l->prev->e != e) { - float *co_prev = l->prev->v->co; - float *co_next = l->next->v->co; - float cross_exist[3]; - float cross_optim[3]; - -#if 1 - float vec_other[3]; /* line between the two outer verts, re-use for both cross products */ - float vec_exist[3]; /* before collapse */ - float vec_optim[3]; /* after collapse */ - - sub_v3_v3v3(vec_other, co_prev, co_next); - sub_v3_v3v3(vec_exist, co_prev, v->co); - sub_v3_v3v3(vec_optim, co_prev, optimize_co); - - cross_v3_v3v3(cross_exist, vec_other, vec_exist); - cross_v3_v3v3(cross_optim, vec_other, vec_optim); - - /* normalize isn't really needed, but ensures the value at a unit we can compare against */ - normalize_v3(cross_exist); - normalize_v3(cross_optim); -#else - normal_tri_v3(cross_exist, v->co, co_prev, co_next); - normal_tri_v3(cross_optim, optimize_co, co_prev, co_next); -#endif - - /* use a small value rather then zero so we don't flip a face in multiple steps - * (first making it zero area, then flipping again)*/ - if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) { - //printf("no flip\n"); - return TRUE; - } - } - } - } - - return FALSE; -} - -static void bm_decim_build_edge_cost_single(BMEdge *e, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) -{ - const Quadric *q1, *q2; - float optimize_co[3]; - float cost; - - if (eheap_table[BM_elem_index_get(e)]) { - BLI_heap_remove(eheap, eheap_table[BM_elem_index_get(e)]); - } - - /* check we can collapse, some edges we better not touch */ - if (BM_edge_is_boundary(e)) { - if (e->l->f->len == 3) { - /* pass */ - } - else { - /* only collapse tri's */ - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - } - else if (BM_edge_is_manifold(e)) { - if ((e->l->f->len == 3) && (e->l->radial_next->f->len == 3)) { - /* pass */ - } - else { - /* only collapse tri's */ - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - } - else { - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - - if (vweights) { - if ((vweights[BM_elem_index_get(e->v1)] < FLT_EPSILON) && - (vweights[BM_elem_index_get(e->v2)] < FLT_EPSILON)) - { - /* skip collapsing this edge */ - eheap_table[BM_elem_index_get(e)] = NULL; - return; - } - } - /* end sanity check */ - - - bm_decim_calc_target_co(e, optimize_co, vquadrics); - - q1 = &vquadrics[BM_elem_index_get(e->v1)]; - q2 = &vquadrics[BM_elem_index_get(e->v2)]; - - if (vweights == NULL) { - cost = (BLI_quadric_evaluate(q1, optimize_co) + - BLI_quadric_evaluate(q2, optimize_co)); - } - else { - cost = ((BLI_quadric_evaluate(q1, optimize_co) * vweights[BM_elem_index_get(e->v1)]) + - (BLI_quadric_evaluate(q2, optimize_co) * vweights[BM_elem_index_get(e->v2)])); - } - // print("COST %.12f\n"); - - eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); -} - - -/* use this for degenerate cases - add back to the heap with an invalid cost, - * this way it may be calculated again if surrounding geometry changes */ -static void bm_decim_invalid_edge_cost_single(BMEdge *e, - Heap *eheap, HeapNode **eheap_table) -{ - BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL); - eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e); -} - -static void bm_decim_build_edge_cost(BMesh *bm, - const Quadric *vquadrics, const float *vweights, - Heap *eheap, HeapNode **eheap_table) -{ - BMIter iter; - BMEdge *e; - unsigned int i; - - BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { - eheap_table[i] = NULL; /* keep sanity check happy */ - bm_decim_build_edge_cost_single(e, vquadrics, vweights, eheap, eheap_table); - } -} - -#ifdef USE_TRIANGULATE -/* Temp Triangulation - * ****************** */ - -/** - * To keep things simple we can only collapse edges on triangulated data - * (limitation with edge collapse and error calculation functions). - * - * But to avoid annoying users by only giving triangle results, we can - * triangulate, keeping a reference between the faces, then join after - * if the edges don't collapse, this will also allow more choices when - * collapsing edges so even has some advantage over decimating quads - * directly. - * - * \return TRUE if any faces were triangulated. - */ - -static int bm_decim_triangulate_begin(BMesh *bm) -{ - BMIter iter; - BMFace *f; - // int has_quad; // could optimize this a little - int has_cut = FALSE; - - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - - /* first clear loop index values */ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_iter; - BMLoop *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - BM_elem_index_set(l_iter, -1); - } while ((l_iter = l_iter->next) != l_first); - - // has_quad |= (f->len == 4) - } - - /* adding new faces as we loop over faces - * is normally best avoided, however in this case its not so bad because any face touched twice - * will already be triangulated*/ - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (f->len == 4) { - BMLoop *f_l[4]; - BMLoop *l_a, *l_b; - - { - BMLoop *l_iter = BM_FACE_FIRST_LOOP(f); - - f_l[0] = l_iter; l_iter = l_iter->next; - f_l[1] = l_iter; l_iter = l_iter->next; - f_l[2] = l_iter; l_iter = l_iter->next; - f_l[3] = l_iter; - } - - if (len_squared_v3v3(f_l[0]->v->co, f_l[2]->v->co) < - len_squared_v3v3(f_l[1]->v->co, f_l[3]->v->co)) - { - l_a = f_l[0]; - l_b = f_l[2]; - } - else { - l_a = f_l[1]; - l_b = f_l[3]; - } - -#ifdef USE_SAFETY_CHECKS - if (BM_edge_exists(l_a->v, l_b->v) == FALSE) -#endif - { - BMFace *f_new; - BMLoop *l_new; - - /* warning, NO_DOUBLE option here isn't handled as nice as it could be - * - if there is a quad that has a free standing edge joining it along - * where we want to split the face, there isnt a good way we can handle this. - * currently that edge will get removed when joining the tris back into a quad. */ - f_new = BM_face_split(bm, f, l_a->v, l_b->v, &l_new, NULL, FALSE); - - if (f_new) { - /* the value of this doesn't matter, only that the 2 loops match and have unique values */ - const int f_index = BM_elem_index_get(f); - - /* since we just split theres only ever 2 loops */ - BLI_assert(BM_edge_is_manifold(l_new->e)); - - BM_elem_index_set(l_new, f_index); - BM_elem_index_set(l_new->radial_next, f_index); - - BM_face_normal_update(f); - BM_face_normal_update(f_new); - - has_cut = TRUE; - } - } - } - } - - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - - if (has_cut) { - /* now triangulation is done we need to correct index values */ - BM_mesh_elem_index_ensure(bm, BM_EDGE | BM_FACE); - } - - return has_cut; -} - -static void bm_decim_triangulate_end(BMesh *bm) -{ - /* decimation finished, now re-join */ - BMIter iter; - BMEdge *e; - - /* boundary edges */ - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - BMLoop *l_a, *l_b; - if (BM_edge_loop_pair(e, &l_a, &l_b)) { - const int l_a_index = BM_elem_index_get(l_a); - if (l_a_index != -1) { - const int l_b_index = BM_elem_index_get(l_b); - if (l_a_index == l_b_index) { - if (LIKELY(l_a->f->len == 3 && l_b->f->len == 3)) { - if (l_a->v != l_b->v) { /* if this is the case, faces have become flipped */ - /* check we are not making a degenerate quad */ - BMVert *vquad[4] = { - e->v1, - BM_vert_in_edge(e, l_a->next->v) ? l_a->prev->v : l_a->next->v, - e->v2, - BM_vert_in_edge(e, l_b->next->v) ? l_b->prev->v : l_b->next->v, - }; - - BLI_assert(ELEM3(vquad[0], vquad[1], vquad[2], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[1], vquad[0], vquad[2], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[2], vquad[1], vquad[0], vquad[3]) == FALSE); - BLI_assert(ELEM3(vquad[3], vquad[1], vquad[2], vquad[0]) == FALSE); - - if (is_quad_convex_v3(vquad[0]->co, vquad[1]->co, vquad[2]->co, vquad[3]->co)) { - /* highly unlikely to fail, but prevents possible double-ups */ - BMFace *f[2] = {l_a->f, l_b->f}; - BM_faces_join(bm, f, 2, TRUE); - } - } - } - } - } - } - } -} - -#endif /* USE_TRIANGULATE */ - -/* Edge Collapse Functions - * *********************** */ - -#ifdef USE_CUSTOMDATA - -/** - * \param v is the target to merge into. - */ -static void bm_edge_collapse_loop_customdata(BMesh *bm, BMLoop *l, BMVert *v_clear, BMVert *v_other, - const float customdata_fac) -{ - /* these don't need to be updated, since they will get removed when the edge collapses */ - BMLoop *l_clear, *l_other; - const int is_manifold = BM_edge_is_manifold(l->e); - int side; - - /* l defines the vert to collapse into */ - - /* first find the loop of 'v_other' thats attached to the face of 'l' */ - if (l->v == v_clear) { - l_clear = l; - l_other = l->next; - } - else { - l_clear = l->next; - l_other = l; - } - - BLI_assert(l_clear->v == v_clear); - BLI_assert(l_other->v == v_other); - (void)v_other; /* quiet warnings for release */ - - /* now we have both corners of the face 'l->f' */ - for (side = 0; side < 2; side++) { - int is_seam = FALSE; - void *src[2]; - BMFace *f_exit = is_manifold ? l->radial_next->f : NULL; - BMEdge *e_prev = l->e; - BMLoop *l_first; - BMLoop *l_iter; - float w[2]; - - if (side == 0) { - l_iter = l_first = l_clear; - src[0] = l_clear->head.data; - src[1] = l_other->head.data; - - w[0] = customdata_fac; - w[1] = 1.0f - customdata_fac; - } - else { - l_iter = l_first = l_other; - src[0] = l_other->head.data; - src[1] = l_clear->head.data; - - w[0] = 1.0f - customdata_fac; - w[1] = customdata_fac; - } - - // print_v2("weights", w); - - /* WATCH IT! - should NOT reference (_clear or _other) vars for this while loop */ - - /* walk around the fan using 'e_prev' */ - while (((l_iter = BM_vert_step_fan_loop(l_iter, &e_prev)) != l_first) && (l_iter != NULL)) { - int i; - /* quit once we hit the opposite face, if we have one */ - if (f_exit && UNLIKELY(f_exit == l_iter->f)) { - break; - } - - /* break out unless we find a match */ - is_seam = TRUE; - - /* ok. we have a loop. now be smart with it! */ - for (i = 0; i < bm->ldata.totlayer; i++) { - if (CustomData_layer_has_math(&bm->ldata, i)) { - const int offset = bm->ldata.layers[i].offset; - const int type = bm->ldata.layers[i].type; - void *cd_src, *cd_iter; - - /* todo, make nicer macros for this */ - cd_src = (char *)src[0] + offset; - // cd_dst = (char *)src[1] + offset; // UNUSED - cd_iter = (char *)l_iter->head.data + offset; - - /* detect seams */ - if (CustomData_data_equals(type, cd_src, cd_iter)) { - CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_iter->head.data); - is_seam = FALSE; - } - } - } - - if (is_seam) { - break; - } - } - } -} -#endif /* USE_CUSTOMDATA */ - -/** - * Check if the collapse will result in a degenerate mesh, - * that is - duplicate edges or faces. - * - * This situation could be checked for when calculating collapse cost - * however its quite slow and a degenerate collapse could eventuate - * after the cost is calculated, so instead, check just before collapsing. - */ - -static void bm_edge_tag_enable(BMEdge *e) -{ - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_TAG); - if (e->l) { - BM_elem_flag_enable(e->l->f, BM_ELEM_TAG); - if (e->l != e->l->radial_next) { - BM_elem_flag_enable(e->l->radial_next->f, BM_ELEM_TAG); - } - } -} - -static void bm_edge_tag_disable(BMEdge *e) -{ - BM_elem_flag_disable(e->v1, BM_ELEM_TAG); - BM_elem_flag_disable(e->v2, BM_ELEM_TAG); - if (e->l) { - BM_elem_flag_disable(e->l->f, BM_ELEM_TAG); - if (e->l != e->l->radial_next) { - BM_elem_flag_disable(e->l->radial_next->f, BM_ELEM_TAG); - } - } -} - -static int bm_edge_tag_test(BMEdge *e) -{ - /* is the edge or one of its faces tagged? */ - return (BM_elem_flag_test(e->v1, BM_ELEM_TAG) || - BM_elem_flag_test(e->v2, BM_ELEM_TAG) || - (e->l && (BM_elem_flag_test(e->l->f, BM_ELEM_TAG) || - (e->l != e->l->radial_next && - BM_elem_flag_test(e->l->radial_next->f, BM_ELEM_TAG)))) - ); -} - -/* takes the edges loop */ -BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) -{ -#if 0 - /* less optimized version of check below */ - return (BM_edge_is_manifold(l->e) || BM_edge_is_boundary(l->e); -#else - /* if the edge is a boundary it points to its self, else this must be a manifold */ - return LIKELY(l) && LIKELY(l->radial_next->radial_next == l); -#endif -} - -static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) -{ - /* simply check that there is no overlap between faces and edges of each vert, - * (excluding the 2 faces attached to 'e' and 'e' its self) */ - - BMEdge *e_iter; - - /* clear flags on both disks */ - e_iter = e_first; - do { - if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; - } - bm_edge_tag_disable(e_iter); - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); - - e_iter = e_first; - do { - if (!bm_edge_is_manifold_or_boundary(e_iter->l)) { - return TRUE; - } - bm_edge_tag_disable(e_iter); - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); - - /* now enable one side... */ - e_iter = e_first; - do { - bm_edge_tag_enable(e_iter); - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v1)) != e_first); - - /* ... except for the edge we will collapse, we know thats shared, - * disable this to avoid false positive. We could be smart and never enable these - * face/edge tags in the first place but easier to do this */ - // bm_edge_tag_disable(e_first); - /* do inline... */ - { -#if 0 - BMIter iter; - BMIter liter; - BMLoop *l; - BMVert *v; - BM_ITER_ELEM (l, &liter, e_first, BM_LOOPS_OF_EDGE) { - BM_elem_flag_disable(l->f, BM_ELEM_TAG); - BM_ITER_ELEM (v, &iter, l->f, BM_VERTS_OF_FACE) { - BM_elem_flag_disable(v, BM_ELEM_TAG); - } - } -#else - /* we know each face is a triangle, no looping/iterators needed here */ - - BMLoop *l_radial; - BMLoop *l_face; - - l_radial = e_first->l; - l_face = l_radial; - BLI_assert(l_face->f->len == 3); - BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_radial)->v, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); - BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); - l_face = l_radial->radial_next; - if (l_radial != l_face) { - BLI_assert(l_face->f->len == 3); - BM_elem_flag_disable(l_face->f, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_radial->radial_next)->v, BM_ELEM_TAG); - BM_elem_flag_disable((l_face = l_face->next)->v, BM_ELEM_TAG); - BM_elem_flag_disable(( l_face->next)->v, BM_ELEM_TAG); - } -#endif - } - - /* and check for overlap */ - e_iter = e_first; - do { - if (bm_edge_tag_test(e_iter)) { - return TRUE; - } - } while ((e_iter = bmesh_disk_edge_next(e_iter, e_first->v2)) != e_first); - - return FALSE; -} - -/** - * special, highly limited edge collapse function - * intended for speed over flexibiliy. - * can only collapse edges connected to (1, 2) tris. - * - * Important - dont add vert/edge/face data on collapsing! - * - * \param e_clear_other let caller know what edges we remove besides \a e_clear - * \param customdata_flag merge factor, scales from 0 - 1 ('v_clear' -> 'v_other') - */ -static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e_clear_other[2], -#ifdef USE_CUSTOMDATA - const CD_UseFlag customdata_flag, - const float customdata_fac -#else - const CD_UseFlag UNUSED(customdata_flag), - const float UNUSED(customdata_fac) -#endif - ) -{ - BMVert *v_other; - - v_other = BM_edge_other_vert(e_clear, v_clear); - BLI_assert(v_other != NULL); - - if (BM_edge_is_manifold(e_clear)) { - BMLoop *l_a, *l_b; - BMEdge *e_a_other[2], *e_b_other[2]; - int ok; - - ok = BM_edge_loop_pair(e_clear, &l_a, &l_b); - - BLI_assert(ok == TRUE); - BLI_assert(l_a->f->len == 3); - BLI_assert(l_b->f->len == 3); - - /* keep 'v_clear' 0th */ - if (BM_vert_in_edge(l_a->prev->e, v_clear)) { - e_a_other[0] = l_a->prev->e; - e_a_other[1] = l_a->next->e; - } - else { - e_a_other[1] = l_a->prev->e; - e_a_other[0] = l_a->next->e; - } - - if (BM_vert_in_edge(l_b->prev->e, v_clear)) { - e_b_other[0] = l_b->prev->e; - e_b_other[1] = l_b->next->e; - } - else { - e_b_other[1] = l_b->prev->e; - e_b_other[0] = l_b->next->e; - } - - BLI_assert(BM_edge_share_vert(e_a_other[0], e_b_other[0])); - BLI_assert(BM_edge_share_vert(e_a_other[1], e_b_other[1])); - - /* we could assert this case, but better just bail out */ -#if 0 - BLI_assert(e_a_other[0] != e_b_other[0]); - BLI_assert(e_a_other[0] != e_b_other[1]); - BLI_assert(e_b_other[0] != e_a_other[0]); - BLI_assert(e_b_other[0] != e_a_other[1]); -#endif - /* not totally common but we want to avoid */ - if (ELEM(e_a_other[0], e_b_other[0], e_b_other[1]) || - ELEM(e_a_other[1], e_b_other[0], e_b_other[1])) - { - return FALSE; - } - - r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); - r_e_clear_other[1] = BM_elem_index_get(e_b_other[0]); - -#ifdef USE_CUSTOMDATA - /* before killing, do customdata */ - if (customdata_flag & CD_DO_VERT) { - BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); - } - if (customdata_flag & CD_DO_EDGE) { - BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); - BM_data_interp_from_edges(bm, e_b_other[1], e_b_other[0], e_b_other[1], customdata_fac); - } - if (customdata_flag & CD_DO_LOOP) { - bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); - bm_edge_collapse_loop_customdata(bm, e_clear->l->radial_next, v_clear, v_other, customdata_fac); - } -#endif - - BM_edge_kill(bm, e_clear); - - v_other->head.hflag |= v_clear->head.hflag; - BM_vert_splice(bm, v_clear, v_other); - - e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; - e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag; - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); - BM_edge_splice(bm, e_b_other[0], e_b_other[1]); - - // BM_mesh_validate(bm); - - return TRUE; - } - else if (BM_edge_is_boundary(e_clear)) { - /* same as above but only one triangle */ - BMLoop *l_a; - BMEdge *e_a_other[2]; - - l_a = e_clear->l; - - BLI_assert(l_a->f->len == 3); - - /* keep 'v_clear' 0th */ - if (BM_vert_in_edge(l_a->prev->e, v_clear)) { - e_a_other[0] = l_a->prev->e; - e_a_other[1] = l_a->next->e; - } - else { - e_a_other[1] = l_a->prev->e; - e_a_other[0] = l_a->next->e; - } - - r_e_clear_other[0] = BM_elem_index_get(e_a_other[0]); - r_e_clear_other[1] = -1; - -#ifdef USE_CUSTOMDATA - /* before killing, do customdata */ - if (customdata_flag & CD_DO_VERT) { - BM_data_interp_from_verts(bm, v_other, v_clear, v_other, customdata_fac); - } - if (customdata_flag & CD_DO_EDGE) { - BM_data_interp_from_edges(bm, e_a_other[1], e_a_other[0], e_a_other[1], customdata_fac); - } - if (customdata_flag & CD_DO_LOOP) { - bm_edge_collapse_loop_customdata(bm, e_clear->l, v_clear, v_other, customdata_fac); - } -#endif - - BM_edge_kill(bm, e_clear); - - v_other->head.hflag |= v_clear->head.hflag; - BM_vert_splice(bm, v_clear, v_other); - - e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; - BM_edge_splice(bm, e_a_other[0], e_a_other[1]); - - // BM_mesh_validate(bm); - - return TRUE; - } - else { - return FALSE; - } -} - - -/* collapse e the edge, removing e->v2 */ -static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, - Quadric *vquadrics, float *vweights, - Heap *eheap, HeapNode **eheap_table, - const CD_UseFlag customdata_flag) -{ - int e_clear_other[2]; - BMVert *v_other = e->v1; - int v_clear_index = BM_elem_index_get(e->v2); /* the vert is removed so only store the index */ - float optimize_co[3]; - float customdata_fac; - -#ifdef USE_VERT_NORMAL_INTERP - float v_clear_no[3]; - copy_v3_v3(v_clear_no, e->v2->no); -#endif - - /* disallow collapsing which results in degenerate cases */ - if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) { - bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ - return; - } - - bm_decim_calc_target_co(e, optimize_co, vquadrics); - - /* check if this would result in an overlapping face */ - if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) { - bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ - return; - } - - /* use for customdata merging */ - if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { - customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); -#if 0 - /* simple test for stupid collapse */ - if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) { - return; - } -#endif - } - else { - /* avoid divide by zero */ - customdata_fac = 0.5f; - } - - if (bm_edge_collapse(bm, e, e->v2, e_clear_other, customdata_flag, customdata_fac)) { - /* update collapse info */ - int i; - - if (vweights) { - const int fac = CLAMPIS(customdata_fac, 0.0f, 1.0f); - vweights[BM_elem_index_get(v_other)] = (vweights[v_clear_index] * (1.0f - fac)) + - (vweights[BM_elem_index_get(v_other)] * fac); - } - - e = NULL; /* paranoid safety check */ - - copy_v3_v3(v_other->co, optimize_co); - - /* remove eheap */ - for (i = 0; i < 2; i++) { - /* highly unlikely 'eheap_table[ke_other[i]]' would be NULL, but do for sanity sake */ - if ((e_clear_other[i] != -1) && (eheap_table[e_clear_other[i]] != NULL)) { - BLI_heap_remove(eheap, eheap_table[e_clear_other[i]]); - eheap_table[e_clear_other[i]] = NULL; - } - } - - /* update vertex quadric, add kept vertex from killed vertex */ - BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(v_other)], &vquadrics[v_clear_index]); - - /* update connected normals */ - - /* in fact face normals are not used for progressive updates, no need to update them */ - // BM_vert_normal_update_all(v); -#ifdef USE_VERT_NORMAL_INTERP - interp_v3_v3v3(v_other->no, v_other->no, v_clear_no, customdata_fac); - normalize_v3(v_other->no); -#else - BM_vert_normal_update(v_other); -#endif - - - /* update error costs and the eheap */ - if (LIKELY(v_other->e)) { - BMEdge *e_iter; - BMEdge *e_first; - e_iter = e_first = v_other->e; - do { - BLI_assert(BM_edge_find_double(e_iter) == NULL); - bm_decim_build_edge_cost_single(e_iter, vquadrics, vweights, eheap, eheap_table); - } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); - } - - /* this block used to be disabled, - * but enable now since surrounding faces may have been - * set to COST_INVALID because of a face overlap that no longer occurs */ -#if 1 - /* optional, update edges around the vertex face fan */ - { - BMIter liter; - BMLoop *l; - BM_ITER_ELEM (l, &liter, v_other, BM_LOOPS_OF_VERT) { - if (l->f->len == 3) { - BMEdge *e_outer; - if (BM_vert_in_edge(l->prev->e, l->v)) - e_outer = l->next->e; - else - e_outer = l->prev->e; - - BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); - - bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table); - } - } - } - /* end optional update */ -#endif - } - else { - /* add back with a high cost */ - bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); - } -} - - -/* Main Decimate Function - * ********************** */ - -/** - * \brief BM_mesh_decimate - * \param bm The mesh - * \param factor face count multiplier [0 - 1] - * \param vertex_weights Optional array of vertex aligned weights [0 - 1], - * a vertex group is the usual source for this. - */ -void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, const int do_triangulate) -{ - Heap *eheap; /* edge heap */ - HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ - Quadric *vquadrics; /* vert index aligned quadrics */ - int tot_edge_orig; - int face_tot_target; - int use_triangulate; - - CD_UseFlag customdata_flag = 0; - -#ifdef USE_TRIANGULATE - /* temp convert quads to triangles */ - use_triangulate = bm_decim_triangulate_begin(bm); -#endif - - - /* alloc vars */ - vquadrics = MEM_callocN(sizeof(Quadric) * bm->totvert, __func__); - /* since some edges may be degenerate, we might be over allocing a little here */ - eheap = BLI_heap_new_ex(bm->totedge); - eheap_table = MEM_callocN(sizeof(HeapNode *) * bm->totedge, __func__); - tot_edge_orig = bm->totedge; - - - /* build initial edge collapse cost data */ - bm_decim_build_quadrics(bm, vquadrics); - - bm_decim_build_edge_cost(bm, vquadrics, vweights, eheap, eheap_table); - - face_tot_target = bm->totface * factor; - bm->elem_index_dirty |= BM_FACE | BM_EDGE | BM_VERT; - - -#ifdef USE_CUSTOMDATA - /* initialize customdata flag, we only need math for loops */ - if (CustomData_has_interp(&bm->vdata)) customdata_flag |= CD_DO_VERT; - if (CustomData_has_interp(&bm->edata)) customdata_flag |= CD_DO_EDGE; - if (CustomData_has_math(&bm->ldata)) customdata_flag |= CD_DO_LOOP; -#endif - - /* iterative edge collapse and maintain the eheap */ - while ((bm->totface > face_tot_target) && - (BLI_heap_is_empty(eheap) == FALSE) && - (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID)) - { - // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); - BMEdge *e = BLI_heap_popmin(eheap); - BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ - - // printf("COST %.10f\n", value); - - /* under normal conditions wont be accessed again, - * but NULL just incase so we don't use freed node */ - eheap_table[BM_elem_index_get(e)] = NULL; - - bm_decim_edge_collapse(bm, e, vquadrics, vweights, eheap, eheap_table, customdata_flag); - } - - -#ifdef USE_TRIANGULATE - if (do_triangulate == FALSE) { - /* its possible we only had triangles, skip this step in that case */ - if (LIKELY(use_triangulate)) { - /* temp convert quads to triangles */ - bm_decim_triangulate_end(bm); - } - } -#endif - - /* free vars */ - MEM_freeN(vquadrics); - MEM_freeN(eheap_table); - BLI_heap_free(eheap, NULL); - - /* testing only */ - // BM_mesh_validate(bm); - - (void)tot_edge_orig; /* quiet release build warning */ -} diff --git a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c b/source/blender/bmesh/intern/bmesh_decimate_dissolve.c deleted file mode 100644 index d1371a18160..00000000000 --- a/source/blender/bmesh/intern/bmesh_decimate_dissolve.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * ***** 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/intern/bmesh_decimate_dissolve.c - * \ingroup bmesh - * - * BMesh decimator that dissolves flat areas into polygons (ngons). - */ - - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" - -#include "bmesh.h" -#include "bmesh_decimate.h" /* own include */ - -#define UNIT_TO_ANGLE DEG2RADF(90.0f) -#define ANGLE_TO_UNIT (1.0f / UNIT_TO_ANGLE) - -/* multiply vertex edge angle by face angle - * this means we are not left with sharp corners between _almost_ planer faces - * convert angles [0-PI/2] -> [0-1], multiply together, then convert back to radians. */ -static float bm_vert_edge_face_angle(BMVert *v) -{ - const float angle = BM_vert_calc_edge_angle(v); - /* note: could be either edge, it doesn't matter */ - if (v->e && BM_edge_is_manifold(v->e)) { - return ((angle * ANGLE_TO_UNIT) * (BM_edge_calc_face_angle(v->e) * ANGLE_TO_UNIT)) * UNIT_TO_ANGLE; - } - else { - return angle; - } -} - -#undef UNIT_TO_ANGLE -#undef ANGLE_TO_UNIT - -typedef struct DissolveElemWeight { - BMHeader *ele; - float weight; -} DissolveElemWeight; - -static int dissolve_elem_cmp(const void *a1, const void *a2) -{ - const struct DissolveElemWeight *d1 = a1, *d2 = a2; - - if (d1->weight > d2->weight) return 1; - else if (d1->weight < d2->weight) return -1; - return 0; -} - -/** - * \param do_all_verts Collapse all verts between 2 faces - don't check their edge angle. - */ -void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries, - BMVert **vinput_arr, const int vinput_len, - BMEdge **einput_arr, const int einput_len) -{ - const float angle_max = (float)M_PI / 2.0f; - DissolveElemWeight *weight_elems = MEM_mallocN(max_ii(einput_len, vinput_len) * - sizeof(DissolveElemWeight), __func__); - int i, tot_found; - - BMIter iter; - BMEdge *e_iter; - BMEdge **earray; - - int *vert_reverse_lookup; - - /* --- first edges --- */ - - /* wire -> tag */ - BM_ITER_MESH (e_iter, &iter, bm, BM_EDGES_OF_MESH) { - BM_elem_flag_set(e_iter, BM_ELEM_TAG, BM_edge_is_wire(e_iter)); - } - - /* go through and split edge */ - for (i = 0, tot_found = 0; i < einput_len; i++) { - BMEdge *e = einput_arr[i]; - const float angle = BM_edge_calc_face_angle(e); - - if (angle < angle_limit) { - tot_found++; - } - weight_elems[i].ele = (BMHeader *)e; - weight_elems[i].weight = angle; - } - - if (tot_found != 0) { - qsort(weight_elems, einput_len, sizeof(DissolveElemWeight), dissolve_elem_cmp); - - for (i = 0; i < tot_found; i++) { - BMEdge *e = (BMEdge *)weight_elems[i].ele; - - if (/* may have become non-manifold */ - BM_edge_is_manifold(e) && - /* check twice because cumulative effect could dissolve over angle limit */ - (BM_edge_calc_face_angle(e) < angle_limit)) - { - BMFace *nf = BM_faces_join_pair(bm, e->l->f, - e->l->radial_next->f, - e, - FALSE); /* join faces */ - - /* there may be some errors, we don't mind, just move on */ - if (nf) { - BM_face_normal_update(nf); - } - else { - BMO_error_clear(bm); - } - } - } - } - - /* prepare for cleanup */ - BM_mesh_elem_index_ensure(bm, BM_VERT); - vert_reverse_lookup = MEM_mallocN(sizeof(int) * bm->totvert, __func__); - fill_vn_i(vert_reverse_lookup, bm->totvert, -1); - for (i = 0, tot_found = 0; i < vinput_len; i++) { - BMVert *v = vinput_arr[i]; - vert_reverse_lookup[BM_elem_index_get(v)] = i; - } - - /* --- cleanup --- */ - earray = MEM_mallocN(sizeof(BMEdge *) * bm->totedge, __func__); - BM_ITER_MESH_INDEX (e_iter, &iter, bm, BM_EDGES_OF_MESH, i) { - earray[i] = e_iter; - } - /* remove all edges/verts left behind from dissolving, NULL'ing the vertex array so we dont re-use */ - for (i = bm->totedge - 1; i != -1; i--) { - e_iter = earray[i]; - - if (BM_edge_is_wire(e_iter) && (BM_elem_flag_test(e_iter, BM_ELEM_TAG) == FALSE)) { - /* edge has become wire */ - int vidx_reverse; - BMVert *v1 = e_iter->v1; - BMVert *v2 = e_iter->v2; - BM_edge_kill(bm, e_iter); - if (v1->e == NULL) { - vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v1)]; - if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL; - BM_vert_kill(bm, v1); - } - if (v2->e == NULL) { - vidx_reverse = vert_reverse_lookup[BM_elem_index_get(v2)]; - if (vidx_reverse != -1) vinput_arr[vidx_reverse] = NULL; - BM_vert_kill(bm, v2); - } - } - } - MEM_freeN(vert_reverse_lookup); - - MEM_freeN(earray); - - - /* --- second verts --- */ - if (do_dissolve_boundaries) { - /* simple version of the branch below, sincve we will dissolve _all_ verts that use 2 edges */ - for (i = 0; i < vinput_len; i++) { - BMVert *v = vinput_arr[i]; - if (LIKELY(v != NULL) && - BM_vert_edge_count(v) == 2) - { - BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ - } - } - } - else { - for (i = 0, tot_found = 0; i < vinput_len; i++) { - BMVert *v = vinput_arr[i]; - const float angle = v ? bm_vert_edge_face_angle(v) : angle_limit; - - if (angle < angle_limit) { - weight_elems[i].ele = (BMHeader *)v; - weight_elems[i].weight = angle; - tot_found++; - } - else { - weight_elems[i].ele = NULL; - weight_elems[i].weight = angle_max; - } - } - - if (tot_found != 0) { - qsort(weight_elems, vinput_len, sizeof(DissolveElemWeight), dissolve_elem_cmp); - - for (i = 0; i < tot_found; i++) { - BMVert *v = (BMVert *)weight_elems[i].ele; - if (LIKELY(v != NULL) && - /* topology changes may cause this to be un-collapsable */ - (BM_vert_edge_count(v) == 2) && - /* check twice because cumulative effect could dissolve over angle limit */ - bm_vert_edge_face_angle(v) < angle_limit) - { - BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, TRUE); /* join edges */ - - if (ne && ne->l) { - BM_edge_normals_update(ne); - } - } - } - } - } - - MEM_freeN(weight_elems); -} - -void BM_mesh_decimate_dissolve(BMesh *bm, const float angle_limit, const int do_dissolve_boundaries) -{ - int vinput_len; - int einput_len; - - BMVert **vinput_arr = BM_iter_as_arrayN(bm, BM_VERTS_OF_MESH, NULL, &vinput_len); - BMEdge **einput_arr = BM_iter_as_arrayN(bm, BM_EDGES_OF_MESH, NULL, &einput_len); - - BM_mesh_decimate_dissolve_ex(bm, angle_limit, do_dissolve_boundaries, - vinput_arr, vinput_len, - einput_arr, einput_len); - - MEM_freeN(vinput_arr); - MEM_freeN(einput_arr); -} diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c deleted file mode 100644 index 1ec13010d80..00000000000 --- a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * ***** 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/intern/bmesh_decimate_unsubdivide.c - * \ingroup bmesh - * - * BMesh decimator that uses a grid un-subdivide method. - */ - - -#include "MEM_guardedalloc.h" - -#include "BLI_math.h" - -#include "bmesh.h" - -#include "intern/bmesh_operators_private.h" /* own include */ - - -static int bm_vert_dissolve_fan_test(BMVert *v) -{ - /* check if we should walk over these verts */ - BMIter iter; - BMEdge *e; - - unsigned int tot_edge = 0; - unsigned int tot_edge_boundary = 0; - unsigned int tot_edge_manifold = 0; - unsigned int tot_edge_wire = 0; - - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - if (BM_edge_is_boundary(e)) { - tot_edge_boundary++; - } - else if (BM_edge_is_manifold(e)) { - tot_edge_manifold++; - } - else if (BM_edge_is_wire(e)) { - tot_edge_wire++; - } - tot_edge++; - } - - if ((tot_edge == 4) && (tot_edge_boundary == 0) && (tot_edge_manifold == 4)) { - return TRUE; - } - else if ((tot_edge == 3) && (tot_edge_boundary == 0) && (tot_edge_manifold == 3)) { - return TRUE; - } - else if ((tot_edge == 3) && (tot_edge_boundary == 2) && (tot_edge_manifold == 1)) { - return TRUE; - } - else if ((tot_edge == 2) && (tot_edge_wire == 2)) { - return TRUE; - } - return FALSE; -} - -static int bm_vert_dissolve_fan(BMesh *bm, BMVert *v) -{ - /* collapse under 2 conditions. - * - vert connects to 4 manifold edges (and 4 faces). - * - vert connecrs to 1 manifold edge, 2 boundary edges (and 2 faces). - * - * This covers boundary verts of a quad grid and center verts. - * note that surrounding faces dont have to be quads. - */ - - BMIter iter; - BMEdge *e; - - unsigned int tot_loop = 0; - unsigned int tot_edge = 0; - unsigned int tot_edge_boundary = 0; - unsigned int tot_edge_manifold = 0; - unsigned int tot_edge_wire = 0; - - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - if (BM_edge_is_boundary(e)) { - tot_edge_boundary++; - } - else if (BM_edge_is_manifold(e)) { - tot_edge_manifold++; - } - else if (BM_edge_is_wire(e)) { - tot_edge_wire++; - } - tot_edge++; - } - - if (tot_edge == 2) { - /* check for 2 wire verts only */ - if (tot_edge_wire == 2) { - return (BM_vert_collapse_edge(bm, v->e, v, TRUE) != NULL); - } - } - else if (tot_edge == 4) { - /* check for 4 faces surrounding */ - if (tot_edge_boundary == 0 && tot_edge_manifold == 4) { - /* good to go! */ - tot_loop = 4; - } - } - else if (tot_edge == 3) { - /* check for 2 faces surrounding at a boundary */ - if (tot_edge_boundary == 2 && tot_edge_manifold == 1) { - /* good to go! */ - tot_loop = 2; - } - else if (tot_edge_boundary == 0 && tot_edge_manifold == 3) { - /* good to go! */ - tot_loop = 3; - } - } - - if (tot_loop) { - BMLoop *f_loop[4]; - unsigned int i; - - /* ensure there are exactly tot_loop loops */ - BLI_assert(BM_iter_at_index(bm, BM_LOOPS_OF_VERT, v, tot_loop) == NULL); - BM_iter_as_array(bm, BM_LOOPS_OF_VERT, v, (void **)f_loop, tot_loop); - - for (i = 0; i < tot_loop; i++) { - BMLoop *l = f_loop[i]; - if (l->f->len > 3) { - BMLoop *l_new; - BLI_assert(l->prev->v != l->next->v); - BM_face_split(bm, l->f, l->prev->v, l->next->v, &l_new, NULL, TRUE); - BM_elem_flag_merge_into(l_new->e, l->e, l->prev->e); - } - } - - return BM_vert_dissolve(bm, v); - } - - return FALSE; -} - -enum { - VERT_INDEX_DO_COLLAPSE = -1, - VERT_INDEX_INIT = 0, - VERT_INDEX_IGNORE = 1 -}; - -// #define USE_WALKER /* gives uneven results, disable for now */ - -/* - BMVert.flag & BM_ELEM_TAG: shows we touched this vert - * - BMVert.index == -1: shows we will remove this vert - */ - -/** - * \param tag_only so we can call this from an operator */ -void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int tag_only) -{ -#ifdef USE_WALKER -# define ELE_VERT_TAG 1 -#else - BMVert **vert_seek_a = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__); - BMVert **vert_seek_b = MEM_mallocN(sizeof(BMVert *) * bm->totvert, __func__); - unsigned vert_seek_a_tot = 0; - unsigned vert_seek_b_tot = 0; -#endif - - BMVert *v; - BMIter iter; - - const unsigned int offset = 0; - const unsigned int nth = 2; - - int iter_step; - - /* if tag_only is set, we assyme the caller knows what verts to tag - * needed for the operator */ - if (tag_only == FALSE) { - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - BM_elem_flag_enable(v, BM_ELEM_TAG); - } - } - - for (iter_step = 0; iter_step < iterations; iter_step++) { - int iter_done; - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_flag_test(v, BM_ELEM_TAG) && bm_vert_dissolve_fan_test(v)) { -#ifdef USE_WALKER - BMO_elem_flag_enable(bm, v, ELE_VERT_TAG); -#endif - BM_elem_index_set(v, VERT_INDEX_INIT); /* set_dirty! */ - } - else { - BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */ - } - } - /* done with selecting tagged verts */ - - - /* main loop, keep tagging until we can't tag any more islands */ - while (TRUE) { -#ifdef USE_WALKER - BMWalker walker; -#else - unsigned int depth = 1; - unsigned int i; -#endif - BMVert *v_first = NULL; - BMVert *v; - - /* we could avoid iterating from the start each time */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (v->e && (BM_elem_index_get(v) == VERT_INDEX_INIT)) { -#ifdef USE_WALKER - if (BMO_elem_flag_test(bm, v, ELE_VERT_TAG)) -#endif - { - /* check again incase the topology changed */ - if (bm_vert_dissolve_fan_test(v)) { - v_first = v; - } - break; - } - } - } - if (v_first == NULL) { - break; - } - -#ifdef USE_WALKER - /* Walk over selected elements starting at active */ - BMW_init(&walker, bm, BMW_CONNECTED_VERTEX, - ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, - BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ - BMW_NIL_LAY); - - BLI_assert(walker.order == BMW_BREADTH_FIRST); - for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) { - /* Deselect elements that aren't at "nth" depth from active */ - if (BM_elem_index_get(v) == VERT_INDEX_INIT) { - if ((offset + BMW_current_depth(&walker)) % nth) { - /* tag for removal */ - BM_elem_index_set(v, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */ - } - else { - /* works better to allow these verts to be checked again */ - //BM_elem_index_set(v, VERT_INDEX_IGNORE); /* set_dirty! */ - } - } - } - BMW_end(&walker); -#else - - BM_elem_index_set(v_first, (offset + depth) % nth ? VERT_INDEX_IGNORE : VERT_INDEX_DO_COLLAPSE); /* set_dirty! */ - - vert_seek_b_tot = 0; - vert_seek_b[vert_seek_b_tot++] = v_first; - - while (TRUE) { - BMEdge *e; - - if ((offset + depth) % nth) { - vert_seek_a_tot = 0; - for (i = 0; i < vert_seek_b_tot; i++) { - v = vert_seek_b[i]; - BLI_assert(BM_elem_index_get(v) == VERT_INDEX_IGNORE); - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - BMVert *v_other = BM_edge_other_vert(e, v); - if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) { - BM_elem_index_set(v_other, VERT_INDEX_DO_COLLAPSE); /* set_dirty! */ - vert_seek_a[vert_seek_a_tot++] = v_other; - } - } - } - if (vert_seek_a_tot == 0) { - break; - } - } - else { - vert_seek_b_tot = 0; - for (i = 0; i < vert_seek_a_tot; i++) { - v = vert_seek_a[i]; - BLI_assert(BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE); - BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - BMVert *v_other = BM_edge_other_vert(e, v); - if (BM_elem_index_get(v_other) == VERT_INDEX_INIT) { - BM_elem_index_set(v_other, VERT_INDEX_IGNORE); /* set_dirty! */ - vert_seek_b[vert_seek_b_tot++] = v_other; - } - } - } - if (vert_seek_b_tot == 0) { - break; - } - } - - depth++; - } -#endif /* USE_WALKER */ - - } - - /* now we tagged all verts -1 for removal, lets loop over and rebuild faces */ - iter_done = FALSE; - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (BM_elem_index_get(v) == VERT_INDEX_DO_COLLAPSE) { - iter_done |= bm_vert_dissolve_fan(bm, v); - } - } - - if (iter_done == FALSE) { - break; - } - } - - bm->elem_index_dirty |= BM_VERT; - -#ifndef USE_WALKER - MEM_freeN(vert_seek_a); - MEM_freeN(vert_seek_b); -#endif -} - -void BM_mesh_decimate_unsubdivide(BMesh *bm, const int iterations) -{ - BM_mesh_decimate_unsubdivide_ex(bm, iterations, FALSE); -} diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 508b3b8fcdf..caf9f3c70d5 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -174,9 +174,9 @@ void BM_face_interp_from_face(BMesh *bm, BMFace *target, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + 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; BM_elem_attrs_copy(bm, bm, source, target); @@ -613,10 +613,10 @@ void BM_loop_interp_from_face(BMesh *bm, BMLoop *target, BMFace *source, void **vblocks = NULL; float (*cos)[3] = NULL, co[3], *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(vblocks, BM_NGON_STACK_SIZE, do_vertex ? source->len : 0, __func__); + 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); @@ -689,9 +689,9 @@ void BM_vert_interp_from_face(BMesh *bm, BMVert *v, BMFace *source) void **blocks = NULL; float (*cos)[3] = NULL, *w = NULL; float cent[3] = {0.0f, 0.0f, 0.0f}; - BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(w, BM_NGON_STACK_SIZE, source->len, __func__); - BLI_array_fixedstack_declare(blocks, BM_NGON_STACK_SIZE, source->len, __func__); + 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; diff --git a/source/blender/bmesh/intern/bmesh_iterators.c b/source/blender/bmesh/intern/bmesh_iterators.c index 1cb95d94e9b..c3f33eb95e1 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.c +++ b/source/blender/bmesh/intern/bmesh_iterators.c @@ -116,10 +116,14 @@ int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, cons * * Caller needs to free the array. */ -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + /* optional args to avoid an alloc (normally stack array) */ + void **stack_array, int stack_array_size) { BMIter iter; + BLI_assert(stack_array_size == 0 || (stack_array_size && stack_array)); + /* we can't rely on coun't being set */ switch (itype) { case BM_VERTS_OF_MESH: @@ -137,7 +141,9 @@ void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) if (BM_iter_init(&iter, bm, itype, data) && iter.count > 0) { BMElem *ele; - BMElem **array = MEM_mallocN(sizeof(ele) * iter.count, __func__); + BMElem **array = iter.count > stack_array_size ? + MEM_mallocN(sizeof(ele) * iter.count, __func__) : + stack_array; int i = 0; *r_len = iter.count; /* set before iterating */ diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index 3c42b3d610c..7291bca6356 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -107,14 +107,14 @@ typedef struct BMIter { BMesh *bm; void (*begin)(struct BMIter *iter); void *(*step)(struct BMIter *iter); - /* +#if 0 union { void *p; int i; long l; float f; } filter; - */ +#endif int count; /* note, only some iterators set this, don't rely on it */ char itype; } BMIter; @@ -125,7 +125,8 @@ __attribute__((warn_unused_result)) #endif ; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); -void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len) +void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, + void **stack_array, int stack_array_size) #ifdef __GNUC__ __attribute__((warn_unused_result)) #endif diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index d3e3bcd3556..ba5e7569c31 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -59,9 +59,45 @@ static void bm_mempool_init(BMesh *bm, const BMAllocTemplate *allocsize) #ifdef USE_BMESH_HOLES bm->looplistpool = BLI_mempool_create(sizeof(BMLoopList), 512, 512, 0); #endif +} - /* allocate one flag pool that we don't get rid of. */ - bm->toolflagpool = BLI_mempool_create(sizeof(BMFlagLayer), 512, 512, 0); +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); + + + for (i = 0; i < 3; i++) { + BM_ITER_MESH (ele, &iter, bm, iter_types[i]) { + ele->oflags = BLI_mempool_calloc(toolflagpool); + } + } + + bm->toolflagpool = toolflagpool; + bm->totflags = 1; + } +} + +void BM_mesh_elem_toolflags_clear(BMesh *bm) +{ + if (bm->toolflagpool) { + BLI_mempool_destroy(bm->toolflagpool); + bm->toolflagpool = NULL; + } } /** @@ -83,7 +119,7 @@ BMesh *BM_mesh_create(BMAllocTemplate *allocsize) /* allocate one flag pool that we don't get rid of. */ bm->stackdepth = 1; - bm->totflags = 1; + bm->totflags = 0; CustomData_reset(&bm->vdata); CustomData_reset(&bm->edata); @@ -143,7 +179,7 @@ void BM_mesh_data_free(BMesh *bm) BLI_mempool_destroy(bm->fpool); /* destroy flag pool */ - BLI_mempool_destroy(bm->toolflagpool); + BM_mesh_elem_toolflags_clear(bm); #ifdef USE_BMESH_HOLES BLI_mempool_destroy(bm->looplistpool); diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h index 8b6ef9aa3e0..b592f863cd1 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.h +++ b/source/blender/bmesh/intern/bmesh_mesh.h @@ -29,6 +29,8 @@ struct BMAllocTemplate; +void BM_mesh_elem_toolflags_ensure(BMesh *bm); +void BM_mesh_elem_toolflags_clear(BMesh *bm); BMesh *BM_mesh_create(struct BMAllocTemplate *allocsize); void BM_mesh_free(BMesh *bm); @@ -58,4 +60,8 @@ typedef struct BMAllocTemplate { extern BMAllocTemplate bm_mesh_allocsize_default; extern BMAllocTemplate bm_mesh_chunksize_default; +enum { + BM_MESH_CREATE_USE_TOOLFLAGS = (1 << 0) +}; + #endif /* __BMESH_MESH_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 398e6bbedcf..ec07eb5d9f7 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -47,9 +47,9 @@ * "in" (e.g. edgefacein). for three-type slots, use geom. * * for output slots, for single-type geometry slots, use the type name plus "out", - * (e.g. vertout), for double-type slots, use the two type names plus "out", - * (e.g. vertfaceout), for three-type slots, use geom. note that you can also - * use more esohteric names (e.g. skirtout) so long as the comment next to the + * (e.g. verts.out), for double-type slots, use the two type names plus "out", + * (e.g. vertfaces.out), for three-type slots, use geom. note that you can also + * use more esohteric names (e.g. geom_skirt.out) so long as the comment next to the * slot definition tells you what types of elements are in it. * */ @@ -82,7 +82,7 @@ * would be extracted from comments * next to them, e.g. * - * {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, //output slot, boundary region + * {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, //output slot, boundary region * * the doc generator would automatically detect the presence of "output slot" * and flag the slot as an output. the same happens for "input slot". also @@ -99,16 +99,18 @@ */ static BMOpDefine bmo_smooth_vert_def = { "smooth_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, /* set vertices close to the x axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */ - {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */ - {BMO_OP_SLOT_FLT, "clipdist"}, /* clipping threshod for the above three slots */ - {BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */ - {BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */ - {BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_BOOL, "mirror_clip_x"}, /* set vertices close to the x axis before the operation to 0 */ + {BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */ + {BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */ + {BMO_OP_SLOT_FLT, "clip_dist"}, /* clipping threshod for the above three slots */ + {BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */ + {BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */ + {BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */ + {0}, }, + {{0}}, /* no output */ bmo_smooth_vert_exec, 0 }; @@ -117,18 +119,20 @@ static BMOpDefine bmo_smooth_vert_def = { * Vertext Smooth Laplacian * Smooths vertices by using Laplacian smoothing propose by. * Desbrun, et al. Implicit Fairing of Irregular Meshes using Diffusion and Curvature Flow -*/ + */ static BMOpDefine bmo_smooth_laplacian_vert_def = { "smooth_laplacian_vert", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, //input vertices - {BMO_OP_SLOT_FLT, "lambda"}, //lambda param - {BMO_OP_SLOT_FLT, "lambda_border"}, //lambda param in border - {BMO_OP_SLOT_BOOL, "use_x"}, //Smooth object along X axis - {BMO_OP_SLOT_BOOL, "use_y"}, //Smooth object along Y axis - {BMO_OP_SLOT_BOOL, "use_z"}, //Smooth object along Z axis - {BMO_OP_SLOT_BOOL, "volume_preservation"}, //Apply volume preservation after smooth - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_FLT, "lambda"}, /* lambda param */ + {BMO_OP_SLOT_FLT, "lambda_border"}, /* lambda param in border */ + {BMO_OP_SLOT_BOOL, "use_x"}, /* Smooth object along X axis */ + {BMO_OP_SLOT_BOOL, "use_y"}, /* Smooth object along Y axis */ + {BMO_OP_SLOT_BOOL, "use_z"}, /* Smooth object along Z axis */ + {BMO_OP_SLOT_BOOL, "preserve_volume"}, /* Apply volume preservation after smooth */ + {0}, }, + {{0}}, /* no output */ bmo_smooth_laplacian_vert_exec, 0 }; @@ -141,10 +145,12 @@ static BMOpDefine bmo_smooth_laplacian_vert_def = { static BMOpDefine bmo_recalc_face_normals_def = { "recalc_face_normals", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_BOOL, "do_flip"}, /* internal flag, used by bmesh_rationalize_normals */ - {0} /* null-terminating sentinel */, + {BMO_OP_SLOT_BOOL, "use_flip"}, /* internal flag, used by bmesh_rationalize_normals */ + {0}, }, + {{0}}, /* no output */ bmo_recalc_face_normals_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -154,18 +160,22 @@ static BMOpDefine bmo_recalc_face_normals_def = { * * used to implement the select more/less tools. * this puts some geometry surrounding regions of - * geometry in geom into geomout. + * geometry in geom into geom.out. * - * if usefaces is 0 then geomout spits out verts and edges, + * if usefaces is 0 then geom.out spits out verts and edges, * otherwise it spits out faces. */ static BMOpDefine bmo_region_extend_def = { "region_extend", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output slot, computed boundary geometry. */ - {BMO_OP_SLOT_BOOL, "constrict"}, /* find boundary inside the regions, not outside. */ - {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ + {BMO_OP_SLOT_BOOL, "use_constrict"}, /* find boundary inside the regions, not outside. */ + {BMO_OP_SLOT_BOOL, "use_faces"}, /* extend from faces instead of edges */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output slot, computed boundary geometry. */ + {0}, }, bmo_region_extend_exec, 0 @@ -179,10 +189,14 @@ static BMOpDefine bmo_region_extend_def = { */ static BMOpDefine bmo_rotate_edges_def = { "rotate_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly spun edges */ - {BMO_OP_SLOT_BOOL, "ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate edge counter-clockwise if true, othewise clockwise */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly spun edges */ + {0}, }, bmo_rotate_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -196,9 +210,11 @@ static BMOpDefine bmo_rotate_edges_def = { */ static BMOpDefine bmo_reverse_faces_def = { "reverse_faces", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {0}, }, + {{0}}, /* no output */ bmo_reverse_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -211,10 +227,14 @@ static BMOpDefine bmo_reverse_faces_def = { */ static BMOpDefine bmo_bisect_edges_def = { "bisect_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_INT, "numcuts"}, /* number of cuts */ - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, /* newly created vertices and edges */ - {0} /* null-terminating sentinel */, + {BMO_OP_SLOT_INT, "cuts"}, /* number of cuts */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, /* newly created vertices and edges */ + {0}, }, bmo_bisect_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -224,20 +244,25 @@ static BMOpDefine bmo_bisect_edges_def = { * Mirror * * Mirrors geometry along an axis. The resulting geometry is welded on using - * mergedist. Pairs of original/mirrored vertices are welded using the mergedist + * merge_dist. Pairs of original/mirrored vertices are welded using the merge_dist * parameter (which defines the minimum distance for welding to happen). */ static BMOpDefine bmo_mirror_def = { "mirror", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ - {BMO_OP_SLOT_FLT, "mergedist"}, /* maximum distance for merging. does no merging if 0. */ - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, /* output geometry, mirrored */ - {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining the mirror transformation */ + {BMO_OP_SLOT_FLT, "merge_dist"}, /* maximum distance for merging. does no merging if 0. */ + {BMO_OP_SLOT_INT, "axis"}, /* the axis to use, 0, 1, or 2 for x, y, z */ {BMO_OP_SLOT_BOOL, "mirror_u"}, /* mirror UVs across the u axis */ {BMO_OP_SLOT_BOOL, "mirror_v"}, /* mirror UVs across the v axis */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry, mirrored */ + {0}, + }, bmo_mirror_exec, 0, }; @@ -253,11 +278,16 @@ static BMOpDefine bmo_mirror_def = { */ static BMOpDefine bmo_find_doubles_def = { "find_doubles", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ {BMO_OP_SLOT_ELEMENT_BUF, "keep_verts"}, /* list of verts to keep */ {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {BMO_OP_SLOT_MAPPING, "targetmapout"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_MAPPING, "targetmap.out"}, + {0}, + }, bmo_find_doubles_exec, 0, }; @@ -270,9 +300,12 @@ static BMOpDefine bmo_find_doubles_def = { */ static BMOpDefine bmo_remove_doubles_def = { "remove_doubles", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_remove_doubles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -286,9 +319,12 @@ static BMOpDefine bmo_remove_doubles_def = { */ static BMOpDefine bmo_automerge_def = { "automerge", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input verts */ {BMO_OP_SLOT_FLT, "dist"}, /* minimum distance */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_automerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -300,8 +336,11 @@ static BMOpDefine bmo_automerge_def = { */ static BMOpDefine bmo_collapse_def = { "collapse", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_collapse_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -314,9 +353,12 @@ static BMOpDefine bmo_collapse_def = { */ static BMOpDefine bmo_pointmerge_facedata_def = { "pointmerge_facedata", - {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap verte */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ + {BMO_OP_SLOT_ELEMENT_BUF, "snapv"}, /* snap vertex */ + {0}, + }, + {{0}}, /* no output */ bmo_pointmerge_facedata_exec, 0, }; @@ -330,8 +372,11 @@ static BMOpDefine bmo_pointmerge_facedata_def = { */ static BMOpDefine bmo_average_vert_facedata_def = { "average_vert_facedata", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_average_vert_facedata_exec, 0, }; @@ -343,9 +388,12 @@ static BMOpDefine bmo_average_vert_facedata_def = { */ static BMOpDefine bmo_pointmerge_def = { "pointmerge", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertice */ {BMO_OP_SLOT_VEC, "merge_co"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_pointmerge_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -357,8 +405,11 @@ static BMOpDefine bmo_pointmerge_def = { */ static BMOpDefine bmo_collapse_uvs_def = { "collapse_uvs", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_collapse_uvs_exec, 0, }; @@ -372,8 +423,11 @@ static BMOpDefine bmo_collapse_uvs_def = { */ static BMOpDefine bmo_weld_verts_def = { "weld_verts", + /* slots_in */ {{BMO_OP_SLOT_MAPPING, "targetmap"}, /* maps welded vertices to verts they should weld to */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_weld_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -386,9 +440,14 @@ static BMOpDefine bmo_weld_verts_def = { */ static BMOpDefine bmo_create_vert_def = { "create_vert", + /* slots_in */ {{BMO_OP_SLOT_VEC, "co"}, /* the coordinate of the new vert */ - {BMO_OP_SLOT_ELEMENT_BUF, "newvertout"}, /* the new vert */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "vert.out"}, /* the new vert */ + {0}, + }, bmo_create_vert_exec, 0, }; @@ -401,14 +460,19 @@ static BMOpDefine bmo_create_vert_def = { */ static BMOpDefine bmo_join_triangles_def = { "join_triangles", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* joined faces */ {BMO_OP_SLOT_BOOL, "cmp_sharp"}, {BMO_OP_SLOT_BOOL, "cmp_uvs"}, {BMO_OP_SLOT_BOOL, "cmp_vcols"}, {BMO_OP_SLOT_BOOL, "cmp_materials"}, {BMO_OP_SLOT_FLT, "limit"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* joined faces */ + {0}, + }, bmo_join_triangles_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -426,13 +490,18 @@ static BMOpDefine bmo_join_triangles_def = { */ static BMOpDefine bmo_contextual_create_def = { "contextual_create", - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* newly-made face(s) */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input geometry. */ + {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ + {BMO_OP_SLOT_BOOL, "use_smooth"}, /* smooth to use */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* newly-made face(s) */ /* note, this is for stand-alone edges only, not edges which are apart of newly created faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* newly-made edge(s) */ - {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ - {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* newly-made edge(s) */ + {0}, + }, bmo_contextual_create_exec, BMO_OP_FLAG_UNTAN_MULTIRES, }; @@ -442,27 +511,37 @@ static BMOpDefine bmo_contextual_create_def = { */ static BMOpDefine bmo_bridge_loops_def = { "bridge_loops", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ {BMO_OP_SLOT_BOOL, "use_merge"}, {BMO_OP_SLOT_FLT, "merge_factor"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new faces */ + {0}, + }, bmo_bridge_loops_exec, 0, }; static BMOpDefine bmo_edgenet_fill_def = { "edgenet_fill", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edge */ {BMO_OP_SLOT_MAPPING, "restrict"}, /* restricts edges to groups. maps edges to integer */ {BMO_OP_SLOT_BOOL, "use_restrict"}, {BMO_OP_SLOT_BOOL, "use_fill_check"}, - {BMO_OP_SLOT_ELEMENT_BUF, "excludefaces"}, /* list of faces to ignore for manifold check */ - {BMO_OP_SLOT_MAPPING, "faceout_groupmap"}, /* maps new faces to the group numbers they came fro */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* new face */ + {BMO_OP_SLOT_ELEMENT_BUF, "exclude_faces"}, /* list of faces to ignore for manifold check */ {BMO_OP_SLOT_INT, "mat_nr"}, /* material to use */ {BMO_OP_SLOT_BOOL, "use_smooth"}, /* material to use */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_MAPPING, "face_groupmap.out"}, /* maps new faces to the group numbers they came from */ + {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* new face */ + {0}, + }, bmo_edgenet_fill_exec, 0, }; @@ -479,9 +558,14 @@ static BMOpDefine bmo_edgenet_fill_def = { */ static BMOpDefine bmo_edgenet_prepare_def = { "edgenet_prepare", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* new edges */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* new edges */ + {0}, + }, bmo_edgenet_prepare, 0, }; @@ -494,10 +578,13 @@ static BMOpDefine bmo_edgenet_prepare_def = { */ static BMOpDefine bmo_rotate_def = { "rotate", + /* slots_in */ {{BMO_OP_SLOT_VEC, "cent"}, /* center of rotation */ {BMO_OP_SLOT_MAT, "mat"}, /* matrix defining rotation */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_rotate_exec, 0, }; @@ -510,9 +597,12 @@ static BMOpDefine bmo_rotate_def = { */ static BMOpDefine bmo_translate_def = { "translate", + /* slots_in */ {{BMO_OP_SLOT_VEC, "vec"}, /* translation offset */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_translate_exec, 0, }; @@ -524,9 +614,12 @@ static BMOpDefine bmo_translate_def = { */ static BMOpDefine bmo_scale_def = { "scale", + /* slots_in */ {{BMO_OP_SLOT_VEC, "vec"}, /* scale factor */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_scale_exec, 0, }; @@ -540,9 +633,12 @@ static BMOpDefine bmo_scale_def = { */ static BMOpDefine bmo_transform_def = { "transform", + /* slots_in */ {{BMO_OP_SLOT_MAT, "mat"}, /* transform matrix */ {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_transform_exec, 0, }; @@ -555,9 +651,12 @@ static BMOpDefine bmo_transform_def = { */ static BMOpDefine bmo_object_load_bmesh_def = { "object_load_bmesh", + /* slots_in */ {{BMO_OP_SLOT_PTR, "scene"}, {BMO_OP_SLOT_PTR, "object"}, - {0, /* null-terminating sentinel */}}, + {0}, + }, + {{0}}, /* no output */ bmo_object_load_bmesh_exec, 0, }; @@ -570,10 +669,13 @@ static BMOpDefine bmo_object_load_bmesh_def = { */ static BMOpDefine bmo_bmesh_to_mesh_def = { "bmesh_to_mesh", + /* slots_in */ {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a mesh structure to fill in */ {BMO_OP_SLOT_PTR, "object"}, /* pointer to an object structure */ - {BMO_OP_SLOT_BOOL, "notessellation"}, /* don't calculate mfaces */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_BOOL, "skip_tessface"}, /* don't calculate mfaces */ + {0}, + }, + {{0}}, /* no output */ bmo_bmesh_to_mesh_exec, 0, }; @@ -586,10 +688,13 @@ static BMOpDefine bmo_bmesh_to_mesh_def = { */ static BMOpDefine bmo_mesh_to_bmesh_def = { "mesh_to_bmesh", + /* slots_in */ {{BMO_OP_SLOT_PTR, "mesh"}, /* pointer to a Mesh structure */ {BMO_OP_SLOT_PTR, "object"}, /* pointer to an Object structure */ - {BMO_OP_SLOT_BOOL, "set_shapekey"}, /* load active shapekey coordinates into verts */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_BOOL, "use_shapekey"}, /* load active shapekey coordinates into verts */ + {0}, + }, + {{0}}, /* no output */ bmo_mesh_to_bmesh_exec, 0 }; @@ -601,10 +706,15 @@ static BMOpDefine bmo_mesh_to_bmesh_def = { */ static BMOpDefine bmo_extrude_discrete_faces_def = { "extrude_discrete_faces", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "skirtout"}, /* output skirt geometry, faces and edges */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {BMO_OP_SLOT_ELEMENT_BUF, "geom_skirt.out"}, /* output skirt geometry, faces and edges */ + {0}, + }, bmo_extrude_discrete_faces_exec, 0 }; @@ -617,9 +727,14 @@ static BMOpDefine bmo_extrude_discrete_faces_def = { */ static BMOpDefine bmo_extrude_edge_only_def = { "extrude_edge_only", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* output geometry */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* output geometry */ + {0}, + }, bmo_extrude_edge_only_exec, 0 }; @@ -631,125 +746,171 @@ static BMOpDefine bmo_extrude_edge_only_def = { */ static BMOpDefine bmo_extrude_vert_indiv_def = { "extrude_vert_indiv", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output wire edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output wire edges */ + {BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ + {0}, + }, bmo_extrude_vert_indiv_exec, 0 }; static BMOpDefine bmo_connect_verts_def = { "connect_verts", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, + {0}, + }, bmo_connect_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_extrude_face_region_def = { "extrude_face_region", - {{BMO_OP_SLOT_ELEMENT_BUF, "edgefacein"}, - {BMO_OP_SLOT_MAPPING, "exclude"}, - {BMO_OP_SLOT_BOOL, "alwayskeeporig"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* edges and faces */ + {BMO_OP_SLOT_MAPPING, "edges_exclude"}, + {BMO_OP_SLOT_BOOL, "use_keep_orig"}, /* keep original geometry */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {0}, + }, bmo_extrude_face_region_exec, 0 }; static BMOpDefine bmo_dissolve_verts_def = { "dissolve_verts", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_dissolve_verts_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_edges_def = { "dissolve_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, + {0}, + }, bmo_dissolve_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_edge_loop_def = { "dissolve_edge_loop", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, + {0}, + }, bmo_dissolve_edgeloop_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_faces_def = { "dissolve_faces", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "regionout"}, {BMO_OP_SLOT_BOOL, "use_verts"}, /* dissolve verts left between only 2 edges. */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "region.out"}, + {0}, + }, bmo_dissolve_faces_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_dissolve_limit_def = { "dissolve_limit", + /* slots_in */ {{BMO_OP_SLOT_FLT, "angle_limit"}, /* total rotation angle (degrees) */ {BMO_OP_SLOT_BOOL, "use_dissolve_boundaries"}, {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, {BMO_OP_SLOT_ELEMENT_BUF, "edges"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_dissolve_limit_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_triangulate_def = { "triangulate", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, - {BMO_OP_SLOT_MAPPING, "facemap"}, {BMO_OP_SLOT_BOOL, "use_beauty"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, + {BMO_OP_SLOT_MAPPING, "facemap.out"}, + {0}, + }, bmo_triangulate_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_unsubdivide_def = { "unsubdivide", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ {BMO_OP_SLOT_INT, "iterations"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_unsubdivide_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; static BMOpDefine bmo_subdivide_edges_def = { "subdivide_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, {BMO_OP_SLOT_FLT, "smooth"}, {BMO_OP_SLOT_FLT, "fractal"}, {BMO_OP_SLOT_FLT, "along_normal"}, - {BMO_OP_SLOT_INT, "numcuts"}, + {BMO_OP_SLOT_INT, "cuts"}, {BMO_OP_SLOT_INT, "seed"}, {BMO_OP_SLOT_MAPPING, "custompatterns"}, {BMO_OP_SLOT_MAPPING, "edgepercents"}, - /* these next three can have multiple types of elements in them */ - {BMO_OP_SLOT_ELEMENT_BUF, "outinner"}, - {BMO_OP_SLOT_ELEMENT_BUF, "outsplit"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* contains all output geometr */ - - {BMO_OP_SLOT_INT, "quadcornertype"}, /* quad corner type, see bmesh_operators.h */ + {BMO_OP_SLOT_INT, "quad_corner_type"}, /* quad corner type, see bmesh_operators.h */ {BMO_OP_SLOT_BOOL, "use_gridfill"}, /* fill in fully-selected faces with a grid */ {BMO_OP_SLOT_BOOL, "use_singleedge"}, /* tessellate the case of one edge selected in a quad or triangle */ {BMO_OP_SLOT_BOOL, "use_sphere"}, /* for making new primitives only */ - - {0} /* null-terminating sentinel */, + {0}, + }, + /* slots_out */ + {/* these next three can have multiple types of elements in them */ + {BMO_OP_SLOT_ELEMENT_BUF, "geom_inner.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_split.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* contains all output geometr */ + {0}, }, bmo_subdivide_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -757,38 +918,51 @@ static BMOpDefine bmo_subdivide_edges_def = { static BMOpDefine bmo_delete_def = { "delete", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, {BMO_OP_SLOT_INT, "context"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + {{0}}, /* no output */ bmo_delete_exec, 0 }; static BMOpDefine bmo_duplicate_def = { "duplicate", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "origout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "newout"}, + {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom_orig.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* facemap maps from source faces to dupe * faces, and from dupe faces to source faces */ - {BMO_OP_SLOT_MAPPING, "facemap"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {0} /* null-terminating sentinel */}, + {BMO_OP_SLOT_MAPPING, "facemap.out"}, + {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, + {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, + {0}, + }, bmo_duplicate_exec, 0 }; static BMOpDefine bmo_split_def = { "split", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_MAPPING, "boundarymap"}, - {BMO_OP_SLOT_MAPPING, "isovertmap"}, - {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current on */ - {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ - {0} /* null-terminating sentinel */}, + {BMO_OP_SLOT_PTR, "dest"}, /* destination bmesh, if NULL will use current one */ + {BMO_OP_SLOT_BOOL, "use_only_faces"}, /* when enabled. don't duplicate loose verts/edges */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {BMO_OP_SLOT_MAPPING, "boundarymap.out"}, + {BMO_OP_SLOT_MAPPING, "isovertmap.out"}, + {0}, + }, bmo_split_exec, 0 }; @@ -801,15 +975,20 @@ static BMOpDefine bmo_split_def = { */ static BMOpDefine bmo_spin_def = { "spin", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "lastout"}, /* result of last step */ - {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */ - {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */ - {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */ - {BMO_OP_SLOT_FLT, "ang"}, /* total rotation angle (degrees) */ - {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ - {BMO_OP_SLOT_BOOL, "do_dupli"}, /* duplicate or extrude? */ - {0} /* null-terminating sentinel */}, + {BMO_OP_SLOT_VEC, "cent"}, /* rotation center */ + {BMO_OP_SLOT_VEC, "axis"}, /* rotation axis */ + {BMO_OP_SLOT_VEC, "dvec"}, /* translation delta per step */ + {BMO_OP_SLOT_FLT, "angle"}, /* total rotation angle (degrees) */ + {BMO_OP_SLOT_INT, "steps"}, /* number of steps */ + {BMO_OP_SLOT_BOOL, "use_duplicate"}, /* duplicate or extrude? */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom_last.out"}, /* result of last step */ + {0}, + }, bmo_spin_exec, 0 }; @@ -822,12 +1001,17 @@ static BMOpDefine bmo_spin_def = { */ static BMOpDefine bmo_similar_faces_def = { "similar_faces", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ {BMO_OP_SLOT_INT, "type"}, /* type of selection */ {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, bmo_similar_faces_exec, 0 }; @@ -839,12 +1023,17 @@ static BMOpDefine bmo_similar_faces_def = { */ static BMOpDefine bmo_similar_edges_def = { "similar_edges", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* output edges */ {BMO_OP_SLOT_INT, "type"}, /* type of selection */ {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* output edges */ + {0}, + }, bmo_similar_edges_exec, 0 }; @@ -856,12 +1045,17 @@ static BMOpDefine bmo_similar_edges_def = { */ static BMOpDefine bmo_similar_verts_def = { "similar_verts", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* input vertices */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ {BMO_OP_SLOT_INT, "type"}, /* type of selection */ {BMO_OP_SLOT_FLT, "thresh"}, /* threshold of selection */ {BMO_OP_SLOT_INT, "compare"}, /* comparison method */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ + {0}, + }, bmo_similar_verts_exec, 0 }; @@ -872,9 +1066,13 @@ static BMOpDefine bmo_similar_verts_def = { */ static BMOpDefine bmo_rotate_uvs_def = { "rotate_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ + {0}, + }, + /* slots_out */ + {{0}}, /* no output */ bmo_rotate_uvs_exec, 0 }; @@ -885,8 +1083,11 @@ static BMOpDefine bmo_rotate_uvs_def = { */ static BMOpDefine bmo_reverse_uvs_def = { "reverse_uvs", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {0}, + }, + {{0}}, /* no output */ bmo_reverse_uvs_exec, 0 }; @@ -897,9 +1098,12 @@ static BMOpDefine bmo_reverse_uvs_def = { */ static BMOpDefine bmo_rotate_colors_def = { "rotate_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_INT, "dir"}, /* direction */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {BMO_OP_SLOT_BOOL, "use_ccw"}, /* rotate counter-clockwise if true, othewise clockwise */ + {0}, + }, + {{0}}, /* no output */ bmo_rotate_colors_exec, 0 }; @@ -910,8 +1114,11 @@ static BMOpDefine bmo_rotate_colors_def = { */ static BMOpDefine bmo_reverse_colors_def = { "reverse_colors", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ + {0}, + }, + {{0}}, /* no output */ bmo_reverse_colors_exec, 0 }; @@ -923,11 +1130,16 @@ static BMOpDefine bmo_reverse_colors_def = { */ static BMOpDefine bmo_shortest_path_def = { "shortest_path", - {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output vertices */ - {BMO_OP_SLOT_INT, "type"}, /* type of selection */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "startv"}, /* start vertex */ + {BMO_OP_SLOT_ELEMENT_BUF, "endv"}, /* end vertex */ + {BMO_OP_SLOT_INT, "type"}, /* type of selection */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output vertices */ + {0}, + }, bmo_shortest_path_exec, 0 }; @@ -939,12 +1151,17 @@ static BMOpDefine bmo_shortest_path_def = { */ static BMOpDefine bmo_split_edges_def = { "split_edges", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "edgeout"}, /* old output disconnected edges */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ /* needed for vertex rip so we can rip only half an edge at a boundary wich would otherwise split off */ - {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* optional tag verts, use to have greater control of splits */ + {BMO_OP_SLOT_ELEMENT_BUF, "verts"}, /* optional tag verts, use to have greater control of splits */ {BMO_OP_SLOT_BOOL, "use_verts"}, /* use 'verts' for splitting, else just find verts to split from edges */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges.out"}, /* old output disconnected edges */ + {0}, + }, bmo_split_edges_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -956,12 +1173,17 @@ static BMOpDefine bmo_split_edges_def = { */ static BMOpDefine bmo_create_grid_def = { "create_grid", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "xsegments"}, /* number of x segments */ - {BMO_OP_SLOT_INT, "ysegments"}, /* number of y segments */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the grid */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_INT, "x_segments"}, /* number of x segments */ + {BMO_OP_SLOT_INT, "y_segments"}, /* number of y segments */ + {BMO_OP_SLOT_FLT, "size"}, /* size of the grid */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_grid_exec, 0, }; @@ -973,12 +1195,17 @@ static BMOpDefine bmo_create_grid_def = { */ static BMOpDefine bmo_create_uvsphere_def = { "create_uvsphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "segments"}, /* number of u segments */ - {BMO_OP_SLOT_INT, "revolutions"}, /* number of v segment */ + /* slots_in */ + {{BMO_OP_SLOT_INT, "u_segments"}, /* number of u segments */ + {BMO_OP_SLOT_INT, "v_segments"}, /* number of v segment */ {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_uvsphere_exec, 0, }; @@ -990,11 +1217,16 @@ static BMOpDefine bmo_create_uvsphere_def = { */ static BMOpDefine bmo_create_icosphere_def = { "create_icosphere", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */ + /* slots_in */ + {{BMO_OP_SLOT_INT, "subdivisions"}, /* how many times to recursively subdivide the sphere */ {BMO_OP_SLOT_FLT, "diameter"}, /* diameter */ {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ - {0, /* null-terminating sentinel */}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_icosphere_exec, 0, }; @@ -1006,9 +1238,14 @@ static BMOpDefine bmo_create_icosphere_def = { */ static BMOpDefine bmo_create_monkey_def = { "create_monkey", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_monkey_exec, 0, }; @@ -1020,15 +1257,20 @@ static BMOpDefine bmo_create_monkey_def = { */ static BMOpDefine bmo_create_cone_def = { "create_cone", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ + /* slots_in */ + {{BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ + {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter1"}, /* diameter of one end */ - {BMO_OP_SLOT_FLT, "diameter2"}, /* diameter of the opposite */ - {BMO_OP_SLOT_FLT, "depth"}, /* distance between ends */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_FLT, "diameter1"}, /* diameter of one end */ + {BMO_OP_SLOT_FLT, "diameter2"}, /* diameter of the opposite */ + {BMO_OP_SLOT_FLT, "depth"}, /* distance between ends */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_cone_exec, 0, }; @@ -1038,13 +1280,18 @@ static BMOpDefine bmo_create_cone_def = { */ static BMOpDefine bmo_create_circle_def = { "create_circle", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ - {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ + /* slots_in */ + {{BMO_OP_SLOT_BOOL, "cap_ends"}, /* wheter or not to fill in the ends with faces */ + {BMO_OP_SLOT_BOOL, "cap_tris"}, /* fill ends with triangles instead of ngons */ {BMO_OP_SLOT_INT, "segments"}, - {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + {BMO_OP_SLOT_FLT, "diameter"}, /* diameter of one end */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_circle_exec, 0, }; @@ -1056,15 +1303,19 @@ static BMOpDefine bmo_create_circle_def = { */ static BMOpDefine bmo_create_cube_def = { "create_cube", - {{BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, /* output verts */ - {BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ - {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with-- */ - {0, /* null-terminating sentinel */}}, + /* slots_in */ + {{BMO_OP_SLOT_FLT, "size"}, /* size of the cube */ + {BMO_OP_SLOT_MAT, "mat"}, /* matrix to multiply the new geometry with */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, /* output verts */ + {0}, + }, bmo_create_cube_exec, 0, }; -#define NEW_BEVEL 1 /* * Bevel * @@ -1072,12 +1323,17 @@ static BMOpDefine bmo_create_cube_def = { */ static BMOpDefine bmo_bevel_def = { "bevel", -#ifdef NEW_BEVEL - {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ - {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */ - {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */ - {0} /* null-terminating sentinel */}, -#else + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ + {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */ + {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, +#if 0 /* old bevel*/ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */ {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */ @@ -1087,7 +1343,8 @@ static BMOpDefine bmo_bevel_def = { * modifier uses this. We could do this as another float setting */ {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */ {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */ - {0} /* null-terminating sentinel */}, + {0}, + }, #endif bmo_bevel_exec, BMO_OP_FLAG_UNTAN_MULTIRES @@ -1100,10 +1357,15 @@ static BMOpDefine bmo_bevel_def = { */ static BMOpDefine bmo_beautify_fill_def = { "beautify_fill", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ {BMO_OP_SLOT_ELEMENT_BUF, "constrain_edges"}, /* edges that can't be flipped */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new flipped faces and edges */ - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new flipped faces and edges */ + {0}, + }, bmo_beautify_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1115,9 +1377,14 @@ static BMOpDefine bmo_beautify_fill_def = { */ static BMOpDefine bmo_triangle_fill_def = { "triangle_fill", - {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, /* new faces and edges */ - {0} /* null-terminating sentinel */}, + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "edges"}, /* input edges */ + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, /* new faces and edges */ + {0}, + }, bmo_triangle_fill_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1129,10 +1396,15 @@ static BMOpDefine bmo_triangle_fill_def = { */ static BMOpDefine bmo_solidify_def = { "solidify", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, {BMO_OP_SLOT_FLT, "thickness"}, - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {0}}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {0}, + }, bmo_solidify_face_region_exec, 0 }; @@ -1144,15 +1416,20 @@ static BMOpDefine bmo_solidify_def = { */ static BMOpDefine bmo_inset_def = { "inset", - {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ + /* slots_in */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ {BMO_OP_SLOT_BOOL, "use_boundary"}, {BMO_OP_SLOT_BOOL, "use_even_offset"}, {BMO_OP_SLOT_BOOL, "use_relative_offset"}, {BMO_OP_SLOT_FLT, "thickness"}, {BMO_OP_SLOT_FLT, "depth"}, {BMO_OP_SLOT_BOOL, "use_outset"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, bmo_inset_exec, 0 }; @@ -1164,15 +1441,20 @@ static BMOpDefine bmo_inset_def = { */ static BMOpDefine bmo_wireframe_def = { "wireframe", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "faces"}, /* input faces */ - {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ {BMO_OP_SLOT_BOOL, "use_boundary"}, {BMO_OP_SLOT_BOOL, "use_even_offset"}, {BMO_OP_SLOT_BOOL, "use_crease"}, {BMO_OP_SLOT_FLT, "thickness"}, {BMO_OP_SLOT_BOOL, "use_relative_offset"}, {BMO_OP_SLOT_FLT, "depth"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "faces.out"}, /* output faces */ + {0}, + }, bmo_wireframe_exec, 0 }; @@ -1184,11 +1466,16 @@ static BMOpDefine bmo_wireframe_def = { */ static BMOpDefine bmo_slide_vert_def = { "slide_vert", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "vert"}, {BMO_OP_SLOT_ELEMENT_BUF, "edge"}, - {BMO_OP_SLOT_ELEMENT_BUF, "vertout"}, {BMO_OP_SLOT_FLT, "distance_t"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "verts.out"}, + {0}, + }, bmo_slide_vert_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; @@ -1202,7 +1489,7 @@ static BMOpDefine bmo_slide_vert_def = { * If 'use_existing_faces' is true, the hull will not output triangles * that are covered by a pre-existing face. * - * All hull vertices, faces, and edges are added to 'geomout'. Any + * All hull vertices, faces, and edges are added to 'geom.out'. Any * input elements that end up inside the hull (i.e. are not used by an * output face) are added to the 'interior_geom' slot. The * 'unused_geom' slot will contain all interior geometry that is @@ -1211,15 +1498,18 @@ static BMOpDefine bmo_slide_vert_def = { */ static BMOpDefine bmo_convex_hull_def = { "convex_hull", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, {BMO_OP_SLOT_BOOL, "use_existing_faces"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - {BMO_OP_SLOT_ELEMENT_BUF, "interior_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "unused_geom"}, - {BMO_OP_SLOT_ELEMENT_BUF, "holes_geom"}, - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_interior.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_unused.out"}, + {BMO_OP_SLOT_ELEMENT_BUF, "geom_holes.out"}, + {0}, + }, bmo_convex_hull_exec, 0 }; @@ -1233,17 +1523,19 @@ static BMOpDefine bmo_convex_hull_def = { * the "direction" slot. The edges and faces that cross the plane of * symmetry are split as needed to enforce symmetry. * - * All new vertices, edges, and faces are added to the "geomout" slot. + * All new vertices, edges, and faces are added to the "geom.out" slot. */ static BMOpDefine bmo_symmetrize_def = { "symmetrize", + /* slots_in */ {{BMO_OP_SLOT_ELEMENT_BUF, "input"}, {BMO_OP_SLOT_INT, "direction"}, - - /* Outputs */ - {BMO_OP_SLOT_ELEMENT_BUF, "geomout"}, - - {0} /* null-terminating sentinel */}, + {0}, + }, + /* slots_out */ + {{BMO_OP_SLOT_ELEMENT_BUF, "geom.out"}, + {0}, + }, bmo_symmetrize_exec, 0 }; diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 671cfbbc55e..b87e023e63a 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -116,30 +116,45 @@ enum { * for when your defining an operator with BMOpDefine.*/ typedef struct BMOpSlot { + const char *slot_name; /* pointer to BMOpDefine.slot_args */ int slot_type; int len; - int flag; - int index; /* index within slot array */ +// int flag; /* UNUSED */ +// int index; /* index within slot array */ /* UNUSED */ union { int i; float f; void *p; float vec[3]; - void *buf; + void **buf; GHash *ghash; } data; } BMOpSlot; -#define BMO_OP_MAX_SLOTS 16 /* way more than probably needed */ +/* mainly for use outside bmesh internal code */ +#define BMO_SLOT_AS_BOOL(slot) ((slot)->data.i) +#define BMO_SLOT_AS_INT(slot) ((slot)->data.i) +#define BMO_SLOT_AS_FLOAT(slot) ((slot)->data.f) +#define BMO_SLOT_AS_VECTOR(slot) ((slot)->data.vec) +#define BMO_SLOT_AS_MATRIX(slot ) ((float (*)[4])((slot)->data.p)) +#define BMO_SLOT_AS_BUFFER(slot ) ((slot)->data.buf) +#define BMO_SLOT_AS_GHASH(slot ) ((slot)->data.ghash) + +#define BMO_ASSERT_SLOT_IN_OP(slot, op) \ + BLI_assert(((slot >= (op)->slots_in) && (slot < &(op)->slots_in[BMO_OP_MAX_SLOTS])) || \ + ((slot >= (op)->slots_out) && (slot < &(op)->slots_out[BMO_OP_MAX_SLOTS]))) + +/* way more than probably needed, compiler complains if limit hit */ +#define BMO_OP_MAX_SLOTS 16 typedef struct BMOperator { + struct BMOpSlot slots_in[BMO_OP_MAX_SLOTS]; + struct BMOpSlot slots_out[BMO_OP_MAX_SLOTS]; + void (*exec)(BMesh *bm, struct BMOperator *op); + struct MemArena *arena; int type; - int slot_type; int type_flag; int flag; /* runtime options */ - struct BMOpSlot slot_args[BMO_OP_MAX_SLOTS]; - void (*exec)(BMesh *bm, struct BMOperator *op); - struct MemArena *arena; } BMOperator; enum { @@ -156,8 +171,9 @@ typedef struct BMOSlotType { } BMOSlotType; typedef struct BMOpDefine { - const char *name; - BMOSlotType slot_types[BMO_OP_MAX_SLOTS]; + const char *opname; + BMOSlotType slot_types_in[BMO_OP_MAX_SLOTS]; + BMOSlotType slot_types_out[BMO_OP_MAX_SLOTS]; void (*exec)(BMesh *bm, BMOperator *op); int type_flag; } BMOpDefine; @@ -245,15 +261,22 @@ int BMO_op_initf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, ... int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *fmt, va_list vlist); /* test whether a named slot exists */ -int BMO_slot_exists(BMOperator *op, const char *slot_name); +int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* get a pointer to a slot. this may be removed layer on from the public API. */ -BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name); +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); /* copies the data of a slot from one operator to another. src and dst are the * source/destination slot codes, respectively. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, - const char *src, const char *dst); +#define BMO_slot_copy(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_copy((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) + +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst); /* del "context" slot values, used for operator too */ enum { @@ -279,13 +302,13 @@ typedef enum { void BMO_op_flag_enable(BMesh *bm, BMOperator *op, const int op_flag); void BMO_op_flag_disable(BMesh *bm, BMOperator *op, const int op_flag); -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f); -float BMO_slot_float_get(BMOperator *op, const char *slot_name); -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_int_get(BMOperator *op, const char *slot_name); -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i); -int BMO_slot_bool_get(BMOperator *op, const char *slot_name); -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f); +float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i); +int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len); /* don't pass in arrays that are supposed to map to elements this way. @@ -293,69 +316,81 @@ void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len); * so, e.g. passing in list of floats per element in another slot is bad. * passing in, e.g. pointer to an editmesh for the conversion operator is fine * though. */ -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p); -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name); -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]); -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]); +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p); +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]); +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]); /* only supports square mats */ /* size must be 3 or 4; this api is meant only for transformation matrices. * note that internally the matrix is stored in 4x4 form, and it's safe to * call whichever BMO_Get_MatXXX function you want. */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size); -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]); -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]); +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size); +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]); +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]); void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); /* copies the values from another slot to the end of the output slot */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_op_slot, - BMOperator *other_op, const char *other_op_slot); +#define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ + op_dst, slots_dst, slot_name_dst) \ + _bmo_slot_buffer_append((op_src)->slots_src, slot_name_src, \ + (op_dst)->slots_dst, slot_name_dst, \ + (op_dst)->arena) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst); /* puts every element of type 'type' (which is a bitmask) with tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* puts every element of type 'type' (which is a bitmask) without tool * flag 'flag', into a slot. */ -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag); /* tool-flags all elements inside an element slot array with flag flag. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush); /* clears tool-flag flag from all elements inside a slot array. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush); /* puts every element of type 'type' (which is a bitmask) with header * flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); /* puts every element of type 'type' (which is a bitmask) without * header flag 'flag', into a slot. note: ignores hidden elements * (e.g. elements with header flag BM_ELEM_HIDDEN set).*/ void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, - const char *slot_name, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag); /* counts number of elements inside a slot array. */ -int BMO_slot_buffer_count(BMesh *bm, BMOperator *op, const char *slot_name); -int BMO_slot_map_count(BMesh *bm, BMOperator *op, const char *slot_name); +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len); +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *data, int len); /* Counts the number of edges with tool flag toolflag around */ @@ -363,13 +398,14 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, - const char hflag, const short oflag); +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char hflag, const short oflag); -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len); +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const int len); -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, - const char htype); +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype); /* this part of the API is used to iterate over element buffer or * mapping slots. @@ -412,10 +448,11 @@ typedef struct BMOIter { char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name); +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); -void *BMO_iter_new(BMOIter *iter, BMesh *bm, BMOperator *op, - const char *slot_name, const char restrictmask); +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask); void *BMO_iter_step(BMOIter *iter); /* returns a pointer to the key value when iterating over mappings. @@ -428,8 +465,8 @@ void *BMO_iter_map_value_p(BMOIter *iter); /* use this for float mappings */ float BMO_iter_map_value_f(BMOIter *iter); -#define BMO_ITER(ele, iter, bm, op, slot_name, restrict) \ - for (ele = BMO_iter_new(iter, bm, op, slot_name, restrict); ele; ele = BMO_iter_step(iter)) +#define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \ + for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter)) /******************* Inlined Functions********************/ typedef void (*opexec)(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 16c2b8b0505..b405ecc1841 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -69,16 +69,16 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor oflags[bm->stackdepth - 1].f ^= oflag; } -BLI_INLINE void BMO_slot_map_int_insert(BMesh *bm, BMOperator *op, const char *slot_name, +BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, void *element, int val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(int)); + BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); } -BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char *slot_name, +BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, void *element, float val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(float)); + BMO_slot_map_insert(op, slot, element, &val, sizeof(float)); } @@ -87,62 +87,62 @@ BLI_INLINE void BMO_slot_map_float_insert(BMesh *bm, BMOperator *op, const char * do NOT use these for non-operator-api-allocated memory! instead * use BMO_slot_map_data_get and BMO_slot_map_insert, which copies the data. */ -BLI_INLINE void BMO_slot_map_ptr_insert(BMesh *bm, BMOperator *op, const char *slot_name, - void *element, void *val) +BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *val) { - BMO_slot_map_insert(bm, op, slot_name, element, &val, sizeof(void *)); + BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); } -BLI_INLINE int BMO_slot_map_contains(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, void *element) +BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return 0; + if (UNLIKELY(slot->data.ghash == NULL)) { + return 0; + } return BLI_ghash_haskey(slot->data.ghash, element); } -BLI_INLINE void *BMO_slot_map_data_get(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ - if (!slot->data.ghash) return NULL; + if (UNLIKELY(slot->data.ghash == NULL)) { + return NULL; + } mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element); - if (!mapping) return NULL; + if (!mapping) { + return NULL; + } return mapping + 1; } -BLI_INLINE float BMO_slot_map_float_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - float *val = (float *) BMO_slot_map_data_get(bm, op, slot_name, element); + float *val = (float *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0.0f; } -BLI_INLINE int BMO_slot_map_int_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - int *val = (int *) BMO_slot_map_data_get(bm, op, slot_name, element); + int *val = (int *) BMO_slot_map_data_get(slot, element); if (val) return *val; return 0; } -BLI_INLINE void *BMO_slot_map_ptr_get(BMesh *bm, BMOperator *op, const char *slot_name, - void *element) +BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) { - void **val = (void **) BMO_slot_map_data_get(bm, op, slot_name, element); + void **val = (void **) BMO_slot_map_data_get(slot, element); if (val) return *val; return NULL; diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 9d1054dc042..157837a13c0 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -45,8 +45,8 @@ static void bmo_flag_layer_alloc(BMesh *bm); static void bmo_flag_layer_free(BMesh *bm); static void bmo_flag_layer_clear(BMesh *bm); -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name); -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name); +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier); static int bmo_opname_to_opcode(const char *opname); static const char *bmo_error_messages[] = { @@ -80,7 +80,7 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = { }; /* Dummy slot so there is something to return when slot name lookup fails */ -static BMOpSlot BMOpEmptySlot = {0}; +// static BMOpSlot BMOpEmptySlot = {0}; void BMO_op_flag_enable(BMesh *UNUSED(bm), BMOperator *op, const int op_flag) { @@ -101,6 +101,8 @@ void BMO_push(BMesh *bm, BMOperator *UNUSED(op)) { bm->stackdepth++; + BLI_assert(bm->totflags > 0); + /* add flag layer, if appropriate */ if (bm->stackdepth > 1) bmo_flag_layer_alloc(bm); @@ -123,6 +125,18 @@ void BMO_pop(BMesh *bm) bm->stackdepth--; } + +/* use for both slot_types_in and slot_types_out */ +static void bmo_op_slots_init(BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot_args[i].slot_name = slot_types[i].name; + slot_args[i].slot_type = slot_types[i].type; + // slot_args[i].index = i; // UNUSED + } +} + /** * \brief BMESH OPSTACK INIT OP * @@ -130,7 +144,7 @@ void BMO_pop(BMesh *bm) */ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) { - int i, opcode = bmo_opname_to_opcode(opname); + int opcode = bmo_opname_to_opcode(opname); #ifdef DEBUG BM_ELEM_INDEX_VALIDATE(bm, "pre bmo", opname); @@ -148,10 +162,8 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) op->flag = flag; /* initialize the operator slot types */ - for (i = 0; opdefines[opcode]->slot_types[i].type; i++) { - op->slot_args[i].slot_type = opdefines[opcode]->slot_types[i].type; - op->slot_args[i].index = i; - } + bmo_op_slots_init(opdefines[opcode]->slot_types_in, op->slots_in); + bmo_op_slots_init(opdefines[opcode]->slot_types_out, op->slots_out); /* callback */ op->exec = opdefines[opcode]->exec; @@ -172,7 +184,9 @@ void BMO_op_init(BMesh *bm, BMOperator *op, const int flag, const char *opname) */ void BMO_op_exec(BMesh *bm, BMOperator *op) { - + /* allocate tool flags on demand */ + BM_mesh_elem_toolflags_ensure(bm); + BMO_push(bm, op); if (bm->stackdepth == 2) @@ -185,6 +199,20 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) BMO_pop(bm); } +static void bmo_op_slots_free(BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + BMOpSlot *slot; + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot = &slot_args[i]; + if (slot->slot_type == BMO_OP_SLOT_MAPPING) { + if (slot->data.ghash) { + BLI_ghash_free(slot->data.ghash, NULL, NULL); + } + } + } +} + /** * \brief BMESH OPSTACK FINISH OP * @@ -192,21 +220,13 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) */ void BMO_op_finish(BMesh *bm, BMOperator *op) { - BMOpSlot *slot; - int i; - - for (i = 0; opdefines[op->type]->slot_types[i].type; i++) { - slot = &op->slot_args[i]; - if (slot->slot_type == BMO_OP_SLOT_MAPPING) { - if (slot->data.ghash) - BLI_ghash_free(slot->data.ghash, NULL, NULL); - } - } + bmo_op_slots_free(opdefines[op->type]->slot_types_in, op->slots_in); + bmo_op_slots_free(opdefines[op->type]->slot_types_out, op->slots_out); BLI_memarena_free(op->arena); #ifdef DEBUG - BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->name); + BM_ELEM_INDEX_VALIDATE(bm, "post bmo", opdefines[op->type]->opname); #else (void)bm; #endif @@ -217,9 +237,9 @@ void BMO_op_finish(BMesh *bm, BMOperator *op) * * \return Success if the slot if found. */ -int BMO_slot_exists(BMOperator *op, const char *slot_name) +int BMO_slot_exists(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode(slot_args, identifier); return (slot_code >= 0); } @@ -228,73 +248,78 @@ int BMO_slot_exists(BMOperator *op, const char *slot_name) * * Returns a pointer to the slot of type 'slot_code' */ -BMOpSlot *BMO_slot_get(BMOperator *op, const char *slot_name) +BMOpSlot *BMO_slot_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int slot_code = bmo_name_to_slotcode_check(opdefines[op->type], slot_name); + int slot_code = bmo_name_to_slotcode_check(slot_args, identifier); - if (slot_code < 0) { - return &BMOpEmptySlot; + if (UNLIKELY(slot_code < 0)) { + //return &BMOpEmptySlot; + BLI_assert(0); + NULL; /* better crash */ } - return &(op->slot_args[slot_code]); + return &slot_args[slot_code]; } /** * \brief BMESH OPSTACK COPY SLOT * + * define used. * Copies data from one slot to another. */ -void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, const char *dst) +void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + struct MemArena *arena_dst) { - BMOpSlot *source_slot = BMO_slot_get(source_op, src); - BMOpSlot *dest_slot = BMO_slot_get(dest_op, dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); - if (source_slot == dest_slot) + if (slot_src == slot_dst) return; - if (source_slot->slot_type != dest_slot->slot_type) { - /* possibly assert here? */ + BLI_assert(slot_src->slot_type == slot_dst->slot_type); + if (slot_src->slot_type != slot_dst->slot_type) { return; } - if (dest_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { + if (slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { /* do buffer copy */ - dest_slot->data.buf = NULL; - dest_slot->len = source_slot->len; - if (dest_slot->len) { - const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[dest_slot->slot_type] * dest_slot->len; - dest_slot->data.buf = BLI_memarena_alloc(dest_op->arena, slot_alloc_size); - memcpy(dest_slot->data.buf, source_slot->data.buf, slot_alloc_size); + slot_dst->data.buf = NULL; + slot_dst->len = slot_src->len; + if (slot_dst->len) { + const int slot_alloc_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type] * slot_dst->len; + slot_dst->data.buf = BLI_memarena_alloc(arena_dst, slot_alloc_size); + memcpy(slot_dst->data.buf, slot_src->data.buf, slot_alloc_size); } } - else if (dest_slot->slot_type == BMO_OP_SLOT_MAPPING) { + else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { GHashIterator it; BMOElemMapping *srcmap, *dstmap; /* sanity check */ - if (!source_slot->data.ghash) { + if (!slot_src->data.ghash) { return; } - if (!dest_slot->data.ghash) { - dest_slot->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); + if (!slot_dst->data.ghash) { + slot_dst->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); } - BLI_ghashIterator_init(&it, source_slot->data.ghash); - for ( ; (srcmap = BLI_ghashIterator_getValue(&it)); - BLI_ghashIterator_step(&it)) + for (BLI_ghashIterator_init(&it, slot_src->data.ghash); + (srcmap = BLI_ghashIterator_getValue(&it)); + BLI_ghashIterator_step(&it)) { - dstmap = BLI_memarena_alloc(dest_op->arena, sizeof(*dstmap) + srcmap->len); + dstmap = BLI_memarena_alloc(arena_dst, sizeof(*dstmap) + srcmap->len); dstmap->element = srcmap->element; dstmap->len = srcmap->len; memcpy(dstmap + 1, srcmap + 1, srcmap->len); - BLI_ghash_insert(dest_slot->data.ghash, dstmap->element, dstmap); + BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap); } } else { - dest_slot->data = source_slot->data; + slot_dst->data = slot_src->data; } } @@ -304,9 +329,9 @@ void BMO_slot_copy(BMOperator *source_op, BMOperator *dest_op, const char *src, * Sets the value of a slot depending on it's type */ -void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) +void BMO_slot_float_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float f) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return; @@ -314,9 +339,9 @@ void BMO_slot_float_set(BMOperator *op, const char *slot_name, const float f) slot->data.f = f; } -void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_int_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return; @@ -324,9 +349,9 @@ void BMO_slot_int_set(BMOperator *op, const char *slot_name, const int i) slot->data.i = i; } -void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) +void BMO_slot_bool_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int i) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return; @@ -335,9 +360,9 @@ void BMO_slot_bool_set(BMOperator *op, const char *slot_name, const int i) } /* only supports square mats */ -void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, int size) +void BMO_slot_mat_set(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float *mat, int size) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; @@ -358,39 +383,39 @@ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, i } } -void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]) +void BMO_slot_mat4_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[4][4]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; if (slot->data.p) { - copy_m4_m4(r_mat, (float (*)[4])slot->data.p); + copy_m4_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); } else { unit_m4(r_mat); } } -void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]) +void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_mat[3][3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAT); if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; if (slot->data.p) { - copy_m3_m4(r_mat, slot->data.p); + copy_m3_m4(r_mat, BMO_SLOT_AS_MATRIX(slot)); } else { unit_m3(r_mat); } } -void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) +void BMO_slot_ptr_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, void *p) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return; @@ -398,9 +423,9 @@ void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) slot->data.p = p; } -void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) +void BMO_slot_vec_set(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const float vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -409,9 +434,9 @@ void BMO_slot_vec_set(BMOperator *op, const char *slot_name, const float vec[3]) } -float BMO_slot_float_get(BMOperator *op, const char *slot_name) +float BMO_slot_float_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_FLT); if (!(slot->slot_type == BMO_OP_SLOT_FLT)) return 0.0f; @@ -419,9 +444,9 @@ float BMO_slot_float_get(BMOperator *op, const char *slot_name) return slot->data.f; } -int BMO_slot_int_get(BMOperator *op, const char *slot_name) +int BMO_slot_int_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_INT); if (!(slot->slot_type == BMO_OP_SLOT_INT)) return 0; @@ -429,9 +454,9 @@ int BMO_slot_int_get(BMOperator *op, const char *slot_name) return slot->data.i; } -int BMO_slot_bool_get(BMOperator *op, const char *slot_name) +int BMO_slot_bool_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_BOOL); if (!(slot->slot_type == BMO_OP_SLOT_BOOL)) return 0; @@ -440,23 +465,23 @@ int BMO_slot_bool_get(BMOperator *op, const char *slot_name) } /* if you want a copy of the elem buffer */ -void *BMO_slot_as_arrayN(BMOperator *op, const char *slot_name, int *len) +void *BMO_slot_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, int *len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); void *ret; /* could add support for mapping type */ BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - ret = MEM_mallocN(sizeof(void *) * slot->len, __func__); - memcpy(ret, slot->data.buf, sizeof(void *) * slot->len); + ret = MEM_mallocN(sizeof(void **) * slot->len, __func__); + memcpy(ret, slot->data.buf, sizeof(void **) * slot->len); *len = slot->len; return ret; } -void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) +void *BMO_slot_ptr_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_PTR); if (!(slot->slot_type == BMO_OP_SLOT_PTR)) return NULL; @@ -464,9 +489,9 @@ void *BMO_slot_ptr_get(BMOperator *op, const char *slot_name) return slot->data.p; } -void BMO_slot_vec_get(BMOperator *op, const char *slot_name, float r_vec[3]) +void BMO_slot_vec_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, float r_vec[3]) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_VEC); if (!(slot->slot_type == BMO_OP_SLOT_VEC)) return; @@ -542,9 +567,9 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty } } -int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); /* check if its actually a buffer */ @@ -554,9 +579,9 @@ int BMO_slot_buffer_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_na return slot->len; } -int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) +int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* check if its actually a buffer */ @@ -569,12 +594,12 @@ int BMO_slot_map_count(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name) /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ -void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_name, - void *element, void *data, int len) +void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, + const void *element, void *data, int len) { BMOElemMapping *mapping; - BMOpSlot *slot = BMO_slot_get(op, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); + BMO_ASSERT_SLOT_IN_OP(slot, op); mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len); @@ -586,7 +611,7 @@ void BMO_slot_map_insert(BMesh *UNUSED(bm), BMOperator *op, const char *slot_nam slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); } - BLI_ghash_insert(slot->data.ghash, element, mapping); + BLI_ghash_insert(slot->data.ghash, (void *)element, mapping); } #if 0 @@ -632,11 +657,11 @@ void *bmo_slot_buffer_grow(BMesh *bm, BMOperator *op, int slot_code, int totadd) } #endif -void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { GHashIterator it; - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMElemF *ele_f; BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); @@ -652,18 +677,22 @@ void BMO_slot_map_to_flag(BMesh *bm, BMOperator *op, const char *slot_name, } } -void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len) +void *BMO_slot_buffer_alloc(BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const int len) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); /* check if its actually a buffer */ if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; slot->len = len; - if (len) + if (len) { slot->data.buf = BLI_memarena_alloc(op->arena, BMO_OPSLOT_TYPEINFO[slot->slot_type] * len); + } + else { + slot->data.buf = NULL; + } + return slot->data.buf; } @@ -672,9 +701,10 @@ void *BMO_slot_buffer_alloc(BMOperator *op, const char *slot_name, const int len * * Copies all elements of a certain type into an operator slot. */ -void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, const char htype) +void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], + const char *slot_name, const char htype) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; if (htype & BM_VERT) totelement += bm->totvert; @@ -685,27 +715,27 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, BMIter iter; BMHeader *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ if (htype & BM_VERT) { BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_EDGE) { BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } if (htype & BM_FACE) { BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { - ((BMHeader **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -718,11 +748,11 @@ void BMO_slot_buffer_from_all(BMesh *bm, BMOperator *op, const char *slot_name, * Copies elements of a certain type, which have a certain header flag * enabled/disabled into a slot for an operator. */ -static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const short test_for_enabled) { - BMOpSlot *output = BMO_slot_get(op, slot_name); + BMOpSlot *output = BMO_slot_get(slot_args, slot_name); int totelement = 0, i = 0; const int respecthide = (op->flag & BMO_FLAG_RESPECT_HIDE) != 0; @@ -737,7 +767,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl BMIter iter; BMElem *ele; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); /* TODO - collapse these loops into one */ @@ -746,7 +776,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -757,7 +787,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -768,7 +798,7 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl if ((!respecthide || !BM_elem_flag_test(ele, BM_ELEM_HIDDEN)) && BM_elem_flag_test_bool(ele, hflag) == test_for_enabled) { - ((BMElem **)output->data.p)[i] = ele; + output->data.buf[i] = ele; i++; } } @@ -779,46 +809,51 @@ static void bmo_slot_buffer_from_hflag(BMesh *bm, BMOperator *op, const char *sl } } -void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_hflag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, TRUE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, TRUE); } -void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_hflag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag) { - bmo_slot_buffer_from_hflag(bm, op, slot_name, htype, hflag, FALSE); + bmo_slot_buffer_from_hflag(bm, op, slot_args, slot_name, htype, hflag, FALSE); } /** * Copies the values from another slot to the end of the output slot. */ -void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, - BMOperator *other_op, const char *other_slot_name) +void _bmo_slot_buffer_append(BMOpSlot slot_args_dst[BMO_OP_MAX_SLOTS], const char *slot_name_dst, + BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_name_src, + struct MemArena *arena_dst) { - BMOpSlot *output_slot = BMO_slot_get(output_op, output_slot_name); - BMOpSlot *other_slot = BMO_slot_get(other_op, other_slot_name); + BMOpSlot *slot_dst = BMO_slot_get(slot_args_dst, slot_name_dst); + BMOpSlot *slot_src = BMO_slot_get(slot_args_src, slot_name_src); - BLI_assert(output_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF && - other_slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); + BLI_assert(slot_dst->slot_type == BMO_OP_SLOT_ELEMENT_BUF && + slot_src->slot_type == BMO_OP_SLOT_ELEMENT_BUF); - if (output_slot->len == 0) { + if (slot_dst->len == 0) { /* output slot is empty, copy rather than append */ - BMO_slot_copy(other_op, output_op, other_slot_name, output_slot_name); + _bmo_slot_copy(slot_args_src, slot_name_src, + slot_args_dst, slot_name_dst, + arena_dst); } - else if (other_slot->len != 0) { - int elem_size = BMO_OPSLOT_TYPEINFO[output_slot->slot_type]; - int alloc_size = elem_size * (output_slot->len + other_slot->len); + else if (slot_src->len != 0) { + int elem_size = BMO_OPSLOT_TYPEINFO[slot_dst->slot_type]; + int alloc_size = elem_size * (slot_dst->len + slot_src->len); /* allocate new buffer */ - void *buf = BLI_memarena_alloc(output_op->arena, alloc_size); + void *buf = BLI_memarena_alloc(arena_dst, alloc_size); /* copy slot data */ - memcpy(buf, output_slot->data.buf, elem_size * output_slot->len); - memcpy(((char *)buf) + elem_size * output_slot->len, other_slot->data.buf, elem_size * other_slot->len); + memcpy(buf, slot_dst->data.buf, elem_size * slot_dst->len); + memcpy(((char *)buf) + elem_size * slot_dst->len, slot_src->data.buf, elem_size * slot_src->len); - output_slot->data.buf = buf; - output_slot->len += other_slot->len; + slot_dst->data.buf = buf; + slot_dst->len += slot_src->len; } } @@ -828,13 +863,15 @@ void BMO_slot_buffer_append(BMOperator *output_op, const char *output_slot_name, * Copies elements of a certain type, which have a certain flag set * into an output slot for an operator. */ -static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slot_name, +static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag, const short test_for_enabled) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); int totelement, i = 0; + BLI_assert(op->slots_in == slot_args || op->slots_out == slot_args); BLI_assert(ELEM(TRUE, FALSE, test_for_enabled)); if (test_for_enabled) @@ -849,9 +886,9 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo BMHeader *ele; BMHeader **ele_array; - BMO_slot_buffer_alloc(op, slot_name, totelement); + BMO_slot_buffer_alloc(op, slot_args, slot_name, totelement); - ele_array = (BMHeader **)slot->data.p; + ele_array = (BMHeader **)slot->data.buf; /* TODO - collapse these loops into one */ @@ -887,16 +924,18 @@ static void bmo_slot_buffer_from_flag(BMesh *bm, BMOperator *op, const char *slo } } -void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_enabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, TRUE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, TRUE); } -void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - bmo_slot_buffer_from_flag(bm, op, slot_name, htype, oflag, FALSE); + bmo_slot_buffer_from_flag(bm, op, slot_args, slot_name, htype, oflag, FALSE); } /** @@ -905,11 +944,12 @@ void BMO_slot_buffer_from_disabled_flag(BMesh *bm, BMOperator *op, const char *s * Header Flags elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; int i; const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); @@ -938,11 +978,12 @@ void BMO_slot_buffer_hflag_enable(BMesh *bm, BMOperator *op, const char *slot_na * Removes flags from elements in a slots buffer, automatically * using the selection API where appropriate. */ -void BMO_slot_buffer_hflag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_hflag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const char hflag, const char do_flush) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMElem **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMElem **data = (BMElem **)slot->data.buf; int i; const char do_flush_select = (do_flush && (hflag & BM_ELEM_SELECT)); const char do_flush_hide = (do_flush && (hflag & BM_ELEM_HIDDEN)); @@ -989,10 +1030,11 @@ int BMO_vert_edge_flags_count(BMesh *bm, BMVert *v, const short oflag) * * Flags elements in a slots buffer */ -void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_enable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BMHeader **data = slot->data.p; int i; @@ -1011,11 +1053,12 @@ void BMO_slot_buffer_flag_enable(BMesh *bm, BMOperator *op, const char *slot_nam * * Removes flags from elements in a slots buffer */ -void BMO_slot_buffer_flag_disable(BMesh *bm, BMOperator *op, const char *slot_name, +void BMO_slot_buffer_flag_disable(BMesh *bm, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char htype, const short oflag) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); - BMHeader **data = slot->data.p; + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); + BMHeader **data = (BMHeader **)slot->data.buf; int i; BLI_assert(slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF); @@ -1056,7 +1099,9 @@ static void bmo_flag_layer_alloc(BMesh *bm) /* 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 */ @@ -1068,18 +1113,21 @@ static void bmo_flag_layer_alloc(BMesh *bm) 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->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1113,18 +1161,21 @@ static void bmo_flag_layer_free(BMesh *bm) 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->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); @@ -1159,14 +1210,14 @@ static void bmo_flag_layer_clear(BMesh *bm) bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } -void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) +void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); if (slot->slot_type != BMO_OP_SLOT_ELEMENT_BUF) return NULL; - return slot->data.buf ? *(void **)slot->data.buf : NULL; + return slot->data.buf ? *slot->data.buf : NULL; } /** @@ -1175,10 +1226,11 @@ void *BMO_slot_buffer_elem_first(BMOperator *op, const char *slot_name) * \param restrictmask restricts the iteration to certain element types * (e.g. combination of BM_VERT, BM_EDGE, BM_FACE), if iterating * over an element buffer (not a mapping). */ -void *BMO_iter_new(BMOIter *iter, BMesh *UNUSED(bm), BMOperator *op, - const char *slot_name, const char restrictmask) +void *BMO_iter_new(BMOIter *iter, + BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, + const char restrictmask) { - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); memset(iter, 0, sizeof(BMOIter)); @@ -1207,13 +1259,13 @@ void *BMO_iter_step(BMOIter *iter) return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; + h = iter->slot->data.buf[iter->cur++]; while (!(iter->restrictmask & h->htype)) { if (iter->cur >= iter->slot->len) { return NULL; } - h = ((void **)iter->slot->data.buf)[iter->cur++]; + h = iter->slot->data.buf[iter->cur++]; } return h; @@ -1312,24 +1364,26 @@ int BMO_error_pop(BMesh *bm, const char **msg, BMOperator **op) #define NEXT_CHAR(fmt) ((fmt)[0] != 0 ? (fmt)[1] : 0) -static int bmo_name_to_slotcode(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i; + int i = 0; - for (i = 0; def->slot_types[i].type; i++) { - if (!strncmp(name, def->slot_types[i].name, MAX_SLOTNAME)) { + while (slot_args->slot_name) { + if (strncmp(identifier, slot_args->slot_name, MAX_SLOTNAME) == 0) { return i; } + slot_args++; + i++; } return -1; } -static int bmo_name_to_slotcode_check(BMOpDefine *def, const char *name) +static int bmo_name_to_slotcode_check(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *identifier) { - int i = bmo_name_to_slotcode(def, name); + int i = bmo_name_to_slotcode(slot_args, identifier); if (i < 0) { - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, name); + fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, identifier); } return i; @@ -1340,12 +1394,12 @@ static int bmo_opname_to_opcode(const char *opname) int i; for (i = 0; i < bmesh_total_ops; i++) { - if (!strcmp(opname, opdefines[i]->name)) { + if (!strcmp(opname, opdefines[i]->opname)) { return i; } } - fprintf(stderr, "%s: ! could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); + fprintf(stderr, "%s: could not find bmesh slot for name %s! (bmesh internal error)\n", __func__, opname); return -1; } @@ -1355,6 +1409,8 @@ static int bmo_opname_to_opcode(const char *opname) * i - int * b - boolean (same as int but 1/0 only) * f - float + * s - slot_in + * S - slot_out * hv - header flagged verts (hflag) * he - header flagged edges (hflag) * hf - header flagged faces (hflag) @@ -1368,7 +1424,7 @@ static int bmo_opname_to_opcode(const char *opname) int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, va_list vlist) { - BMOpDefine *def; +// BMOpDefine *def; char *opname, *ofmt, *fmt; char slot_name[64] = {0}; int i /*, n = strlen(fmt) */, stop /*, slot_code = -1 */, type, state; @@ -1407,7 +1463,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } BMO_op_init(bm, op, flag, opname); - def = opdefines[i]; +// def = opdefines[i]; i = 0; state = 1; /* 0: not inside slot_code name, 1: inside slot_code name */ @@ -1430,7 +1486,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v fmt[i] = 0; - if (bmo_name_to_slotcode_check(def, fmt) < 0) { + if (bmo_name_to_slotcode_check(op->slots_in, fmt) < 0) { GOTO_ERROR("name to slot code check failed"); } @@ -1456,47 +1512,57 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v else if (c == '4') size = 4; else GOTO_ERROR("matrix size was not 3 or 4"); - BMO_slot_mat_set(op, slot_name, va_arg(vlist, void *), size); + BMO_slot_mat_set(op, op->slots_in, slot_name, va_arg(vlist, void *), size); state = 1; break; } case 'v': { - BMO_slot_vec_set(op, slot_name, va_arg(vlist, float *)); + BMO_slot_vec_set(op->slots_in, slot_name, va_arg(vlist, float *)); state = 1; break; } case 'e': { BMHeader *ele = va_arg(vlist, void *); - BMOpSlot *slot = BMO_slot_get(op, slot_name); + BMOpSlot *slot = BMO_slot_get(op->slots_in, slot_name); slot->data.buf = BLI_memarena_alloc(op->arena, sizeof(void *) * 4); slot->len = 1; - *((void **)slot->data.buf) = ele; + *slot->data.buf = ele; state = 1; break; } case 's': + case 'S': { - BMOperator *op2 = va_arg(vlist, void *); - const char *slot_name2 = va_arg(vlist, char *); + BMOperator *op_other = va_arg(vlist, void *); + const char *slot_name_other = va_arg(vlist, char *); - BMO_slot_copy(op2, op, slot_name2, slot_name); + if (*fmt == 's') { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_in, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_in, slot_name_other, + op, slots_in, slot_name); + } + else { + BLI_assert(bmo_name_to_slotcode_check(op_other->slots_out, slot_name_other) != -1); + BMO_slot_copy(op_other, slots_out, slot_name_other, + op, slots_in, slot_name); + } state = 1; break; } case 'i': - BMO_slot_int_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_int_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'b': - BMO_slot_bool_set(op, slot_name, va_arg(vlist, int)); + BMO_slot_bool_set(op->slots_in, slot_name, va_arg(vlist, int)); state = 1; break; case 'p': - BMO_slot_ptr_set(op, slot_name, va_arg(vlist, void *)); + BMO_slot_ptr_set(op->slots_in, slot_name, va_arg(vlist, void *)); state = 1; break; case 'f': @@ -1507,7 +1573,7 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v type = *fmt; if (NEXT_CHAR(fmt) == ' ' || NEXT_CHAR(fmt) == '\0') { - BMO_slot_float_set(op, slot_name, va_arg(vlist, double)); + BMO_slot_float_set(op->slots_in, slot_name, va_arg(vlist, double)); } else { htype = 0; @@ -1529,19 +1595,19 @@ int BMO_op_vinitf(BMesh *bm, BMOperator *op, const int flag, const char *_fmt, v } if (type == 'h') { - BMO_slot_buffer_from_enabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'H') { - BMO_slot_buffer_from_disabled_hflag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_hflag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'a') { - BMO_slot_buffer_from_all(bm, op, slot_name, htype); + BMO_slot_buffer_from_all(bm, op, op->slots_in, slot_name, htype); } else if (type == 'f') { - BMO_slot_buffer_from_enabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } else if (type == 'F') { - BMO_slot_buffer_from_disabled_flag(bm, op, slot_name, htype, va_arg(vlist, int)); + BMO_slot_buffer_from_disabled_flag(bm, op, op->slots_in, slot_name, htype, va_arg(vlist, int)); } } diff --git a/source/blender/bmesh/intern/bmesh_operators.h b/source/blender/bmesh/intern/bmesh_operators.h index 14da93302b9..b74d97c9bb5 100644 --- a/source/blender/bmesh/intern/bmesh_operators.h +++ b/source/blender/bmesh/intern/bmesh_operators.h @@ -88,11 +88,6 @@ enum { OPUVC_AXIS_Y }; -enum { - DIRECTION_CW = 1, - DIRECTION_CCW -}; - /* vertex path selection values */ enum { VPATH_SELECT_EDGE_LENGTH = 0, diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 98edceb30a2..2e0471863d4 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -162,7 +162,7 @@ float BM_face_calc_area(BMFace *f) float area; int i; - BLI_array_fixedstack_declare(verts, BM_NGON_STACK_SIZE, f->len, __func__); + 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); @@ -677,6 +677,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa BMLoop *l_first; const float cos_threshold = 0.9f; + const float bias = 1.0f + 1e-6f; if (f->len == 4) { BMLoop *larr[4]; @@ -691,7 +692,7 @@ static BMLoop *find_ear(BMFace *f, float (*verts)[3], const int use_beauty, floa /* pick 0/1 based on best lenth */ /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */ i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > - len_squared_v3v3(larr[1]->v->co, larr[3]->v->co))) != use_beauty); + len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); i4 = (i + 3) % 4; /* Check produced tris aren’t too flat/narrow... * Probably not the best test, but is quite efficient and should at least avoid null-area faces! */ @@ -965,8 +966,8 @@ void BM_face_legal_splits(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f; int i, j, a = 0, clen; - BLI_array_fixedstack_declare(projverts, BM_NGON_STACK_SIZE, f->len, "projvertsb"); - BLI_array_fixedstack_declare(edgeverts, BM_NGON_STACK_SIZE * 2, len * 2, "edgevertsb"); + 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); diff --git a/source/blender/bmesh/intern/bmesh_private.h b/source/blender/bmesh/intern/bmesh_private.h index b3fe3676ab8..850e81ba3ac 100644 --- a/source/blender/bmesh/intern/bmesh_private.h +++ b/source/blender/bmesh/intern/bmesh_private.h @@ -56,15 +56,21 @@ int bmesh_elem_check(void *element, const char htype); int bmesh_radial_length(BMLoop *l); int bmesh_disk_count(BMVert *v); -/* NOTE: ensure different parts of the API do not conflict +/** + * Internal BMHeader.api_flag + * \note Ensure different parts of the API do not conflict * on using these internal flags!*/ -#define _FLAG_JF 1 /* join faces */ -#define _FLAG_MF 2 /* make face */ -#define _FLAG_MV 2 /* make face, vertex */ +enum { + _FLAG_JF = (1 << 0), /* join faces */ + _FLAG_MF = (1 << 1), /* make face */ + _FLAG_MV = (1 << 1), /* make face, vertex */ + _FLAG_OVERLAP = (1 << 2) /* general overlap flag */ +}; -#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->oflags[0].pflag |= (f)) -#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->oflags[0].pflag &= ~(f)) -#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->oflags[0].pflag & (f)) +#define BM_ELEM_API_FLAG_ENABLE(element, f) ((element)->head.api_flag |= (f)) +#define BM_ELEM_API_FLAG_DISABLE(element, f) ((element)->head.api_flag &= ~(f)) +#define BM_ELEM_API_FLAG_TEST(element, f) ((element)->head.api_flag & (f)) +#define BM_ELEM_API_FLAG_CLEAR(element) ((element)->head.api_flag = 0) void calc_poly_plane(float (*verts)[3], const int nverts); void poly_rotate_plane(const float normal[3], float (*verts)[3], const int nverts); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 1e1d7d1becb..ec2e90591cc 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -39,8 +39,6 @@ #include "bmesh.h" #include "intern/bmesh_private.h" -#define BM_OVERLAP (1 << 13) - /** * Returns whether or not a given vertex is * is part of a given edge. @@ -240,7 +238,7 @@ int BM_vert_in_face(BMFace *f, BMVert *v) * Compares the number of vertices in an array * that appear in a given face */ -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) +int BM_verts_in_face(BMFace *f, BMVert **varr, int len) { BMLoop *l_iter, *l_first; @@ -251,7 +249,7 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) int i, count = 0; for (i = 0; i < len; i++) { - BMO_elem_flag_enable(bm, varr[i], BM_OVERLAP); + BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); } #ifdef USE_BMESH_HOLES @@ -266,14 +264,16 @@ int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len) #endif do { - if (BMO_elem_flag_test(bm, l_iter->v, BM_OVERLAP)) { + if (BM_ELEM_API_FLAG_TEST(l_iter->v, _FLAG_OVERLAP)) { count++; } } while ((l_iter = l_iter->next) != l_first); } - for (i = 0; i < len; i++) BMO_elem_flag_disable(bm, varr[i], BM_OVERLAP); + for (i = 0; i < len; i++) { + BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); + } return count; } @@ -1217,7 +1217,7 @@ BMEdge *BM_edge_find_double(BMEdge *e) * \returns TRUE for overlap * */ -int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlapface) +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_overlapface) { BMIter viter; BMFace *f; @@ -1225,7 +1225,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount >= len) { if (r_overlapface) { *r_overlapface = f; @@ -1247,7 +1247,7 @@ int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_overlap * there is a face with exactly those vertices * (and only those vertices). */ -int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) +int BM_face_exists(BMVert **varr, int len, BMFace **r_existface) { BMIter viter; BMFace *f; @@ -1255,7 +1255,7 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface) for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { - amount = BM_verts_in_face(bm, f, varr, len); + amount = BM_verts_in_face(f, varr, len); if (amount == len && amount == f->len) { if (r_existface) { *r_existface = f; @@ -1393,7 +1393,7 @@ int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len) int BM_face_exists_multi_edge(BMEdge **earr, int len) { BMVert **varr; - BLI_array_fixedstack_declare(varr, BM_NGON_STACK_SIZE, len, __func__); + BLI_array_fixedstack_declare(varr, BM_DEFAULT_NGON_STACK_SIZE, len, __func__); int ok; int i, i_next; @@ -1419,3 +1419,38 @@ int BM_face_exists_multi_edge(BMEdge **earr, int len) return ok; } + +/* convenience functions for checking flags */ +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag) +{ + return (BM_elem_flag_test(e->v1, hflag) || + BM_elem_flag_test(e->v2, hflag)); +} + +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->v, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} + +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (BM_elem_flag_test(l_iter->e, hflag)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + return FALSE; +} diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 579a1397b0c..d97faebf021 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -28,7 +28,7 @@ */ int BM_vert_in_face(BMFace *f, BMVert *v); -int BM_verts_in_face(BMesh *bm, BMFace *f, BMVert **varr, int len); +int BM_verts_in_face(BMFace *f, BMVert **varr, int len); int BM_edge_in_face(BMFace *f, BMEdge *e); int BM_edge_in_loop(BMEdge *e, BMLoop *l); @@ -77,9 +77,9 @@ BMLoop *BM_face_find_longest_loop(BMFace *f); BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2); BMEdge *BM_edge_find_double(BMEdge *e); -int BM_face_exists_overlap(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); +int BM_face_exists_overlap(BMVert **varr, int len, BMFace **r_existface); -int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); +int BM_face_exists(BMVert **varr, int len, BMFace **r_existface); int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len); int BM_face_exists_multi_edge(BMEdge **earr, int len); @@ -100,4 +100,8 @@ void BM_edge_ordered_verts(BMEdge *edge, BMVert **r_v1, BMVert **r_v2); void BM_edge_ordered_verts_ex(BMEdge *edge, BMVert **r_v1, BMVert **r_v2, BMLoop *edge_loop); +int BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag); +int BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); +int BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); + #endif /* __BMESH_QUERIES_H__ */ |