diff options
author | Campbell Barton <ideasman42@gmail.com> | 2012-11-19 06:26:59 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2012-11-19 06:26:59 +0400 |
commit | 185cf6095e50eb4b3c27ad07dc31367da9d486f0 (patch) | |
tree | 74645191ff61bc9be7d47a53e4f47267b3ea3058 /source | |
parent | cdc4037f0dbdc73016420504a3c6c0f6de78d3a3 (diff) |
improvements to bevel
- the resulting selection is now correct
internal details
- bev_rebuild_polygon() now only rebuilds polygons that are attached to a bevel vertex (was rebuilding ALL).
... need to take care we don't leave faces pointing to removed geometry, so far this works fine.
- bev_rebuild_polygon() uses stack memory for <32 size ngons to reduce allocs.
- skip hash lookup when removing bevel verts (use tag instead).
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 1 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_bevel.c | 7 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 63 | ||||
-rw-r--r-- | source/blender/editors/mesh/editmesh_tools.c | 18 |
4 files changed, 67 insertions, 22 deletions
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index c5941a6c637..1700e5c47fd 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1076,6 +1076,7 @@ static BMOpDefine bmo_bevel_def = { {{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 */ + {BMO_OP_SLOT_ELEMENT_BUF, "faceout"}, /* output faces */ {0} /* null-terminating sentinel */}, #else {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 1e95191bc73..a8c859b2ebf 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -40,8 +40,9 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) BMEdge *e; BMVert *v; - /* first flush 'geom' into flags, this makes it possible to check connected data */ - BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE, BM_ELEM_TAG, FALSE); + /* first flush 'geom' into flags, this makes it possible to check connected data, + * BM_FACE is cleared so we can put newly created faces into a bmesh slot. */ + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, FALSE); BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { BM_elem_flag_enable(v, BM_ELEM_TAG); @@ -54,5 +55,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) } BM_mesh_bevel(bm, offset, seg); + + BMO_slot_buffer_from_enabled_hflag(bm, op, "faceout", BM_FACE, BM_ELEM_TAG); } } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index cfc7edb2400..0a75943cf8b 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -242,20 +242,24 @@ static BMFace *boundvert_rep_face(BoundVert *v) return fans; } -/* Make ngon from verts alone. +/** + * Make ngon from verts alone. * Make sure to properly copy face attributes and do custom data interpolation from - * example face, facerep. */ -static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *facerep) + * example face, facerep. + * + * \note ALL face creation goes through this function, this is important to keep! + */ +static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMFace *facerep) { BMIter iter; BMLoop *l; BMFace *f; if (totv == 3) { - f = BM_face_create_quad_tri_v(bm, vert_arr, 3, facerep, 0); + f = BM_face_create_quad_tri_v(bm, vert_arr, 3, facerep, FALSE); } else if (totv == 4) { - f = BM_face_create_quad_tri_v(bm, vert_arr, 4, facerep, 0); + f = BM_face_create_quad_tri_v(bm, vert_arr, 4, facerep, FALSE); } else { int i; @@ -278,6 +282,13 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *f BM_loop_interp_multires(bm, l, facerep); } } + + /* not essential for bevels own internal logic, + * this is done so the operator can select newly created faces */ + if (f) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + return f; } @@ -1416,8 +1427,11 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) } } - if (nsel == 0) + if (nsel == 0) { + /* signal this vert isn't being beveled */ + BM_elem_flag_disable(v, BM_ELEM_TAG); return; + } ntot = BM_vert_edge_count(v); bv = (BevVert *)BLI_memarena_alloc(bp->mem_arena, (sizeof(BevVert))); @@ -1525,7 +1539,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMVert *v) } /* Face f has at least one beveled vertex. Rebuild f */ -static void rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) +static int bev_rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) { BMIter liter; BMLoop *l, *lprev; @@ -1534,9 +1548,10 @@ static void rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) EdgeHalf *e, *eprev; VMesh *vm; int i, k; + int do_rebuild = FALSE; BMVert *bmv; BMVert **vv = NULL; - BLI_array_declare(vv); + BLI_array_staticdeclare(vv, BM_DEFAULT_NGON_STACK_SIZE); BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { bv = find_bevvert(bp, l->v); @@ -1566,13 +1581,24 @@ static void rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) v = v->prev; BLI_array_append(vv, v->nv.v); } + + do_rebuild = TRUE; } else { BLI_array_append(vv, l->v); } } - bev_create_ngon(bm, vv, BLI_array_count(vv), f); + if (do_rebuild) { + BMFace *f_new = bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + /* don't select newly created boundary faces... */ + if (f_new) { + BM_elem_flag_disable(f_new, BM_ELEM_TAG); + } + } + BLI_array_free(vv); + return do_rebuild; } /* All polygons touching v need rebuilding because beveling v has made new vertices */ @@ -1586,8 +1612,9 @@ static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert * if (LIKELY(faces != NULL)) { for (f_index = 0; f_index < faces_len; f_index++) { BMFace *f = faces[f_index]; - rebuild_polygon(bm, bp, f); - BM_face_kill(bm, f); + if (bev_rebuild_polygon(bm, bp, f)) { + BM_face_kill(bm, f); + } } if (faces != (BMFace **)faces_stack) { @@ -1664,8 +1691,13 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) } /** - * currently only bevels BM_ELEM_TAG'd verts and edges - * all tagged edges _must_ be manifold. + * - Currently only bevels BM_ELEM_TAG'd verts and edges. + * + * - Newly created faces are BM_ELEM_TAG'd too, + * the caller needs to ensure this is cleared before calling + * if its going to use this face tag. + * + * \warning all tagged edges _must_ be manifold. */ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments) { @@ -1705,9 +1737,8 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments) BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { - if (find_bevvert(&bp, v)) { - BM_vert_kill(bm, v); - } + BLI_assert(find_bevvert(&bp, v) != NULL); + BM_vert_kill(bm, v); } } diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 57d6a9b3361..0048e7d0a14 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4757,13 +4757,23 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) if (!EDBM_op_init(em, &bmop, op, "bevel geom=%hev offset=%f segments=%i", BM_ELEM_SELECT, offset, segments)) - { - return 0; - } - + { + return 0; + } + BMO_op_exec(em->bm, &bmop); + + /* no need to de-select existing geometry */ if (!EDBM_op_finish(em, &bmop, op, TRUE)) return 0; + + if (offset != 0.0f) { + /* not essential, but we may have some loose geometry that + * won't get bevel'd and better not leave it selected */ + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BMO_slot_buffer_hflag_enable(em->bm, &bmop, "faceout", BM_FACE, BM_ELEM_SELECT, TRUE); + } + #else int i; |