diff options
author | Campbell Barton <ideasman42@gmail.com> | 2016-11-09 14:25:31 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2016-11-09 16:08:26 +0300 |
commit | 49a3eaa3dc416d7f8c96c4c01da95c52a587821b (patch) | |
tree | d6a3daa41a75bdbf02a56de0ed7606b2eb08e412 | |
parent | e9689e1a204ee9b74fae7d0051b79649e79035f7 (diff) |
BMesh: face-flip, no need for temporary edge-array
Reverse loops in-place.
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.c | 85 | ||||
-rw-r--r-- | source/blender/bmesh/intern/bmesh_core.h | 2 |
2 files changed, 51 insertions, 36 deletions
diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 6abc52d75ef..ac4eb2c33fd 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -1019,18 +1019,12 @@ static int UNUSED_FUNCTION(bm_loop_length)(BMLoop *l) * \brief Loop Reverse * * Changes the winding order of a face from CW to CCW or vice versa. - * This euler is a bit peculiar in comparison to others as it is its - * own inverse. - * - * BMESH_TODO: reinsert validation code. * * \param cd_loop_mdisp_offset: Cached result of `CustomData_get_offset(&bm->ldata, CD_MDISPS)`. * \param use_loop_mdisp_flip: When set, flip the Z-depth of the mdisp, * (use when flipping normals, disable when mirroring, eg: symmetrize). - * - * \return Success */ -static bool bm_loop_reverse_loop( +static void bm_loop_reverse_loop( BMesh *bm, BMFace *f, #ifdef USE_BMESH_HOLES BMLoopList *lst, @@ -1044,39 +1038,62 @@ static bool bm_loop_reverse_loop( BMLoop *l_first = f->l_first; #endif - const int len = f->len; - BMLoop *l_iter; - BMEdge **edar = BLI_array_alloca(edar, len); - int i; + /* track previous cycles radial state */ + BMEdge *e_prev = l_first->prev->e; + BMLoop *l_prev_radial_next = l_first->prev->radial_next; + BMLoop *l_prev_radial_prev = l_first->prev->radial_prev; + bool is_prev_boundary = l_prev_radial_next == l_prev_radial_next->radial_next; - for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { - bmesh_radial_loop_remove((edar[i] = l_iter->e), l_iter); - } + BMLoop *l_iter = l_first; + do { + BMEdge *e_iter = l_iter->e; + BMLoop *l_iter_radial_next = l_iter->radial_next; + BMLoop *l_iter_radial_prev = l_iter->radial_prev; + bool is_iter_boundary = l_iter_radial_next == l_iter_radial_next->radial_next; + +#if 0 + bmesh_radial_loop_remove(e_curr, l_iter); + bmesh_radial_loop_append(e_prev, l_iter); +#else + /* inline loop reversal */ + if (is_prev_boundary) { + /* boundary */ + l_iter->radial_next = l_iter; + l_iter->radial_prev = l_iter; + } + else { + /* non-boundary, replace radial links */ + l_iter->radial_next = l_prev_radial_next; + l_iter->radial_prev = l_prev_radial_prev; + l_prev_radial_next->radial_prev = l_iter; + l_prev_radial_prev->radial_next = l_iter; + } + + if (e_iter->l == l_iter) { + e_iter->l = l_iter->next; + } + l_iter->e = e_prev; +#endif + + SWAP(BMLoop *, l_iter->next, l_iter->prev); - /* actually reverse the loop */ - for (i = 0, l_iter = l_first; i < len; i++) { - BMLoop *oldnext = l_iter->next; - BMLoop *oldprev = l_iter->prev; - l_iter->next = oldprev; - l_iter->prev = oldnext; - l_iter = oldnext; - if (cd_loop_mdisp_offset != -1) { MDisps *md = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_mdisp_offset); BKE_mesh_mdisp_flip(md, use_loop_mdisp_flip); } - } - /* rebuild radial */ - for (i = 0, l_iter = l_first->prev; i < len; i++, l_iter = l_iter->prev) { - BLI_assert(BM_verts_in_edge(l_iter->v, l_iter->next->v, edar[i])); - l_iter->e = edar[i]; - bmesh_radial_loop_append(l_iter->e, l_iter); - } + e_prev = e_iter; + l_prev_radial_next = l_iter_radial_next; + l_prev_radial_prev = l_iter_radial_prev; + is_prev_boundary = is_iter_boundary; + + /* step to next (now swapped) */ + } while ((l_iter = l_iter->prev) != l_first); #ifndef NDEBUG /* validate radial */ - for (i = 0, l_iter = l_first; i < len; i++, l_iter = l_iter->next) { + int i; + for (i = 0, l_iter = l_first; i < f->len; i++, l_iter = l_iter->next) { BM_CHECK_ELEMENT(l_iter); BM_CHECK_ELEMENT(l_iter->e); BM_CHECK_ELEMENT(l_iter->v); @@ -1088,21 +1105,19 @@ static bool bm_loop_reverse_loop( /* Loop indices are no more valid! */ bm->elem_index_dirty |= BM_LOOP; - - return true; } /** * \brief Flip the faces direction */ -bool bmesh_loop_reverse( +void bmesh_loop_reverse( BMesh *bm, BMFace *f, const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) { #ifdef USE_BMESH_HOLES - return bm_loop_reverse_loop(bm, f, f->loops.first, cd_loop_mdisp_offset, use_loop_mdisp_flip); + bm_loop_reverse_loop(bm, f, f->loops.first, cd_loop_mdisp_offset, use_loop_mdisp_flip); #else - return bm_loop_reverse_loop(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); + bm_loop_reverse_loop(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); #endif } diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index fb5702bc574..f72e9d7b198 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -75,7 +75,7 @@ void bmesh_vert_separate( BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len, const bool copy_select); -bool bmesh_loop_reverse( +void bmesh_loop_reverse( BMesh *bm, BMFace *f, const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip); |