diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-03-14 22:04:52 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-03-14 22:04:52 +0300 |
commit | 1d5ba269c1f6b232f1ec83e77e6e8fe07d5c5d1f (patch) | |
tree | 327dc2edb006468113e185b4946ab4c3b434d68b /source/blender/bmesh | |
parent | 0f13f5a683ec9b8d024feaec5ba2ede193a618f0 (diff) | |
parent | f13c729b26befae8709a8e565a27d6fd31101d44 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh.c | 93 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_opdefines.c | 2 | ||||
-rw-r--r-- | source/blender/bmesh/operators/bmo_bisect_plane.c | 7 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bisect_plane.c | 39 | ||||
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bisect_plane.h | 2 |
5 files changed, 92 insertions, 51 deletions
diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 57a6d8d2e1a..d92d0cbb469 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -486,8 +486,7 @@ static void bm_mesh_edges_sharp_tag( BMesh *bm, const float (*vnos)[3], const float (*fnos)[3], float split_angle, float (*r_lnos)[3]) { - BMIter eiter, viter; - BMVert *v; + BMIter eiter; BMEdge *e; int i; @@ -498,19 +497,13 @@ static void bm_mesh_edges_sharp_tag( } { - char htype = BM_LOOP; + char htype = BM_VERT | BM_LOOP; if (fnos) { htype |= BM_FACE; } BM_mesh_elem_index_ensure(bm, htype); } - /* Clear all vertices' tags (means they are all smooth for now). */ - BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { - BM_elem_index_set(v, i); /* set_inline */ - BM_elem_flag_disable(v, BM_ELEM_TAG); - } - /* This first loop checks which edges are actually smooth, and pre-populate lnos with vnos (as if they were * all smooth). */ @@ -551,20 +544,45 @@ static void bm_mesh_edges_sharp_tag( no = vnos ? vnos[BM_elem_index_get(l_b->v)] : l_b->v->no; copy_v3_v3(r_lnos[BM_elem_index_get(l_b)], no); } - else { - /* Sharp edge, tag its verts as such. */ - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + } + } + + bm->elem_index_dirty &= ~BM_EDGE; +} + +/* Check whether gievn loop is part of an unknown-so-far cyclic smooth fan, or not. + * Needed because cyclic smooth fans have no obvious 'entry point', and yet we need to walk them once, and only once. */ +static bool bm_mesh_loop_check_cyclic_smooth_fan(BMLoop *l_curr) +{ + BMLoop *lfan_pivot_next = l_curr; + BMEdge *e_next = l_curr->e; + + BLI_assert(!BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)); + BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); + + while (true) { + /* Much simpler than in sibling code with basic Mesh data! */ + lfan_pivot_next = BM_vert_step_fan_loop(lfan_pivot_next, &e_next); + + if (!lfan_pivot_next || !BM_elem_flag_test(e_next, BM_ELEM_TAG)) { + /* Sharp loop/edge, so not a cyclic smooth fan... */ + return false; + } + /* Smooth loop/edge... */ + else if (BM_elem_flag_test(lfan_pivot_next, BM_ELEM_TAG)) { + if (lfan_pivot_next == l_curr) { + /* We walked around a whole cyclic smooth fan without finding any already-processed loop, means we can + * use initial l_curr/l_prev edge as start for this smooth fan. */ + return true; } + /* ... already checked in some previous looping, we can abort. */ + return false; } else { - /* Sharp edge, tag its verts as such. */ - BM_elem_flag_enable(e->v1, BM_ELEM_TAG); - BM_elem_flag_enable(e->v2, BM_ELEM_TAG); + /* ... we can skip it in future, and keep checking the smooth fan. */ + BM_elem_flag_enable(lfan_pivot_next, BM_ELEM_TAG); } } - - bm->elem_index_dirty &= ~(BM_EDGE | BM_VERT); } /* BMesh version of BKE_mesh_normals_loop_split() in mesh_evaluate.c @@ -587,13 +605,11 @@ static void bm_mesh_loops_calc_normals( BLI_Stack *edge_vectors = NULL; { - char htype = BM_LOOP; + char htype = 0; if (vcos) { htype |= BM_VERT; } - if (fnos) { - htype |= BM_FACE; - } + /* Face/Loop indices are set inline below. */ BM_mesh_elem_index_ensure(bm, htype); } @@ -606,6 +622,21 @@ static void bm_mesh_loops_calc_normals( edge_vectors = BLI_stack_new(sizeof(float[3]), __func__); } + /* Clear all loops' tags (means none are to be skipped for now). */ + int index_face, index_loop = 0; + BM_ITER_MESH_INDEX (f_curr, &fiter, bm, BM_FACES_OF_MESH, index_face) { + BMLoop *l_curr, *l_first; + + BM_elem_index_set(f_curr, index_face); /* set_inline */ + + l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); + do { + BM_elem_index_set(l_curr, index_loop++); /* set_inline */ + BM_elem_flag_disable(l_curr, BM_ELEM_TAG); + } while ((l_curr = l_curr->next) != l_first); + } + bm->elem_index_dirty &= ~(BM_FACE|BM_LOOP); + /* We now know edges that can be smoothed (they are tagged), and edges that will be hard (they aren't). * Now, time to generate the normals. */ @@ -614,16 +645,16 @@ static void bm_mesh_loops_calc_normals( l_curr = l_first = BM_FACE_FIRST_LOOP(f_curr); do { + /* A smooth edge, we have to check for cyclic smooth fan case. + * If we find a new, never-processed cyclic smooth fan, we can do it now using that loop/edge as + * 'entry point', otherwise we can skip it. */ + /* Note: In theory, we could make bm_mesh_loop_check_cyclic_smooth_fan() store mlfan_pivot's in a stack, + * to avoid having to fan again around the vert during actual computation of clnor & clnorspace. + * However, this would complicate the code, add more memory usage, and BM_vert_step_fan_loop() + * is quite cheap in term of CPU cycles, so really think it's not worth it. */ if (BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && - (!r_lnors_spacearr || BM_elem_flag_test(l_curr->v, BM_ELEM_TAG))) + (BM_elem_flag_test(l_curr, BM_ELEM_TAG) || !bm_mesh_loop_check_cyclic_smooth_fan(l_curr))) { - /* A smooth edge, and we are not generating lnors_spacearr, or the related vertex is sharp. - * We skip it because it is either: - * - in the middle of a 'smooth fan' already computed (or that will be as soon as we hit - * one of its ends, i.e. one of its two sharp edges), or... - * - the related vertex is a "full smooth" one, in which case pre-populated normals from vertex - * are just fine! - */ } else if (!BM_elem_flag_test(l_curr->e, BM_ELEM_TAG) && !BM_elem_flag_test(l_curr->prev->e, BM_ELEM_TAG)) @@ -2008,4 +2039,4 @@ void BM_mesh_toolflags_set(BMesh *bm, bool use_toolflags) vpool_dst, epool_dst, NULL, fpool_dst); bm->use_toolflags = use_toolflags; -}
\ No newline at end of file +} diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 0d0fdda2c4c..6b388a75436 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1284,7 +1284,7 @@ static BMOpDefine bmo_bisect_plane_def = { {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */ {{'\0'}}, }, - {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output new geometry from the cut */ + {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output geometry aligned with the plane (new and existing) */ {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */ {{'\0'}}}, bmo_bisect_plane_exec, diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c index bed1ea5cb94..2c80ff651b8 100644 --- a/source/blender/bmesh/operators/bmo_bisect_plane.c +++ b/source/blender/bmesh/operators/bmo_bisect_plane.c @@ -38,7 +38,8 @@ #include "intern/bmesh_operators_private.h" /* own include */ #define ELE_NEW 1 -#define ELE_INPUT 2 +#define ELE_CUT 2 +#define ELE_INPUT 4 void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) { @@ -69,7 +70,7 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) BM_mesh_bisect_plane(bm, plane, use_snap_center, true, - ELE_NEW, dist); + ELE_CUT, ELE_NEW, dist); if (clear_outer || clear_inner) { @@ -108,5 +109,5 @@ void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_CUT); } diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c index 51b92a3c45e..828c50c39fd 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.c +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c @@ -110,7 +110,7 @@ static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v) } -static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center) +static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center, const short oflag_new) { /* unlikely more than 2 verts are needed */ const unsigned int f_len_orig = (unsigned int)f->len; @@ -154,10 +154,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con /* common case, just cut the face once */ BM_face_split(bm, f, l_a, l_b, &l_new, NULL, true); if (l_new) { - if (oflag_center) { - BMO_edge_flag_enable(bm, l_new->e, oflag_center); - BMO_face_flag_enable(bm, l_new->f, oflag_center); - BMO_face_flag_enable(bm, f, oflag_center); + if (oflag_center | oflag_new) { + BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new); + } + if (oflag_new) { + BMO_face_flag_enable(bm, l_new->f, oflag_new); } } } @@ -269,10 +270,11 @@ static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], con f_tmp = BM_face_split(bm, face_split_arr[j], l_a, l_b, &l_new, NULL, true); if (l_new) { - if (oflag_center) { - BMO_edge_flag_enable(bm, l_new->e, oflag_center); - BMO_face_flag_enable(bm, l_new->f, oflag_center); - BMO_face_flag_enable(bm, face_split_arr[j], oflag_center); + if (oflag_center | oflag_new) { + BMO_edge_flag_enable(bm, l_new->e, oflag_center | oflag_new); + } + if (oflag_new) { + BMO_face_flag_enable(bm, l_new->f, oflag_new); } } @@ -307,7 +309,7 @@ finally: void BM_mesh_bisect_plane( BMesh *bm, const float plane[4], const bool use_snap_center, const bool use_tag, - const short oflag_center, const float eps) + const short oflag_center, const short oflag_new, const float eps) { unsigned int einput_len; unsigned int i; @@ -390,7 +392,7 @@ void BM_mesh_bisect_plane( const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)}; if (side[0] && side[1] && (side[0] != side[1])) { - const float e_fac = fabsf(dist[0]) / fabsf(dist[0] - dist[1]); + const float e_fac = dist[0] / (dist[0] - dist[1]); BMVert *v_new; if (e->l) { @@ -404,10 +406,17 @@ void BM_mesh_bisect_plane( } while ((l_iter = l_iter->radial_next) != l_first); } - v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac); + { + BMEdge *e_new; + v_new = BM_edge_split(bm, e, e->v1, &e_new, e_fac); + if (oflag_new) { + BMO_edge_flag_enable(bm, e_new, oflag_new); + } + } + vert_is_center_enable(v_new); - if (oflag_center) { - BMO_vert_flag_enable(bm, v_new, oflag_center); + if (oflag_new | oflag_center) { + BMO_vert_flag_enable(bm, v_new, oflag_new | oflag_center); } BM_VERT_DIR(v_new) = 0; @@ -448,7 +457,7 @@ void BM_mesh_bisect_plane( MEM_freeN(edges_arr); while ((f = BLI_LINKSTACK_POP(face_stack))) { - bm_face_bisect_verts(bm, f, plane, oflag_center); + bm_face_bisect_verts(bm, f, plane, oflag_center, oflag_new); } /* now we have all faces to split in the stack */ diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h index 7f3a97c4c79..fb99a1c8214 100644 --- a/source/blender/bmesh/tools/bmesh_bisect_plane.h +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h @@ -30,6 +30,6 @@ void BM_mesh_bisect_plane( BMesh *bm, const float plane[4], const bool use_snap_center, const bool use_tag, - const short oflag_center, const float eps); + const short oflag_center, const short oflag_new, const float eps); #endif /* __BMESH_BISECT_PLANE_H__ */ |