Changeset View
Changeset View
Standalone View
Standalone View
source/blender/bmesh/intern/bmesh_polygon.c
| Show All 31 Lines | |||||
| #include "DNA_modifier_types.h" | #include "DNA_modifier_types.h" | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_alloca.h" | #include "BLI_alloca.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_memarena.h" | #include "BLI_memarena.h" | ||||
| #include "BLI_polyfill2d.h" | #include "BLI_polyfill2d.h" | ||||
| #include "BLI_polyfill2d_beautify.h" | |||||
| #include "bmesh.h" | #include "bmesh.h" | ||||
| #include "bmesh_tools.h" | #include "bmesh_tools.h" | ||||
| #include "intern/bmesh_private.h" | #include "intern/bmesh_private.h" | ||||
| /** | /** | ||||
| * \brief TEST EDGE SIDE and POINT IN TRIANGLE | * \brief TEST EDGE SIDE and POINT IN TRIANGLE | ||||
| ▲ Show 20 Lines • Show All 696 Lines • ▼ Show 20 Lines | |||||
| */ | */ | ||||
| void BM_face_triangulate( | void BM_face_triangulate( | ||||
| BMesh *bm, BMFace *f, | BMesh *bm, BMFace *f, | ||||
| BMFace **r_faces_new, | BMFace **r_faces_new, | ||||
| int *r_faces_new_tot, | int *r_faces_new_tot, | ||||
| const int quad_method, | const int quad_method, | ||||
| const int ngon_method, | const int ngon_method, | ||||
| const bool use_tag, | const bool use_tag, | ||||
| MemArena *pf_arena, | |||||
| MemArena *pf_arena) | /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ | ||||
| struct Heap *pf_heap, struct EdgeHash *pf_ehash) | |||||
| { | { | ||||
| BMLoop *l_iter, *l_first, *l_new; | BMLoop *l_iter, *l_first, *l_new; | ||||
| BMFace *f_new; | BMFace *f_new; | ||||
| int orig_f_len = f->len; | |||||
| int nf_i = 0; | int nf_i = 0; | ||||
| BMEdge **edge_array; | |||||
| int edge_array_len; | |||||
| bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY); | bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY); | ||||
| BLI_assert(BM_face_is_normal_valid(f)); | BLI_assert(BM_face_is_normal_valid(f)); | ||||
| /* ensure both are valid or NULL */ | /* ensure both are valid or NULL */ | ||||
| BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL)); | BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL)); | ||||
| if (f->len == 4) { | if (f->len == 4) { | ||||
| ▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { | ||||
| loops[i] = l_iter; | loops[i] = l_iter; | ||||
| mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); | mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); | ||||
| } | } | ||||
| BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, -1, tris, | BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, -1, tris, | ||||
| pf_arena); | pf_arena); | ||||
| if (use_beauty) { | if (use_beauty) { | ||||
| edge_array = BLI_array_alloca(edge_array, orig_f_len - 3); | BLI_polyfill_beautify( | ||||
| edge_array_len = 0; | (const float (*)[2])projverts, f->len, tris, | ||||
| pf_arena, pf_heap, pf_ehash); | |||||
| } | } | ||||
| /* loop over calculated triangles and create new geometry */ | /* loop over calculated triangles and create new geometry */ | ||||
| for (i = 0; i < totfilltri; i++) { | for (i = 0; i < totfilltri; i++) { | ||||
| /* the order is reverse, otherwise the normal is flipped */ | /* the order is reverse, otherwise the normal is flipped */ | ||||
| BMLoop *l_tri[3] = { | BMLoop *l_tri[3] = { | ||||
| loops[tris[i][2]], | loops[tris[i][2]], | ||||
| loops[tris[i][1]], | loops[tris[i][1]], | ||||
| Show All 20 Lines | for (i = 0; i < totfilltri; i++) { | ||||
| BM_elem_flag_enable(f_new, BM_ELEM_TAG); | BM_elem_flag_enable(f_new, BM_ELEM_TAG); | ||||
| } | } | ||||
| if (r_faces_new) { | if (r_faces_new) { | ||||
| r_faces_new[nf_i++] = f_new; | r_faces_new[nf_i++] = f_new; | ||||
| } | } | ||||
| } | } | ||||
| /* we know any edge that we create and _isnt_ */ | /* we know any edge that we create and _isnt_ */ | ||||
| if (use_beauty || use_tag) { | if (use_tag) { | ||||
| /* new faces loops */ | /* new faces loops */ | ||||
| l_iter = l_first = l_new; | l_iter = l_first = l_new; | ||||
| do { | do { | ||||
| BMEdge *e = l_iter->e; | BMEdge *e = l_iter->e; | ||||
| /* confusing! if its not a boundary now, we know it will be later | /* confusing! if its not a boundary now, we know it will be later | ||||
| * since this will be an edge of one of the new faces which we're in the middle of creating */ | * since this will be an edge of one of the new faces which we're in the middle of creating */ | ||||
| bool is_new_edge = (l_iter == l_iter->radial_next); | bool is_new_edge = (l_iter == l_iter->radial_next); | ||||
| if (is_new_edge) { | if (is_new_edge) { | ||||
| if (use_beauty) { | |||||
| edge_array[edge_array_len] = e; | |||||
| edge_array_len++; | |||||
| } | |||||
| if (use_tag) { | |||||
| BM_elem_flag_enable(e, BM_ELEM_TAG); | BM_elem_flag_enable(e, BM_ELEM_TAG); | ||||
| } | |||||
| } | } | ||||
| /* note, never disable tag's */ | /* note, never disable tag's */ | ||||
| } while ((l_iter = l_iter->next) != l_first); | } while ((l_iter = l_iter->next) != l_first); | ||||
| } | } | ||||
| } | } | ||||
| if ((!use_beauty) || (!r_faces_new)) { | { | ||||
| /* we can't delete the real face, because some of the callers expect it to remain valid. | |||||
| * so swap data and delete the last created tri */ | |||||
| bmesh_face_swap_data(f, f_new); | |||||
| BM_face_kill(bm, f_new); | |||||
| } | |||||
| if (use_beauty) { | |||||
| BLI_assert(edge_array_len <= orig_f_len - 3); | |||||
| BM_mesh_beautify_fill(bm, edge_array, edge_array_len, 0, 0, 0, 0); | |||||
| if (r_faces_new) { | |||||
| /* beautify deletes and creates new faces | |||||
| * we need to re-populate the r_faces_new array | |||||
| * with the new faces | |||||
| */ | |||||
| int i; | |||||
| #define FACE_USED_TEST(f) (BM_elem_index_get(f) == -2) | |||||
| #define FACE_USED_SET(f) BM_elem_index_set(f, -2) | |||||
| nf_i = 0; | |||||
| for (i = 0; i < edge_array_len; i++) { | |||||
| BMFace *f_pair[2]; | |||||
| BMEdge *e = edge_array[i]; | |||||
| int j; | |||||
| #ifndef NDEBUG | |||||
| const bool ok = BM_edge_face_pair(e, &f_pair[0], &f_pair[1]); | |||||
| BLI_assert(ok); | |||||
| #else | |||||
| BM_edge_face_pair(e, &f_pair[0], &f_pair[1]); | |||||
| #endif | |||||
| for (j = 0; j < 2; j++) { | |||||
| if (FACE_USED_TEST(f_pair[j]) == false) { | |||||
| FACE_USED_SET(f_pair[j]); /* set_dirty */ | |||||
| if (nf_i < edge_array_len) { | |||||
| r_faces_new[nf_i++] = f_pair[j]; | |||||
| } | |||||
| else { | |||||
| f_new = f_pair[j]; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| #undef FACE_USED_TEST | |||||
| #undef FACE_USED_SET | |||||
| /* nf_i doesn't include the last face */ | |||||
| BLI_assert(nf_i <= orig_f_len - 3); | |||||
| /* we can't delete the real face, because some of the callers expect it to remain valid. | /* we can't delete the real face, because some of the callers expect it to remain valid. | ||||
| * so swap data and delete the last created tri */ | * so swap data and delete the last created tri */ | ||||
| bmesh_face_swap_data(f, f_new); | bmesh_face_swap_data(f, f_new); | ||||
| BM_face_kill(bm, f_new); | BM_face_kill(bm, f_new); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| bm->elem_index_dirty |= BM_FACE; | bm->elem_index_dirty |= BM_FACE; | ||||
| if (r_faces_new_tot) { | if (r_faces_new_tot) { | ||||
| *r_faces_new_tot = nf_i; | *r_faces_new_tot = nf_i; | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| ▲ Show 20 Lines • Show All 350 Lines • Show Last 20 Lines | |||||