diff options
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_polygon.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_polygon.c | 460 |
1 files changed, 288 insertions, 172 deletions
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index b0eddf73960..62b29e61d08 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -38,10 +38,13 @@ #include "BLI_memarena.h" #include "BLI_polyfill2d.h" #include "BLI_polyfill2d_beautify.h" +#include "BLI_linklist.h" #include "bmesh.h" #include "bmesh_tools.h" +#include "BKE_customdata.h" + #include "intern/bmesh_private.h" /** @@ -103,7 +106,7 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3]) * but takes an array of vertex locations. */ static float bm_face_calc_poly_normal_vertex_cos( - BMFace *f, float r_no[3], + const BMFace *f, float r_no[3], float const (*vertexCos)[3]) { BMLoop *l_first = BM_FACE_FIRST_LOOP(f); @@ -129,15 +132,15 @@ static float bm_face_calc_poly_normal_vertex_cos( * \brief COMPUTE POLY CENTER (BMFace) */ static void bm_face_calc_poly_center_mean_vertex_cos( - BMFace *f, float r_cent[3], + const BMFace *f, float r_cent[3], float const (*vertexCos)[3]) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter = l_first; + const BMLoop *l_first, *l_iter; zero_v3(r_cent); /* Newell's Method */ + l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { add_v3_v3(r_cent, vertexCos[BM_elem_index_get(l_iter->v)]); } while ((l_iter = l_iter->next) != l_first); @@ -147,10 +150,14 @@ static void bm_face_calc_poly_center_mean_vertex_cos( /** * For tools that insist on using triangles, ideally we would cache this data. * - * \param r_loops Store face loop pointers, (f->len) - * \param r_index Store triangle triples, indices into \a r_loops, ((f->len - 2) * 3) + * \param use_fixed_quad: When true, always split quad along (0 -> 2) regardless of concave corners, + * (as done in #BM_mesh_calc_tessellation). + * \param r_loops: Store face loop pointers, (f->len) + * \param r_index: Store triangle triples, indices into \a r_loops, `((f->len - 2) * 3)` */ -void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int (*r_index)[3]) +void BM_face_calc_tessellation( + const BMFace *f, const bool use_fixed_quad, + BMLoop **r_loops, unsigned int (*r_index)[3]) { BMLoop *l_first = BM_FACE_FIRST_LOOP(f); BMLoop *l_iter; @@ -164,7 +171,7 @@ void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int ( r_index[0][1] = 1; r_index[0][2] = 2; } - else if (f->len == 4) { + else if (f->len == 4 && use_fixed_quad) { *r_loops++ = (l_iter = l_first); *r_loops++ = (l_iter = l_iter->next); *r_loops++ = (l_iter = l_iter->next); @@ -199,11 +206,51 @@ void BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, unsigned int ( } /** + * Return a point inside the face. + */ +void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]) +{ + const BMLoop *l_tri[3]; + + if (f->len == 3) { + const BMLoop *l = BM_FACE_FIRST_LOOP(f); + ARRAY_SET_ITEMS(l_tri, l, l->next, l->prev); + } + else { + /* tessellation here seems overkill when in many cases this will be the center, + * but without this we can't be sure the point is inside a concave face. */ + const int tottri = f->len - 2; + BMLoop **loops = BLI_array_alloca(loops, f->len); + unsigned int (*index)[3] = BLI_array_alloca(index, tottri); + int j; + int j_best = 0; /* use as fallback when unset */ + float area_best = -1.0f; + + BM_face_calc_tessellation(f, false, loops, index); + + for (j = 0; j < tottri; j++) { + const float *p1 = loops[index[j][0]]->v->co; + const float *p2 = loops[index[j][1]]->v->co; + const float *p3 = loops[index[j][2]]->v->co; + const float area = area_squared_tri_v3(p1, p2, p3); + if (area > area_best) { + j_best = j; + area_best = area; + } + } + + ARRAY_SET_ITEMS(l_tri, loops[index[j_best][0]], loops[index[j_best][1]], loops[index[j_best][2]]); + } + + mid_v3_v3v3v3(r_co, l_tri[0]->v->co, l_tri[1]->v->co, l_tri[2]->v->co); +} + +/** * get the area of the face */ -float BM_face_calc_area(BMFace *f) +float BM_face_calc_area(const BMFace *f) { - BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; float (*verts)[3] = BLI_array_alloca(verts, f->len); float area; unsigned int i = 0; @@ -226,9 +273,9 @@ float BM_face_calc_area(BMFace *f) /** * compute the perimeter of an ngon */ -float BM_face_calc_perimeter(BMFace *f) +float BM_face_calc_perimeter(const BMFace *f) { - BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; float perimeter = 0.0f; l_iter = l_first = BM_FACE_FIRST_LOOP(f); @@ -262,12 +309,12 @@ void BM_vert_tri_calc_plane(BMVert *verts[3], float r_plane[3]) * Compute a meaningful direction along the face (use for manipulator axis). * \note result isnt normalized. */ -void BM_face_calc_plane(BMFace *f, float r_plane[3]) +void BM_face_calc_plane(const BMFace *f, float r_plane[3]) { if (f->len == 3) { BMVert *verts[3]; - BM_face_as_array_vert_tri(f, verts); + BM_face_as_array_vert_tri((BMFace *)f, verts); BM_vert_tri_calc_plane(verts, r_plane); } @@ -276,7 +323,7 @@ void BM_face_calc_plane(BMFace *f, float r_plane[3]) float vec[3], vec_a[3], vec_b[3]; // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4); - BM_face_as_array_vert_quad(f, verts); + BM_face_as_array_vert_quad((BMFace *)f, verts); sub_v3_v3v3(vec_a, verts[3]->co, verts[2]->co); sub_v3_v3v3(vec_b, verts[0]->co, verts[1]->co); @@ -291,7 +338,7 @@ void BM_face_calc_plane(BMFace *f, float r_plane[3]) } } else { - BMLoop *l_long = BM_face_find_longest_loop(f); + const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); sub_v3_v3v3(r_plane, l_long->v->co, l_long->next->v->co); } @@ -302,10 +349,9 @@ void BM_face_calc_plane(BMFace *f, float r_plane[3]) /** * computes center of face in 3d. uses center of bounding box. */ -void BM_face_calc_center_bounds(BMFace *f, float r_cent[3]) +void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) { - BMLoop *l_iter; - BMLoop *l_first; + const BMLoop *l_iter, *l_first; float min[3], max[3]; INIT_MINMAX(min, max); @@ -321,9 +367,9 @@ void BM_face_calc_center_bounds(BMFace *f, float r_cent[3]) /** * computes the center of a face, using the mean average */ -void BM_face_calc_center_mean(BMFace *f, float r_cent[3]) +void BM_face_calc_center_mean(const BMFace *f, float r_cent[3]) { - BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; zero_v3(r_cent); @@ -338,10 +384,10 @@ void BM_face_calc_center_mean(BMFace *f, float r_cent[3]) * computes the center of a face, using the mean average * weighted by edge length */ -void BM_face_calc_center_mean_weighted(BMFace *f, float r_cent[3]) +void BM_face_calc_center_mean_weighted(const BMFace *f, float r_cent[3]) { - BMLoop *l_iter; - BMLoop *l_first; + const BMLoop *l_iter; + const BMLoop *l_first; float totw = 0.0f; float w_prev; @@ -422,32 +468,42 @@ void BM_edge_normals_update(BMEdge *e) BM_vert_normal_update(e->v2); } -bool BM_vert_normal_update_ex(BMVert *v, const char hflag, float r_no[3]) +static void bm_loop_normal_accum(const BMLoop *l, float no[3]) { - /* TODO, we can normalize each edge only once, then compare with previous edge */ - - BMIter liter; - BMLoop *l; - int len = 0; + float vec1[3], vec2[3], fac; - zero_v3(r_no); + /* Same calculation used in BM_mesh_normals_update */ + sub_v3_v3v3(vec1, l->v->co, l->prev->v->co); + sub_v3_v3v3(vec2, l->next->v->co, l->v->co); + normalize_v3(vec1); + normalize_v3(vec2); - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - if (BM_elem_flag_test(l->f, hflag)) { - float vec1[3], vec2[3], fac; + fac = saacos(-dot_v3v3(vec1, vec2)); - /* Same calculation used in BM_mesh_normals_update */ - sub_v3_v3v3(vec1, l->v->co, l->prev->v->co); - sub_v3_v3v3(vec2, l->next->v->co, l->v->co); - normalize_v3(vec1); - normalize_v3(vec2); + madd_v3_v3fl(no, l->f->no, fac); +} - fac = saacos(-dot_v3v3(vec1, vec2)); +bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]) +{ + int len = 0; - madd_v3_v3fl(r_no, l->f->no, fac); + zero_v3(r_no); - len++; - } + if (v->e) { + const BMEdge *e = v->e; + do { + if (e->l) { + const BMLoop *l = e->l; + do { + if (l->v == v) { + if (BM_elem_flag_test(l->f, hflag)) { + bm_loop_normal_accum(l, r_no); + len++; + } + } + } while ((l = l->radial_next) != e->l); + } + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); } if (len) { @@ -459,33 +515,56 @@ bool BM_vert_normal_update_ex(BMVert *v, const char hflag, float r_no[3]) } } -/** - * update a vert normal (but not the faces incident on it) - */ -void BM_vert_normal_update(BMVert *v) +bool BM_vert_calc_normal(const BMVert *v, float r_no[3]) { - /* TODO, we can normalize each edge only once, then compare with previous edge */ - - BMIter liter; - BMLoop *l; int len = 0; - zero_v3(v->no); + zero_v3(r_no); - BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - float vec1[3], vec2[3], fac; + if (v->e) { + const BMEdge *e = v->e; + do { + if (e->l) { + const BMLoop *l = e->l; + do { + if (l->v == v) { + bm_loop_normal_accum(l, r_no); + len++; + } + } while ((l = l->radial_next) != e->l); + } + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); + } - /* Same calculation used in BM_mesh_normals_update */ - sub_v3_v3v3(vec1, l->v->co, l->prev->v->co); - sub_v3_v3v3(vec2, l->next->v->co, l->v->co); - normalize_v3(vec1); - normalize_v3(vec2); + if (len) { + normalize_v3(r_no); + return true; + } + else { + return false; + } +} - fac = saacos(-dot_v3v3(vec1, vec2)); +void BM_vert_normal_update_all(BMVert *v) +{ + int len = 0; - madd_v3_v3fl(v->no, l->f->no, fac); + zero_v3(v->no); - len++; + if (v->e) { + const BMEdge *e = v->e; + do { + if (e->l) { + const BMLoop *l = e->l; + do { + if (l->v == v) { + BM_face_normal_update(l->f); + bm_loop_normal_accum(l, v->no); + len++; + } + } while ((l = l->radial_next) != e->l); + } + } while ((e = bmesh_disk_edge_next(e, v)) != v->e); } if (len) { @@ -493,16 +572,12 @@ void BM_vert_normal_update(BMVert *v) } } -void BM_vert_normal_update_all(BMVert *v) +/** + * update a vert normal (but not the faces incident on it) + */ +void BM_vert_normal_update(BMVert *v) { - BMIter iter; - BMFace *f; - - BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { - BM_face_normal_update(f); - } - - BM_vert_normal_update(v); + BM_vert_calc_normal(v, v->no); } /** @@ -551,7 +626,7 @@ void BM_face_normal_update(BMFace *f) /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ float BM_face_calc_normal_vcos( - BMesh *bm, BMFace *f, float r_no[3], + const BMesh *bm, const BMFace *f, float r_no[3], float const (*vertexCos)[3]) { BMLoop *l; @@ -589,13 +664,13 @@ float BM_face_calc_normal_vcos( /** * Calculates the face subset normal. */ -float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) +float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) { const float *v_prev, *v_curr; /* Newell's Method */ - BMLoop *l_iter = l_first; - BMLoop *l_term = l_last->next; + const BMLoop *l_iter = l_first; + const BMLoop *l_term = l_last->next; zero_v3(r_no); @@ -611,7 +686,7 @@ float BM_face_calc_normal_subset(BMLoop *l_first, BMLoop *l_last, float r_no[3]) /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ void BM_face_calc_center_mean_vcos( - BMesh *bm, BMFace *f, float r_cent[3], + const BMesh *bm, const BMFace *f, float r_cent[3], float const (*vertexCos)[3]) { /* must have valid index data */ @@ -627,12 +702,20 @@ void BM_face_calc_center_mean_vcos( * Reverses the winding of a face. * \note This updates the calculated normal. */ -void BM_face_normal_flip(BMesh *bm, BMFace *f) +void BM_face_normal_flip_ex( + BMesh *bm, BMFace *f, + const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) { - bmesh_loop_reverse(bm, f); + bmesh_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); negate_v3(f->no); } +void BM_face_normal_flip(BMesh *bm, BMFace *f) +{ + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true); +} + /* detects if two line segments cross each other (intersects). * note, there could be more winding cases then there needs to be. */ static bool line_crosses_v2f(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) @@ -704,7 +787,7 @@ static bool line_crosses_v2f(const float v1[2], const float v2[2], const float v * instead of projecting co directly into f's orientation space, * so there might be accuracy issues. */ -bool BM_face_point_inside_test(BMFace *f, const float co[3]) +bool BM_face_point_inside_test(const BMFace *f, const float co[3]) { float axis_mat[3][3]; float (*projverts)[2] = BLI_array_alloca(projverts, f->len); @@ -713,8 +796,7 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3]) BMLoop *l_iter; int i; - if (is_zero_v3(f->no)) - BM_face_normal_update(f); + BLI_assert(BM_face_is_normal_valid(f)); axis_dominant_v3_to_m3(axis_mat, f->no); @@ -738,6 +820,12 @@ bool BM_face_point_inside_test(BMFace *f, const float co[3]) * with a length equal to (f->len - 3). It will be filled with the new * triangles (not including the original triangle). * + * \param r_faces_double: When newly created faces are duplicates of existing faces, they're added to this list. + * Caller must handle de-duplication. + * This is done because its possible _all_ faces exist already, + * and in that case we would have to remove all faces including the one passed, + * which causes complications adding/removing faces while looking over them. + * * \note The number of faces is _almost_ always (f->len - 3), * However there may be faces that already occupying the * triangles we would make, so the caller must check \a r_faces_new_tot. @@ -750,6 +838,7 @@ void BM_face_triangulate( int *r_faces_new_tot, BMEdge **r_edges_new, int *r_edges_new_tot, + LinkNode **r_faces_double, const int quad_method, const int ngon_method, const bool use_tag, @@ -758,125 +847,132 @@ void BM_face_triangulate( /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ struct Heap *pf_heap, struct EdgeHash *pf_ehash) { - BMLoop *l_iter, *l_first, *l_new; + const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS); + const bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY); + BMLoop *l_first, *l_new; BMFace *f_new; int nf_i = 0; int ne_i = 0; - bool use_beauty = (ngon_method == MOD_TRIANGULATE_NGON_BEAUTY); BLI_assert(BM_face_is_normal_valid(f)); /* ensure both are valid or NULL */ BLI_assert((r_faces_new == NULL) == (r_faces_new_tot == NULL)); - if (f->len == 4) { - BMLoop *l_v1, *l_v2; - l_first = BM_FACE_FIRST_LOOP(f); + BLI_assert(f->len > 3); - switch (quad_method) { - case MOD_TRIANGULATE_QUAD_FIXED: - { - l_v1 = l_first; - l_v2 = l_first->next->next; - break; - } - case MOD_TRIANGULATE_QUAD_ALTERNATE: - { - l_v1 = l_first->next; - l_v2 = l_first->prev; - break; - } - case MOD_TRIANGULATE_QUAD_SHORTEDGE: - case MOD_TRIANGULATE_QUAD_BEAUTY: - default: - { - BMLoop *l_v3, *l_v4; - bool split_24; - - l_v1 = l_first->next; - l_v2 = l_first->next->next; - l_v3 = l_first->prev; - l_v4 = l_first; - - if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) { - float d1, d2; - d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co); - d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co); - split_24 = ((d2 - d1) > 0.0f); + { + BMLoop **loops = BLI_array_alloca(loops, f->len); + unsigned int (*tris)[3] = BLI_array_alloca(tris, f->len); + const int totfilltri = f->len - 2; + const int last_tri = f->len - 3; + int i; + /* for mdisps */ + float f_center[3]; + + if (f->len == 4) { + /* even though we're not using BLI_polyfill, fill in 'tris' and 'loops' + * so we can share code to handle face creation afterwards. */ + BMLoop *l_v1, *l_v2; + + l_first = BM_FACE_FIRST_LOOP(f); + + switch (quad_method) { + case MOD_TRIANGULATE_QUAD_FIXED: + { + l_v1 = l_first; + l_v2 = l_first->next->next; + break; } - else { - /* first check if the quad is concave on either diagonal */ - const int flip_flag = is_quad_flip_v3(l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co); - if (UNLIKELY(flip_flag & (1 << 0))) { - split_24 = true; - } - else if (UNLIKELY(flip_flag & (1 << 1))) { - split_24 = false; + case MOD_TRIANGULATE_QUAD_ALTERNATE: + { + l_v1 = l_first->next; + l_v2 = l_first->prev; + break; + } + case MOD_TRIANGULATE_QUAD_SHORTEDGE: + case MOD_TRIANGULATE_QUAD_BEAUTY: + default: + { + BMLoop *l_v3, *l_v4; + bool split_24; + + l_v1 = l_first->next; + l_v2 = l_first->next->next; + l_v3 = l_first->prev; + l_v4 = l_first; + + if (quad_method == MOD_TRIANGULATE_QUAD_SHORTEDGE) { + float d1, d2; + d1 = len_squared_v3v3(l_v4->v->co, l_v2->v->co); + d2 = len_squared_v3v3(l_v1->v->co, l_v3->v->co); + split_24 = ((d2 - d1) > 0.0f); } else { - split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) > 0.0f); + /* first check if the quad is concave on either diagonal */ + const int flip_flag = is_quad_flip_v3(l_v1->v->co, l_v2->v->co, l_v3->v->co, l_v4->v->co); + if (UNLIKELY(flip_flag & (1 << 0))) { + split_24 = true; + } + else if (UNLIKELY(flip_flag & (1 << 1))) { + split_24 = false; + } + else { + split_24 = (BM_verts_calc_rotate_beauty(l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) > 0.0f); + } } - } - /* named confusingly, l_v1 is in fact the second vertex */ - if (split_24) { - l_v1 = l_v4; - //l_v2 = l_v2; - } - else { - //l_v1 = l_v1; - l_v2 = l_v3; + /* named confusingly, l_v1 is in fact the second vertex */ + if (split_24) { + l_v1 = l_v4; + //l_v2 = l_v2; + } + else { + //l_v1 = l_v1; + l_v2 = l_v3; + } + break; } - break; } - } - - f_new = BM_face_split(bm, f, l_v1, l_v2, &l_new, NULL, true); - copy_v3_v3(f_new->no, f->no); - if (use_tag) { - BM_elem_flag_enable(l_new->e, BM_ELEM_TAG); - BM_elem_flag_enable(f_new, BM_ELEM_TAG); - } + loops[0] = l_v1; + loops[1] = l_v1->next; + loops[2] = l_v2; + loops[3] = l_v2->next; - if (r_faces_new) { - r_faces_new[nf_i++] = f_new; - } - if (r_edges_new) { - r_edges_new[ne_i++] = l_new->e; + ARRAY_SET_ITEMS(tris[0], 0, 1, 2); + ARRAY_SET_ITEMS(tris[1], 0, 2, 3); } - } - else if (f->len > 4) { + else { + BMLoop *l_iter; + float axis_mat[3][3]; + float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - BMLoop **loops = BLI_array_alloca(loops, f->len); - unsigned int (*tris)[3] = BLI_array_alloca(tris, f->len); - const int totfilltri = f->len - 2; - const int last_tri = f->len - 3; - int i; + axis_dominant_v3_to_m3_negate(axis_mat, f->no); - axis_dominant_v3_to_m3_negate(axis_mat, f->no); + for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { + loops[i] = l_iter; + mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); + } - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { - loops[i] = l_iter; - mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); - } + BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, 1, tris, + pf_arena); - BLI_polyfill_calc_arena((const float (*)[2])projverts, f->len, 1, tris, - pf_arena); + if (use_beauty) { + BLI_polyfill_beautify( + (const float (*)[2])projverts, f->len, tris, + pf_arena, pf_heap, pf_ehash); + } - if (use_beauty) { - BLI_polyfill_beautify( - (const float (*)[2])projverts, f->len, tris, - pf_arena, pf_heap, pf_ehash); + BLI_memarena_clear(pf_arena); } - BLI_memarena_clear(pf_arena); + if (cd_loop_mdisp_offset != -1) { + BM_face_calc_center_mean(f, f_center); + } /* loop over calculated triangles and create new geometry */ for (i = 0; i < totfilltri; i++) { - /* the order is reverse, otherwise the normal is flipped */ BMLoop *l_tri[3] = { loops[tris[i][0]], loops[tris[i][1]], @@ -892,6 +988,18 @@ void BM_face_triangulate( BLI_assert(v_tri[0] == l_new->v); + /* check for duplicate */ + if (l_new->radial_next != l_new) { + BMLoop *l_iter = l_new->radial_next; + do { + if (UNLIKELY((l_iter->f->len == 3) && (l_new->prev->v == l_iter->prev->v))) { + /* Check the last tri because we swap last f_new with f at the end... */ + BLI_linklist_prepend(r_faces_double, (i != last_tri) ? f_new : f); + break; + } + } while ((l_iter = l_iter->radial_next) != l_new); + } + /* copy CD data */ BM_elem_attrs_copy(bm, bm, l_tri[0], l_new); BM_elem_attrs_copy(bm, bm, l_tri[1], l_new->next); @@ -909,6 +1017,8 @@ void BM_face_triangulate( if (use_tag || r_edges_new) { /* new faces loops */ + BMLoop *l_iter; + l_iter = l_first = l_new; do { BMEdge *e = l_iter->e; @@ -927,6 +1037,12 @@ void BM_face_triangulate( /* note, never disable tag's */ } while ((l_iter = l_iter->next) != l_first); } + + if (cd_loop_mdisp_offset != -1) { + float f_new_center[3]; + BM_face_calc_center_mean(f_new, f_new_center); + BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset); + } } { @@ -1159,12 +1275,12 @@ void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) /** - * \brief BM_bmesh_calc_tessellation get the looptris and its number from a certain bmesh + * \brief BM_mesh_calc_tessellation get the looptris and its number from a certain bmesh * \param looptris * * \note \a looptris Must be pre-allocated to at least the size of given by: poly_to_tri_count */ -void BM_bmesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot) +void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot) { /* use this to avoid locking pthread for _every_ polygon * and calling the fill function */ |