diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/bmesh/operators/bmo_extrude.c | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/bmesh/operators/bmo_extrude.c')
-rw-r--r-- | source/blender/bmesh/operators/bmo_extrude.c | 1366 |
1 files changed, 679 insertions, 687 deletions
diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index eaf059c7e03..cec7a920abb 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -36,9 +36,9 @@ #define USE_EDGE_REGION_FLAGS enum { - EXT_INPUT = 1, - EXT_KEEP = 2, - EXT_DEL = 4, + EXT_INPUT = 1, + EXT_KEEP = 2, + EXT_DEL = 4, }; #define VERT_MARK 1 @@ -49,80 +49,78 @@ enum { void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) { - const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history"); - GHash *select_history_map = NULL; - - BMOIter siter; - BMFace *f_org; - - if (use_select_history) { - select_history_map = BM_select_history_map_create(bm); - } - - BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) { - BMFace *f_new; - BMLoop *l_org, *l_org_first; - BMLoop *l_new; - - BMO_face_flag_enable(bm, f_org, EXT_DEL); - - f_new = BM_face_copy(bm, bm, f_org, true, true); - BMO_face_flag_enable(bm, f_new, EXT_KEEP); - - if (select_history_map) { - BMEditSelection *ese; - ese = BLI_ghash_lookup(select_history_map, f_org); - if (ese) { - ese->ele = (BMElem *)f_new; - } - } - - l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org); - l_new = BM_FACE_FIRST_LOOP(f_new); - - do { - BMFace *f_side; - BMLoop *l_side_iter; - - BM_elem_attrs_copy(bm, bm, l_org, l_new); - - f_side = BM_face_create_quad_tri(bm, - l_org->next->v, l_new->next->v, l_new->v, l_org->v, - f_org, BM_CREATE_NOP); - - l_side_iter = BM_FACE_FIRST_LOOP(f_side); - - BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next; - BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); l_side_iter = l_side_iter->next; - BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); l_side_iter = l_side_iter->next; - BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); - - if (select_history_map) { - BMEditSelection *ese; - - ese = BLI_ghash_lookup(select_history_map, l_org->v); - if (ese) { - ese->ele = (BMElem *)l_new->v; - } - ese = BLI_ghash_lookup(select_history_map, l_org->e); - if (ese) { - ese->ele = (BMElem *)l_new->e; - } - } - - } while (((void) - (l_new = l_new->next), - (l_org = l_org->next)) != l_org_first); - } - - if (select_history_map) { - BLI_ghash_free(select_history_map, NULL, NULL); - } - - BMO_op_callf(bm, op->flag, - "delete geom=%ff context=%i", - EXT_DEL, DEL_ONLYFACES); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, EXT_KEEP); + const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history"); + GHash *select_history_map = NULL; + + BMOIter siter; + BMFace *f_org; + + if (use_select_history) { + select_history_map = BM_select_history_map_create(bm); + } + + BMO_ITER (f_org, &siter, op->slots_in, "faces", BM_FACE) { + BMFace *f_new; + BMLoop *l_org, *l_org_first; + BMLoop *l_new; + + BMO_face_flag_enable(bm, f_org, EXT_DEL); + + f_new = BM_face_copy(bm, bm, f_org, true, true); + BMO_face_flag_enable(bm, f_new, EXT_KEEP); + + if (select_history_map) { + BMEditSelection *ese; + ese = BLI_ghash_lookup(select_history_map, f_org); + if (ese) { + ese->ele = (BMElem *)f_new; + } + } + + l_org = l_org_first = BM_FACE_FIRST_LOOP(f_org); + l_new = BM_FACE_FIRST_LOOP(f_new); + + do { + BMFace *f_side; + BMLoop *l_side_iter; + + BM_elem_attrs_copy(bm, bm, l_org, l_new); + + f_side = BM_face_create_quad_tri( + bm, l_org->next->v, l_new->next->v, l_new->v, l_org->v, f_org, BM_CREATE_NOP); + + l_side_iter = BM_FACE_FIRST_LOOP(f_side); + + BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); + l_side_iter = l_side_iter->next; + BM_elem_attrs_copy(bm, bm, l_org->next, l_side_iter); + l_side_iter = l_side_iter->next; + BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); + l_side_iter = l_side_iter->next; + BM_elem_attrs_copy(bm, bm, l_org, l_side_iter); + + if (select_history_map) { + BMEditSelection *ese; + + ese = BLI_ghash_lookup(select_history_map, l_org->v); + if (ese) { + ese->ele = (BMElem *)l_new->v; + } + ese = BLI_ghash_lookup(select_history_map, l_org->e); + if (ese) { + ese->ele = (BMElem *)l_new->e; + } + } + + } while (((void)(l_new = l_new->next), (l_org = l_org->next)) != l_org_first); + } + + if (select_history_map) { + BLI_ghash_free(select_history_map, NULL, NULL); + } + + BMO_op_callf(bm, op->flag, "delete geom=%ff context=%i", EXT_DEL, DEL_ONLYFACES); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, EXT_KEEP); } /** @@ -137,156 +135,157 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) */ static void bm_extrude_copy_face_loop_attributes(BMesh *bm, BMFace *f) { - /* edge we are extruded from */ - BMLoop *l_first_0 = BM_FACE_FIRST_LOOP(f); - BMLoop *l_first_1 = l_first_0->next; - BMLoop *l_first_2 = l_first_1->next; - BMLoop *l_first_3 = l_first_2->next; + /* edge we are extruded from */ + BMLoop *l_first_0 = BM_FACE_FIRST_LOOP(f); + BMLoop *l_first_1 = l_first_0->next; + BMLoop *l_first_2 = l_first_1->next; + BMLoop *l_first_3 = l_first_2->next; - BMLoop *l_other_0; - BMLoop *l_other_1; + BMLoop *l_other_0; + BMLoop *l_other_1; - if (UNLIKELY(l_first_0 == l_first_0->radial_next)) { - return; - } + if (UNLIKELY(l_first_0 == l_first_0->radial_next)) { + return; + } - l_other_0 = BM_edge_other_loop(l_first_0->e, l_first_0); - l_other_1 = BM_edge_other_loop(l_first_0->e, l_first_1); + l_other_0 = BM_edge_other_loop(l_first_0->e, l_first_0); + l_other_1 = BM_edge_other_loop(l_first_0->e, l_first_1); - /* copy data */ - BM_elem_attrs_copy(bm, bm, l_other_0->f, f); - BM_elem_flag_disable(f, BM_ELEM_HIDDEN); /* possibly we copy from a hidden face */ + /* copy data */ + BM_elem_attrs_copy(bm, bm, l_other_0->f, f); + BM_elem_flag_disable(f, BM_ELEM_HIDDEN); /* possibly we copy from a hidden face */ - BM_elem_attrs_copy(bm, bm, l_other_0, l_first_0); - BM_elem_attrs_copy(bm, bm, l_other_0, l_first_3); + BM_elem_attrs_copy(bm, bm, l_other_0, l_first_0); + BM_elem_attrs_copy(bm, bm, l_other_0, l_first_3); - BM_elem_attrs_copy(bm, bm, l_other_1, l_first_1); - BM_elem_attrs_copy(bm, bm, l_other_1, l_first_2); + BM_elem_attrs_copy(bm, bm, l_other_1, l_first_1); + BM_elem_attrs_copy(bm, bm, l_other_1, l_first_2); } /* Disable the skin root flag on the input vert, assumes that the vert * data includes an CD_MVERT_SKIN layer */ static void bm_extrude_disable_skin_root(BMesh *bm, BMVert *v) { - MVertSkin *vs; + MVertSkin *vs; - vs = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN); - vs->flag &= ~MVERT_SKIN_ROOT; + vs = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_MVERT_SKIN); + vs->flag &= ~MVERT_SKIN_ROOT; } void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) { - BMOIter siter; - BMOperator dupeop; - BMFace *f; - BMEdge *e, *e_new; - const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); - - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - BMO_edge_flag_enable(bm, e, EXT_INPUT); - BMO_vert_flag_enable(bm, e->v1, EXT_INPUT); - BMO_vert_flag_enable(bm, e->v2, EXT_INPUT); - } - - BMO_op_initf( - bm, &dupeop, op->flag, - "duplicate geom=%fve use_select_history=%b", - EXT_INPUT, BMO_slot_bool_get(op->slots_in, "use_select_history")); - - BMO_op_exec(bm, &dupeop); - - /* disable root flag on all new skin nodes */ - if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { - BMVert *v; - BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { - bm_extrude_disable_skin_root(bm, v); - } - } - - for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) { - BMVert *f_verts[4]; - e_new = BMO_iter_map_value_ptr(&siter); - - - const bool edge_normal_flip = !(e->l && e->v1 != e->l->v); - if (edge_normal_flip == use_normal_flip) { - f_verts[0] = e->v1; - f_verts[1] = e->v2; - f_verts[2] = e_new->v2; - f_verts[3] = e_new->v1; - } - else { - f_verts[0] = e->v2; - f_verts[1] = e->v1; - f_verts[2] = e_new->v1; - f_verts[3] = e_new->v2; - } - /* not sure what to do about example face, pass NULL for now */ - f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); - bm_extrude_copy_face_loop_attributes(bm, f); - - if (BMO_edge_flag_test(bm, e, EXT_INPUT)) { - e = e_new; - } - - BMO_face_flag_enable(bm, f, EXT_KEEP); - BMO_edge_flag_enable(bm, e, EXT_KEEP); - BMO_vert_flag_enable(bm, e->v1, EXT_KEEP); - BMO_vert_flag_enable(bm, e->v2, EXT_KEEP); - - } - - BMO_op_finish(bm, &dupeop); - - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, EXT_KEEP); + BMOIter siter; + BMOperator dupeop; + BMFace *f; + BMEdge *e, *e_new; + const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); + + BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { + BMO_edge_flag_enable(bm, e, EXT_INPUT); + BMO_vert_flag_enable(bm, e->v1, EXT_INPUT); + BMO_vert_flag_enable(bm, e->v2, EXT_INPUT); + } + + BMO_op_initf(bm, + &dupeop, + op->flag, + "duplicate geom=%fve use_select_history=%b", + EXT_INPUT, + BMO_slot_bool_get(op->slots_in, "use_select_history")); + + BMO_op_exec(bm, &dupeop); + + /* disable root flag on all new skin nodes */ + if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { + BMVert *v; + BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { + bm_extrude_disable_skin_root(bm, v); + } + } + + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; + e = BMO_iter_step(&siter)) { + BMVert *f_verts[4]; + e_new = BMO_iter_map_value_ptr(&siter); + + const bool edge_normal_flip = !(e->l && e->v1 != e->l->v); + if (edge_normal_flip == use_normal_flip) { + f_verts[0] = e->v1; + f_verts[1] = e->v2; + f_verts[2] = e_new->v2; + f_verts[3] = e_new->v1; + } + else { + f_verts[0] = e->v2; + f_verts[1] = e->v1; + f_verts[2] = e_new->v1; + f_verts[3] = e_new->v2; + } + /* not sure what to do about example face, pass NULL for now */ + f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); + bm_extrude_copy_face_loop_attributes(bm, f); + + if (BMO_edge_flag_test(bm, e, EXT_INPUT)) { + e = e_new; + } + + BMO_face_flag_enable(bm, f, EXT_KEEP); + BMO_edge_flag_enable(bm, e, EXT_KEEP); + BMO_vert_flag_enable(bm, e->v1, EXT_KEEP); + BMO_vert_flag_enable(bm, e->v2, EXT_KEEP); + } + + BMO_op_finish(bm, &dupeop); + + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, EXT_KEEP); } void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) { - const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history"); - BMOIter siter; - BMVert *v, *dupev; - BMEdge *e; - const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); - GHash *select_history_map = NULL; - - if (use_select_history) { - select_history_map = BM_select_history_map_create(bm); - } - - for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { - dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); - BMO_vert_flag_enable(bm, dupev, EXT_KEEP); - - if (has_vskin) { - bm_extrude_disable_skin_root(bm, v); - } - - if (select_history_map) { - BMEditSelection *ese; - ese = BLI_ghash_lookup(select_history_map, v); - if (ese) { - ese->ele = (BMElem *)dupev; - } - } - - /* not essential, but ensures face normals from extruded edges are contiguous */ - if (BM_vert_is_wire_endpoint(v)) { - if (v->e->v1 == v) { - SWAP(BMVert *, v, dupev); - } - } - - e = BM_edge_create(bm, v, dupev, NULL, BM_CREATE_NOP); - BMO_edge_flag_enable(bm, e, EXT_KEEP); - } - - if (select_history_map) { - BLI_ghash_free(select_history_map, NULL, NULL); - } - - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP); + const bool use_select_history = BMO_slot_bool_get(op->slots_in, "use_select_history"); + BMOIter siter; + BMVert *v, *dupev; + BMEdge *e; + const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); + GHash *select_history_map = NULL; + + if (use_select_history) { + select_history_map = BM_select_history_map_create(bm); + } + + for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { + dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); + BMO_vert_flag_enable(bm, dupev, EXT_KEEP); + + if (has_vskin) { + bm_extrude_disable_skin_root(bm, v); + } + + if (select_history_map) { + BMEditSelection *ese; + ese = BLI_ghash_lookup(select_history_map, v); + if (ese) { + ese->ele = (BMElem *)dupev; + } + } + + /* not essential, but ensures face normals from extruded edges are contiguous */ + if (BM_vert_is_wire_endpoint(v)) { + if (v->e->v1 == v) { + SWAP(BMVert *, v, dupev); + } + } + + e = BM_edge_create(bm, v, dupev, NULL, BM_CREATE_NOP); + BMO_edge_flag_enable(bm, e, EXT_KEEP); + } + + if (select_history_map) { + BLI_ghash_free(select_history_map, NULL, NULL); + } + + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "verts.out", BM_VERT, EXT_KEEP); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "edges.out", BM_EDGE, EXT_KEEP); } #ifdef USE_EDGE_REGION_FLAGS @@ -296,280 +295,275 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) */ static bool bm_extrude_region_edge_flag(const BMVert *v, char r_e_hflag[2]) { - BMEdge *e_iter; - const char hflag_enable = BM_ELEM_SEAM; - const char hflag_disable = BM_ELEM_SMOOTH; - bool ok = false; - - r_e_hflag[0] = 0x0; - r_e_hflag[1] = 0xff; - - /* clear flags on both disks */ - e_iter = v->e; - do { - if (e_iter->l && !BM_edge_is_boundary(e_iter)) { - r_e_hflag[0] |= e_iter->head.hflag; - r_e_hflag[1] &= e_iter->head.hflag; - ok = true; - } - } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != v->e); - - if (ok) { - r_e_hflag[0] &= hflag_enable; - r_e_hflag[1] = hflag_disable & ~r_e_hflag[1]; - } - return ok; + BMEdge *e_iter; + const char hflag_enable = BM_ELEM_SEAM; + const char hflag_disable = BM_ELEM_SMOOTH; + bool ok = false; + + r_e_hflag[0] = 0x0; + r_e_hflag[1] = 0xff; + + /* clear flags on both disks */ + e_iter = v->e; + do { + if (e_iter->l && !BM_edge_is_boundary(e_iter)) { + r_e_hflag[0] |= e_iter->head.hflag; + r_e_hflag[1] &= e_iter->head.hflag; + ok = true; + } + } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != v->e); + + if (ok) { + r_e_hflag[0] &= hflag_enable; + r_e_hflag[1] = hflag_disable & ~r_e_hflag[1]; + } + return ok; } -#endif /* USE_EDGE_REGION_FLAGS */ +#endif /* USE_EDGE_REGION_FLAGS */ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) { - BMOperator dupeop, delop; - BMOIter siter; - BMIter iter, fiter, viter; - BMEdge *e, *e_new; - BMVert *v; - BMFace *f; - bool found, delorig = false; - BMOpSlot *slot_facemap_out; - BMOpSlot *slot_edges_exclude; - const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); - const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in, "use_normal_from_adjacent"); - - /* initialize our sub-operators */ - BMO_op_initf( - bm, &dupeop, op->flag, - "duplicate use_select_history=%b", - BMO_slot_bool_get(op->slots_in, "use_select_history")); - - BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT); - - /* if one flagged face is bordered by an un-flagged face, then we delete - * original geometry unless caller explicitly asked to keep it. */ - if (!BMO_slot_bool_get(op->slots_in, "use_keep_orig")) { - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { - - int edge_face_tot; - - if (!BMO_edge_flag_test(bm, e, EXT_INPUT)) { - continue; - } - - found = false; /* found a face that isn't input? */ - edge_face_tot = 0; /* edge/face count */ - - BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { - if (!BMO_face_flag_test(bm, f, EXT_INPUT)) { - found = true; - delorig = true; - break; - } - - edge_face_tot++; - } - - if ((edge_face_tot > 1) && (found == false)) { - /* edge has a face user, that face isn't extrude input */ - BMO_edge_flag_enable(bm, e, EXT_DEL); - } - } - } - - /* calculate verts to delete */ - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - if (v->e) { /* only deal with verts attached to geometry [#33651] */ - found = false; - - BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) { - if (!BMO_edge_flag_test(bm, e, EXT_INPUT) || - !BMO_edge_flag_test(bm, e, EXT_DEL)) - { - found = true; - break; - } - } - - /* avoid an extra loop */ - if (found == true) { - BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) { - if (!BMO_face_flag_test(bm, f, EXT_INPUT)) { - found = true; - break; - } - } - } - - if (found == false) { - BMO_vert_flag_enable(bm, v, EXT_DEL); - } - } - } - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test(bm, f, EXT_INPUT)) { - BMO_face_flag_enable(bm, f, EXT_DEL); - } - } - - if (delorig == true) { - BMO_op_initf(bm, &delop, op->flag, - "delete geom=%fvef context=%i", - EXT_DEL, DEL_ONLYTAGGED); - } - - BMO_slot_copy(op, slots_in, "geom", - &dupeop, slots_in, "geom"); - BMO_op_exec(bm, &dupeop); - - /* disable root flag on all new skin nodes */ - if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { - BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { - bm_extrude_disable_skin_root(bm, v); - } - } - - slot_facemap_out = BMO_slot_get(dupeop.slots_out, "face_map.out"); - if (bm->act_face && BMO_face_flag_test(bm, bm->act_face, EXT_INPUT)) { - bm->act_face = BMO_slot_map_elem_get(slot_facemap_out, bm->act_face); - } - - if (delorig) { - BMO_op_exec(bm, &delop); - } - - /* if not delorig, reverse loops of original face */ - if (!delorig) { - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test(bm, f, EXT_INPUT)) { - BM_face_normal_flip(bm, f); - } - } - } - - BMO_slot_copy(&dupeop, slots_out, "geom.out", - op, slots_out, "geom.out"); - - slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); - for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) { - BMVert *f_verts[4]; + BMOperator dupeop, delop; + BMOIter siter; + BMIter iter, fiter, viter; + BMEdge *e, *e_new; + BMVert *v; + BMFace *f; + bool found, delorig = false; + BMOpSlot *slot_facemap_out; + BMOpSlot *slot_edges_exclude; + const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); + const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in, + "use_normal_from_adjacent"); + + /* initialize our sub-operators */ + BMO_op_initf(bm, + &dupeop, + op->flag, + "duplicate use_select_history=%b", + BMO_slot_bool_get(op->slots_in, "use_select_history")); + + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, EXT_INPUT); + + /* if one flagged face is bordered by an un-flagged face, then we delete + * original geometry unless caller explicitly asked to keep it. */ + if (!BMO_slot_bool_get(op->slots_in, "use_keep_orig")) { + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + + int edge_face_tot; + + if (!BMO_edge_flag_test(bm, e, EXT_INPUT)) { + continue; + } + + found = false; /* found a face that isn't input? */ + edge_face_tot = 0; /* edge/face count */ + + BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { + if (!BMO_face_flag_test(bm, f, EXT_INPUT)) { + found = true; + delorig = true; + break; + } + + edge_face_tot++; + } + + if ((edge_face_tot > 1) && (found == false)) { + /* edge has a face user, that face isn't extrude input */ + BMO_edge_flag_enable(bm, e, EXT_DEL); + } + } + } + + /* calculate verts to delete */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (v->e) { /* only deal with verts attached to geometry [#33651] */ + found = false; + + BM_ITER_ELEM (e, &viter, v, BM_EDGES_OF_VERT) { + if (!BMO_edge_flag_test(bm, e, EXT_INPUT) || !BMO_edge_flag_test(bm, e, EXT_DEL)) { + found = true; + break; + } + } + + /* avoid an extra loop */ + if (found == true) { + BM_ITER_ELEM (f, &viter, v, BM_FACES_OF_VERT) { + if (!BMO_face_flag_test(bm, f, EXT_INPUT)) { + found = true; + break; + } + } + } + + if (found == false) { + BMO_vert_flag_enable(bm, v, EXT_DEL); + } + } + } + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test(bm, f, EXT_INPUT)) { + BMO_face_flag_enable(bm, f, EXT_DEL); + } + } + + if (delorig == true) { + BMO_op_initf(bm, &delop, op->flag, "delete geom=%fvef context=%i", EXT_DEL, DEL_ONLYTAGGED); + } + + BMO_slot_copy(op, slots_in, "geom", &dupeop, slots_in, "geom"); + BMO_op_exec(bm, &dupeop); + + /* disable root flag on all new skin nodes */ + if (CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { + BMO_ITER (v, &siter, dupeop.slots_out, "geom.out", BM_VERT) { + bm_extrude_disable_skin_root(bm, v); + } + } + + slot_facemap_out = BMO_slot_get(dupeop.slots_out, "face_map.out"); + if (bm->act_face && BMO_face_flag_test(bm, bm->act_face, EXT_INPUT)) { + bm->act_face = BMO_slot_map_elem_get(slot_facemap_out, bm->act_face); + } + + if (delorig) { + BMO_op_exec(bm, &delop); + } + + /* if not delorig, reverse loops of original face */ + if (!delorig) { + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test(bm, f, EXT_INPUT)) { + BM_face_normal_flip(bm, f); + } + } + } + + BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out"); + + slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); + for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; + e = BMO_iter_step(&siter)) { + BMVert *f_verts[4]; #ifdef USE_EDGE_REGION_FLAGS - BMEdge *f_edges[4]; + BMEdge *f_edges[4]; #endif - /* this should always be wire, so this is mainly a speedup to avoid map lookup */ - if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) { - BMVert *v1 = e->v1, *v2 = e->v2; - - /* The original edge was excluded, - * this would result in a standalone wire edge - see [#30399] */ - BM_edge_kill(bm, e); - - /* kill standalone vertices from this edge - see [#32341] */ - if (!v1->e) { - BM_vert_kill(bm, v1); - } - if (!v2->e) { - BM_vert_kill(bm, v2); - } - - continue; - } - - /* skip creating face for excluded edges see [#35503] */ - if (BMO_slot_map_contains(slot_edges_exclude, e)) { - /* simply skip creating the face */ - continue; - } - - e_new = BMO_iter_map_value_ptr(&siter); - - if (!e_new) { - continue; - } - - bool edge_normal_flip; - if (use_normal_from_adjacent == false) { - /* Orient loop to give same normal as a loop of 'e_new' - * if it exists (will be one of the faces from the region), - * else same normal as a loop of e, if it exists. */ - edge_normal_flip = !( - e_new->l ? - (e_new->l->v == e_new->v1) : - (!e->l || !(e->l->v == e->v1))); - } - else { - /* Special case, needed for repetitive extrusions - * that use the normals from the previously created faces. */ - edge_normal_flip = !(e->l && e->v1 != e->l->v); - } - - if (edge_normal_flip == use_normal_flip) { - f_verts[0] = e->v1; - f_verts[1] = e->v2; - f_verts[2] = e_new->v2; - f_verts[3] = e_new->v1; - } - else { - f_verts[0] = e->v2; - f_verts[1] = e->v1; - f_verts[2] = e_new->v1; - f_verts[3] = e_new->v2; - } + /* this should always be wire, so this is mainly a speedup to avoid map lookup */ + if (BM_edge_is_wire(e) && BMO_slot_map_contains(slot_edges_exclude, e)) { + BMVert *v1 = e->v1, *v2 = e->v2; + + /* The original edge was excluded, + * this would result in a standalone wire edge - see [#30399] */ + BM_edge_kill(bm, e); + + /* kill standalone vertices from this edge - see [#32341] */ + if (!v1->e) { + BM_vert_kill(bm, v1); + } + if (!v2->e) { + BM_vert_kill(bm, v2); + } + + continue; + } + + /* skip creating face for excluded edges see [#35503] */ + if (BMO_slot_map_contains(slot_edges_exclude, e)) { + /* simply skip creating the face */ + continue; + } + + e_new = BMO_iter_map_value_ptr(&siter); + + if (!e_new) { + continue; + } + + bool edge_normal_flip; + if (use_normal_from_adjacent == false) { + /* Orient loop to give same normal as a loop of 'e_new' + * if it exists (will be one of the faces from the region), + * else same normal as a loop of e, if it exists. */ + edge_normal_flip = !(e_new->l ? (e_new->l->v == e_new->v1) : (!e->l || !(e->l->v == e->v1))); + } + else { + /* Special case, needed for repetitive extrusions + * that use the normals from the previously created faces. */ + edge_normal_flip = !(e->l && e->v1 != e->l->v); + } + + if (edge_normal_flip == use_normal_flip) { + f_verts[0] = e->v1; + f_verts[1] = e->v2; + f_verts[2] = e_new->v2; + f_verts[3] = e_new->v1; + } + else { + f_verts[0] = e->v2; + f_verts[1] = e->v1; + f_verts[2] = e_new->v1; + f_verts[3] = e_new->v2; + } #ifdef USE_EDGE_REGION_FLAGS - /* handle new edges */ - f_edges[0] = e; - f_edges[2] = e_new; - - f_edges[1] = BM_edge_exists(f_verts[1], f_verts[2]); - if (f_edges[1] == NULL) { - char e_hflag[2]; - bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[2], e_hflag); - f_edges[1] = BM_edge_create(bm, f_verts[1], f_verts[2], NULL, BM_CREATE_NOP); - if (e_hflag_ok) { - BM_elem_flag_enable(f_edges[1], e_hflag[0]); - BM_elem_flag_disable(f_edges[1], e_hflag[1]); - } - } - - f_edges[3] = BM_edge_exists(f_verts[3], f_verts[0]); - if (f_edges[3] == NULL) { - char e_hflag[2]; - bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[3], e_hflag); - f_edges[3] = BM_edge_create(bm, f_verts[3], f_verts[0], NULL, BM_CREATE_NOP); - if (e_hflag_ok) { - BM_elem_flag_enable(f_edges[3], e_hflag[0]); - BM_elem_flag_disable(f_edges[3], e_hflag[1]); - } - } - - f = BM_face_create(bm, f_verts, f_edges, 4, NULL, BM_CREATE_NOP); + /* handle new edges */ + f_edges[0] = e; + f_edges[2] = e_new; + + f_edges[1] = BM_edge_exists(f_verts[1], f_verts[2]); + if (f_edges[1] == NULL) { + char e_hflag[2]; + bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[2], e_hflag); + f_edges[1] = BM_edge_create(bm, f_verts[1], f_verts[2], NULL, BM_CREATE_NOP); + if (e_hflag_ok) { + BM_elem_flag_enable(f_edges[1], e_hflag[0]); + BM_elem_flag_disable(f_edges[1], e_hflag[1]); + } + } + + f_edges[3] = BM_edge_exists(f_verts[3], f_verts[0]); + if (f_edges[3] == NULL) { + char e_hflag[2]; + bool e_hflag_ok = bm_extrude_region_edge_flag(f_verts[3], e_hflag); + f_edges[3] = BM_edge_create(bm, f_verts[3], f_verts[0], NULL, BM_CREATE_NOP); + if (e_hflag_ok) { + BM_elem_flag_enable(f_edges[3], e_hflag[0]); + BM_elem_flag_disable(f_edges[3], e_hflag[1]); + } + } + + f = BM_face_create(bm, f_verts, f_edges, 4, NULL, BM_CREATE_NOP); #else - f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); + f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); #endif - bm_extrude_copy_face_loop_attributes(bm, f); - } - - /* link isolated vert */ - for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) { - BMVert *v2 = BMO_iter_map_value_ptr(&siter); - - /* not essential, but ensures face normals from extruded edges are contiguous */ - if (BM_vert_is_wire_endpoint(v)) { - if (v->e->v1 == v) { - SWAP(BMVert *, v, v2); - } - } - - BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE); - } - - /* cleanup */ - if (delorig) { - BMO_op_finish(bm, &delop); - } - BMO_op_finish(bm, &dupeop); + bm_extrude_copy_face_loop_attributes(bm, f); + } + + /* link isolated vert */ + for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; + v = BMO_iter_step(&siter)) { + BMVert *v2 = BMO_iter_map_value_ptr(&siter); + + /* not essential, but ensures face normals from extruded edges are contiguous */ + if (BM_vert_is_wire_endpoint(v)) { + if (v->e->v1 == v) { + SWAP(BMVert *, v, v2); + } + } + + BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE); + } + + /* cleanup */ + if (delorig) { + BMO_op_finish(bm, &delop); + } + BMO_op_finish(bm, &dupeop); } /* @@ -580,231 +574,229 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) */ static void calc_solidify_normals(BMesh *bm) { - BMIter viter, eiter, fiter; - BMVert *v; - BMEdge *e; - BMFace *f, *f1, *f2; - float edge_normal[3]; - int i; - - /* can't use BM_edge_face_count because we need to count only marked faces */ - int *edge_face_count = MEM_callocN(sizeof(int) * bm->totedge, __func__); - - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - BM_elem_flag_enable(v, BM_ELEM_TAG); - } - - BM_mesh_elem_index_ensure(bm, BM_EDGE); - - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - if (!BMO_face_flag_test(bm, f, FACE_MARK)) { - continue; - } - - BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) { - - /* And mark all edges and vertices on the - * marked faces */ - BMO_edge_flag_enable(bm, e, EDGE_MARK); - BMO_vert_flag_enable(bm, e->v1, VERT_MARK); - BMO_vert_flag_enable(bm, e->v2, VERT_MARK); - edge_face_count[BM_elem_index_get(e)]++; - } - } - - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) { - continue; - } - - i = edge_face_count[BM_elem_index_get(e)]++; - - if (i == 0 || i > 2) { - /* Edge & vertices are non-manifold even when considering - * only marked faces */ - BMO_edge_flag_enable(bm, e, EDGE_NONMAN); - BMO_vert_flag_enable(bm, e->v1, VERT_NONMAN); - BMO_vert_flag_enable(bm, e->v2, VERT_NONMAN); - } - } - MEM_freeN(edge_face_count); - edge_face_count = NULL; /* don't re-use */ - - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - if (!BM_vert_is_manifold(v)) { - BMO_vert_flag_enable(bm, v, VERT_NONMAN); - continue; - } - - if (BMO_vert_flag_test(bm, v, VERT_MARK)) { - zero_v3(v->no); - } - } - - BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { - - /* If the edge is not part of a the solidify region - * its normal should not be considered */ - if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) { - continue; - } - - /* If the edge joins more than two marked faces high - * quality normal computation won't work */ - if (BMO_edge_flag_test(bm, e, EDGE_NONMAN)) { - continue; - } - - f1 = f2 = NULL; - - BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { - if (BMO_face_flag_test(bm, f, FACE_MARK)) { - if (f1 == NULL) { - f1 = f; - } - else { - BLI_assert(f2 == NULL); - f2 = f; - } - } - } - - BLI_assert(f1 != NULL); - - if (f2 != NULL) { - const float angle = angle_normalized_v3v3(f1->no, f2->no); - - if (angle > 0.0f) { - /* two faces using this edge, calculate the edge normal - * using the angle between the faces as a weighting */ - add_v3_v3v3(edge_normal, f1->no, f2->no); - normalize_v3_length(edge_normal, angle); - } - else { - /* can't do anything useful here! - * Set the face index for a vert in case it gets a zero normal */ - BM_elem_flag_disable(e->v1, BM_ELEM_TAG); - BM_elem_flag_disable(e->v2, BM_ELEM_TAG); - continue; - } - } - else { - /* only one face attached to that edge */ - /* an edge without another attached- the weight on this is undefined, - * M_PI_2 is 90d in radians and that seems good enough */ - copy_v3_v3(edge_normal, f1->no); - mul_v3_fl(edge_normal, M_PI_2); - } - - add_v3_v3(e->v1->no, edge_normal); - add_v3_v3(e->v2->no, edge_normal); - } - - /* normalize accumulated vertex normal */ - BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { - if (!BMO_vert_flag_test(bm, v, VERT_MARK)) { - continue; - } - - if (BMO_vert_flag_test(bm, v, VERT_NONMAN)) { - /* use standard normals for vertices connected to non-manifold edges */ - BM_vert_normal_update(v); - } - else if (normalize_v3(v->no) == 0.0f && !BM_elem_flag_test(v, BM_ELEM_TAG)) { - /* exceptional case, totally flat. use the normal - * of any marked face around the vertex */ - BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { - if (BMO_face_flag_test(bm, f, FACE_MARK)) { - break; - } - } - copy_v3_v3(v->no, f->no); - } - } + BMIter viter, eiter, fiter; + BMVert *v; + BMEdge *e; + BMFace *f, *f1, *f2; + float edge_normal[3]; + int i; + + /* can't use BM_edge_face_count because we need to count only marked faces */ + int *edge_face_count = MEM_callocN(sizeof(int) * bm->totedge, __func__); + + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + + BM_mesh_elem_index_ensure(bm, BM_EDGE); + + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + if (!BMO_face_flag_test(bm, f, FACE_MARK)) { + continue; + } + + BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) { + + /* And mark all edges and vertices on the + * marked faces */ + BMO_edge_flag_enable(bm, e, EDGE_MARK); + BMO_vert_flag_enable(bm, e->v1, VERT_MARK); + BMO_vert_flag_enable(bm, e->v2, VERT_MARK); + edge_face_count[BM_elem_index_get(e)]++; + } + } + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) { + continue; + } + + i = edge_face_count[BM_elem_index_get(e)]++; + + if (i == 0 || i > 2) { + /* Edge & vertices are non-manifold even when considering + * only marked faces */ + BMO_edge_flag_enable(bm, e, EDGE_NONMAN); + BMO_vert_flag_enable(bm, e->v1, VERT_NONMAN); + BMO_vert_flag_enable(bm, e->v2, VERT_NONMAN); + } + } + MEM_freeN(edge_face_count); + edge_face_count = NULL; /* don't re-use */ + + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + if (!BM_vert_is_manifold(v)) { + BMO_vert_flag_enable(bm, v, VERT_NONMAN); + continue; + } + + if (BMO_vert_flag_test(bm, v, VERT_MARK)) { + zero_v3(v->no); + } + } + + BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) { + + /* If the edge is not part of a the solidify region + * its normal should not be considered */ + if (!BMO_edge_flag_test(bm, e, EDGE_MARK)) { + continue; + } + + /* If the edge joins more than two marked faces high + * quality normal computation won't work */ + if (BMO_edge_flag_test(bm, e, EDGE_NONMAN)) { + continue; + } + + f1 = f2 = NULL; + + BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { + if (BMO_face_flag_test(bm, f, FACE_MARK)) { + if (f1 == NULL) { + f1 = f; + } + else { + BLI_assert(f2 == NULL); + f2 = f; + } + } + } + + BLI_assert(f1 != NULL); + + if (f2 != NULL) { + const float angle = angle_normalized_v3v3(f1->no, f2->no); + + if (angle > 0.0f) { + /* two faces using this edge, calculate the edge normal + * using the angle between the faces as a weighting */ + add_v3_v3v3(edge_normal, f1->no, f2->no); + normalize_v3_length(edge_normal, angle); + } + else { + /* can't do anything useful here! + * Set the face index for a vert in case it gets a zero normal */ + BM_elem_flag_disable(e->v1, BM_ELEM_TAG); + BM_elem_flag_disable(e->v2, BM_ELEM_TAG); + continue; + } + } + else { + /* only one face attached to that edge */ + /* an edge without another attached- the weight on this is undefined, + * M_PI_2 is 90d in radians and that seems good enough */ + copy_v3_v3(edge_normal, f1->no); + mul_v3_fl(edge_normal, M_PI_2); + } + + add_v3_v3(e->v1->no, edge_normal); + add_v3_v3(e->v2->no, edge_normal); + } + + /* normalize accumulated vertex normal */ + BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) { + if (!BMO_vert_flag_test(bm, v, VERT_MARK)) { + continue; + } + + if (BMO_vert_flag_test(bm, v, VERT_NONMAN)) { + /* use standard normals for vertices connected to non-manifold edges */ + BM_vert_normal_update(v); + } + else if (normalize_v3(v->no) == 0.0f && !BM_elem_flag_test(v, BM_ELEM_TAG)) { + /* exceptional case, totally flat. use the normal + * of any marked face around the vertex */ + BM_ITER_ELEM (f, &fiter, v, BM_FACES_OF_VERT) { + if (BMO_face_flag_test(bm, f, FACE_MARK)) { + break; + } + } + copy_v3_v3(v->no, f->no); + } + } } static void solidify_add_thickness(BMesh *bm, const float dist) { - BMFace *f; - BMVert *v; - BMLoop *l; - BMIter iter, loopIter; - float *vert_angles = MEM_callocN(sizeof(float) * bm->totvert * 2, "solidify"); /* 2 in 1 */ - float *vert_accum = vert_angles + bm->totvert; - int i, index; - - BLI_buffer_declare_static(float, face_angles_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); - BLI_buffer_declare_static(float *, verts_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - if (BMO_face_flag_test(bm, f, FACE_MARK)) { - - /* array for passing verts to angle_poly_v3 */ - float *face_angles = BLI_buffer_reinit_data(&face_angles_buf, float, f->len); - /* array for receiving angles from angle_poly_v3 */ - float **verts = BLI_buffer_reinit_data(&verts_buf, float *, f->len); - - BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) { - verts[i] = l->v->co; - } - - angle_poly_v3(face_angles, (const float **)verts, f->len); - - i = 0; - BM_ITER_ELEM (l, &loopIter, f, BM_LOOPS_OF_FACE) { - v = l->v; - index = BM_elem_index_get(v); - vert_accum[index] += face_angles[i]; - vert_angles[index] += shell_v3v3_normalized_to_dist(v->no, f->no) * face_angles[i]; - i++; - } - } - } - - BLI_buffer_free(&face_angles_buf); - BLI_buffer_free(&verts_buf); - - BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { - index = BM_elem_index_get(v); - if (vert_accum[index]) { /* zero if unselected */ - madd_v3_v3fl(v->co, v->no, dist * (vert_angles[index] / vert_accum[index])); - } - } - - MEM_freeN(vert_angles); + BMFace *f; + BMVert *v; + BMLoop *l; + BMIter iter, loopIter; + float *vert_angles = MEM_callocN(sizeof(float) * bm->totvert * 2, "solidify"); /* 2 in 1 */ + float *vert_accum = vert_angles + bm->totvert; + int i, index; + + BLI_buffer_declare_static(float, face_angles_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + BLI_buffer_declare_static(float *, verts_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BMO_face_flag_test(bm, f, FACE_MARK)) { + + /* array for passing verts to angle_poly_v3 */ + float *face_angles = BLI_buffer_reinit_data(&face_angles_buf, float, f->len); + /* array for receiving angles from angle_poly_v3 */ + float **verts = BLI_buffer_reinit_data(&verts_buf, float *, f->len); + + BM_ITER_ELEM_INDEX(l, &loopIter, f, BM_LOOPS_OF_FACE, i) + { + verts[i] = l->v->co; + } + + angle_poly_v3(face_angles, (const float **)verts, f->len); + + i = 0; + BM_ITER_ELEM (l, &loopIter, f, BM_LOOPS_OF_FACE) { + v = l->v; + index = BM_elem_index_get(v); + vert_accum[index] += face_angles[i]; + vert_angles[index] += shell_v3v3_normalized_to_dist(v->no, f->no) * face_angles[i]; + i++; + } + } + } + + BLI_buffer_free(&face_angles_buf); + BLI_buffer_free(&verts_buf); + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + index = BM_elem_index_get(v); + if (vert_accum[index]) { /* zero if unselected */ + madd_v3_v3fl(v->co, v->no, dist * (vert_angles[index] / vert_accum[index])); + } + } + + MEM_freeN(vert_angles); } void bmo_solidify_face_region_exec(BMesh *bm, BMOperator *op) { - BMOperator extrudeop; - BMOperator reverseop; - float thickness; - - thickness = BMO_slot_float_get(op->slots_in, "thickness"); - - /* Flip original faces (so the shell is extruded inward) */ - BMO_op_init(bm, &reverseop, op->flag, "reverse_faces"); - BMO_slot_bool_set(reverseop.slots_in, "flip_multires", true); - BMO_slot_copy(op, slots_in, "geom", - &reverseop, slots_in, "faces"); - BMO_op_exec(bm, &reverseop); - BMO_op_finish(bm, &reverseop); - - /* Extrude the region */ - BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", true); - BMO_slot_copy(op, slots_in, "geom", - &extrudeop, slots_in, "geom"); - BMO_op_exec(bm, &extrudeop); - - /* Push the verts of the extruded faces inward to create thickness */ - BMO_slot_buffer_flag_enable(bm, extrudeop.slots_out, "geom.out", BM_FACE, FACE_MARK); - calc_solidify_normals(bm); - solidify_add_thickness(bm, thickness); - - BMO_slot_copy(&extrudeop, slots_out, "geom.out", - op, slots_out, "geom.out"); - - BMO_op_finish(bm, &extrudeop); + BMOperator extrudeop; + BMOperator reverseop; + float thickness; + + thickness = BMO_slot_float_get(op->slots_in, "thickness"); + + /* Flip original faces (so the shell is extruded inward) */ + BMO_op_init(bm, &reverseop, op->flag, "reverse_faces"); + BMO_slot_bool_set(reverseop.slots_in, "flip_multires", true); + BMO_slot_copy(op, slots_in, "geom", &reverseop, slots_in, "faces"); + BMO_op_exec(bm, &reverseop); + BMO_op_finish(bm, &reverseop); + + /* Extrude the region */ + BMO_op_initf(bm, &extrudeop, op->flag, "extrude_face_region use_keep_orig=%b", true); + BMO_slot_copy(op, slots_in, "geom", &extrudeop, slots_in, "geom"); + BMO_op_exec(bm, &extrudeop); + + /* Push the verts of the extruded faces inward to create thickness */ + BMO_slot_buffer_flag_enable(bm, extrudeop.slots_out, "geom.out", BM_FACE, FACE_MARK); + calc_solidify_normals(bm); + solidify_add_thickness(bm, thickness); + + BMO_slot_copy(&extrudeop, slots_out, "geom.out", op, slots_out, "geom.out"); + + BMO_op_finish(bm, &extrudeop); } |