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/intern/bmesh_polygon.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/intern/bmesh_polygon.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_polygon.c | 2349 |
1 files changed, 1166 insertions, 1183 deletions
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 4cc3cf3e4c1..2a734c242ba 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -50,24 +50,24 @@ */ static float bm_face_calc_poly_normal(const BMFace *f, float n[3]) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter = l_first; - const float *v_prev = l_first->prev->v->co; - const float *v_curr = l_first->v->co; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter = l_first; + const float *v_prev = l_first->prev->v->co; + const float *v_curr = l_first->v->co; - zero_v3(n); + zero_v3(n); - /* Newell's Method */ - do { - add_newell_cross_v3_v3v3(n, v_prev, v_curr); + /* Newell's Method */ + do { + add_newell_cross_v3_v3v3(n, v_prev, v_curr); - l_iter = l_iter->next; - v_prev = v_curr; - v_curr = l_iter->v->co; + l_iter = l_iter->next; + v_prev = v_curr; + v_curr = l_iter->v->co; - } while (l_iter != l_first); + } while (l_iter != l_first); - return normalize_v3(n); + return normalize_v3(n); } /** @@ -76,46 +76,46 @@ static float bm_face_calc_poly_normal(const BMFace *f, float n[3]) * Same as #bm_face_calc_poly_normal * but takes an array of vertex locations. */ -static float bm_face_calc_poly_normal_vertex_cos( - const BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +static float bm_face_calc_poly_normal_vertex_cos(const BMFace *f, + float r_no[3], + float const (*vertexCos)[3]) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter = l_first; - const float *v_prev = vertexCos[BM_elem_index_get(l_first->prev->v)]; - const float *v_curr = vertexCos[BM_elem_index_get(l_first->v)]; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter = l_first; + const float *v_prev = vertexCos[BM_elem_index_get(l_first->prev->v)]; + const float *v_curr = vertexCos[BM_elem_index_get(l_first->v)]; - zero_v3(r_no); + zero_v3(r_no); - /* Newell's Method */ - do { - add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); + /* Newell's Method */ + do { + add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); - l_iter = l_iter->next; - v_prev = v_curr; - v_curr = vertexCos[BM_elem_index_get(l_iter->v)]; - } while (l_iter != l_first); + l_iter = l_iter->next; + v_prev = v_curr; + v_curr = vertexCos[BM_elem_index_get(l_iter->v)]; + } while (l_iter != l_first); - return normalize_v3(r_no); + return normalize_v3(r_no); } /** * \brief COMPUTE POLY CENTER (BMFace) */ -static void bm_face_calc_poly_center_median_vertex_cos( - const BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +static void bm_face_calc_poly_center_median_vertex_cos(const BMFace *f, + float r_cent[3], + float const (*vertexCos)[3]) { - const BMLoop *l_first, *l_iter; + const BMLoop *l_first, *l_iter; - zero_v3(r_cent); + 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); - mul_v3_fl(r_cent, 1.0f / f->len); + /* 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); + mul_v3_fl(r_cent, 1.0f / f->len); } /** @@ -126,54 +126,55 @@ static void bm_face_calc_poly_center_median_vertex_cos( * \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, const bool use_fixed_quad, - BMLoop **r_loops, uint (*r_index)[3]) +void BM_face_calc_tessellation(const BMFace *f, + const bool use_fixed_quad, + BMLoop **r_loops, + uint (*r_index)[3]) { - BMLoop *l_first = BM_FACE_FIRST_LOOP(f); - BMLoop *l_iter; - - if (f->len == 3) { - *r_loops++ = (l_iter = l_first); - *r_loops++ = (l_iter = l_iter->next); - *r_loops++ = ( l_iter->next); - - r_index[0][0] = 0; - r_index[0][1] = 1; - r_index[0][2] = 2; - } - 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); - *r_loops++ = ( l_iter->next); - - r_index[0][0] = 0; - r_index[0][1] = 1; - r_index[0][2] = 2; - - r_index[1][0] = 0; - r_index[1][1] = 2; - r_index[1][2] = 3; - } - else { - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - int j; - - axis_dominant_v3_to_m3(axis_mat, f->no); - - j = 0; - l_iter = l_first; - do { - mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); - r_loops[j] = l_iter; - j++; - } while ((l_iter = l_iter->next) != l_first); - - /* complete the loop */ - BLI_polyfill_calc(projverts, f->len, -1, r_index); - } + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + + if (f->len == 3) { + *r_loops++ = (l_iter = l_first); + *r_loops++ = (l_iter = l_iter->next); + *r_loops++ = (l_iter->next); + + r_index[0][0] = 0; + r_index[0][1] = 1; + r_index[0][2] = 2; + } + 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); + *r_loops++ = (l_iter->next); + + r_index[0][0] = 0; + r_index[0][1] = 1; + r_index[0][2] = 2; + + r_index[1][0] = 0; + r_index[1][1] = 2; + r_index[1][2] = 3; + } + else { + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); + int j; + + axis_dominant_v3_to_m3(axis_mat, f->no); + + j = 0; + l_iter = l_first; + do { + mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); + r_loops[j] = l_iter; + j++; + } while ((l_iter = l_iter->next) != l_first); + + /* complete the loop */ + BLI_polyfill_calc(projverts, f->len, -1, r_index); + } } /** @@ -181,39 +182,40 @@ void BM_face_calc_tessellation( */ 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); - uint (*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); + 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); + uint(*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); } /** @@ -221,16 +223,16 @@ void BM_face_calc_point_in_face(const BMFace *f, float r_co[3]) */ float BM_face_calc_area(const BMFace *f) { - /* inline 'area_poly_v3' logic, avoid creating a temp array */ - const BMLoop *l_iter, *l_first; - float n[3]; - - zero_v3(n); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co); - } while ((l_iter = l_iter->next) != l_first); - return len_v3(n) * 0.5f; + /* inline 'area_poly_v3' logic, avoid creating a temp array */ + const BMLoop *l_iter, *l_first; + float n[3]; + + zero_v3(n); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_newell_cross_v3_v3v3(n, l_iter->v->co, l_iter->next->v->co); + } while ((l_iter = l_iter->next) != l_first); + return len_v3(n) * 0.5f; } /** @@ -238,21 +240,21 @@ float BM_face_calc_area(const BMFace *f) */ float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) { - /* inline 'area_poly_v3' logic, avoid creating a temp array */ - const BMLoop *l_iter, *l_first; - float co[3]; - float n[3]; - - zero_v3(n); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - mul_v3_m3v3(co, mat3, l_iter->v->co); - do { - float co_next[3]; - mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); - add_newell_cross_v3_v3v3(n, co, co_next); - copy_v3_v3(co, co_next); - } while ((l_iter = l_iter->next) != l_first); - return len_v3(n) * 0.5f; + /* inline 'area_poly_v3' logic, avoid creating a temp array */ + const BMLoop *l_iter, *l_first; + float co[3]; + float n[3]; + + zero_v3(n); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + mul_v3_m3v3(co, mat3, l_iter->v->co); + do { + float co_next[3]; + mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); + add_newell_cross_v3_v3v3(n, co, co_next); + copy_v3_v3(co, co_next); + } while ((l_iter = l_iter->next) != l_first); + return len_v3(n) * 0.5f; } /** @@ -260,18 +262,18 @@ float BM_face_calc_area_with_mat3(const BMFace *f, const float mat3[3][3]) */ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) { - /* inline 'area_poly_v2' logic, avoid creating a temp array */ - const BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - /* The Trapezium Area Rule */ - float cross = 0.0f; - do { - const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); - const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset); - cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]); - } while ((l_iter = l_iter->next) != l_first); - return fabsf(cross * 0.5f); + /* inline 'area_poly_v2' logic, avoid creating a temp array */ + const BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + /* The Trapezium Area Rule */ + float cross = 0.0f; + do { + const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset); + const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset); + cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]); + } while ((l_iter = l_iter->next) != l_first); + return fabsf(cross * 0.5f); } /** @@ -279,15 +281,15 @@ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset) */ float BM_face_calc_perimeter(const BMFace *f) { - const BMLoop *l_iter, *l_first; - float perimeter = 0.0f; + const BMLoop *l_iter, *l_first; + float perimeter = 0.0f; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - perimeter += len_v3v3(l_iter->v->co, l_iter->next->v->co); - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + perimeter += len_v3v3(l_iter->v->co, l_iter->next->v->co); + } while ((l_iter = l_iter->next) != l_first); - return perimeter; + return perimeter; } /** @@ -295,20 +297,20 @@ float BM_face_calc_perimeter(const BMFace *f) */ float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3]) { - const BMLoop *l_iter, *l_first; - float co[3]; - float perimeter = 0.0f; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - mul_v3_m3v3(co, mat3, l_iter->v->co); - do { - float co_next[3]; - mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); - perimeter += len_v3v3(co, co_next); - copy_v3_v3(co, co_next); - } while ((l_iter = l_iter->next) != l_first); - - return perimeter; + const BMLoop *l_iter, *l_first; + float co[3]; + float perimeter = 0.0f; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + mul_v3_m3v3(co, mat3, l_iter->v->co); + do { + float co_next[3]; + mul_v3_m3v3(co_next, mat3, l_iter->next->v->co); + perimeter += len_v3v3(co, co_next); + copy_v3_v3(co, co_next); + } while ((l_iter = l_iter->next) != l_first); + + return perimeter; } /** @@ -318,42 +320,39 @@ float BM_face_calc_perimeter_with_mat3(const BMFace *f, const float mat3[3][3]) */ static int bm_vert_tri_find_unique_edge(BMVert *verts[3]) { - /* find the most 'unique' loop, (greatest difference to others) */ + /* find the most 'unique' loop, (greatest difference to others) */ #if 1 - /* optimized version that avoids sqrt */ - float difs[3]; - for (int i_prev = 1, i_curr = 2, i_next = 0; - i_next < 3; - i_prev = i_curr, i_curr = i_next++) - { - const float *co = verts[i_curr]->co; - const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co}; - float proj_dir[3]; - mid_v3_v3v3(proj_dir, co_other[0], co_other[1]); - sub_v3_v3(proj_dir, co); - - float proj_pair[2][3]; - project_v3_v3v3(proj_pair[0], co_other[0], proj_dir); - project_v3_v3v3(proj_pair[1], co_other[1], proj_dir); - difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]); - } + /* optimized version that avoids sqrt */ + float difs[3]; + for (int i_prev = 1, i_curr = 2, i_next = 0; i_next < 3; i_prev = i_curr, i_curr = i_next++) { + const float *co = verts[i_curr]->co; + const float *co_other[2] = {verts[i_prev]->co, verts[i_next]->co}; + float proj_dir[3]; + mid_v3_v3v3(proj_dir, co_other[0], co_other[1]); + sub_v3_v3(proj_dir, co); + + float proj_pair[2][3]; + project_v3_v3v3(proj_pair[0], co_other[0], proj_dir); + project_v3_v3v3(proj_pair[1], co_other[1], proj_dir); + difs[i_next] = len_squared_v3v3(proj_pair[0], proj_pair[1]); + } #else - const float lens[3] = { - len_v3v3(verts[0]->co, verts[1]->co), - len_v3v3(verts[1]->co, verts[2]->co), - len_v3v3(verts[2]->co, verts[0]->co), - }; - const float difs[3] = { - fabsf(lens[1] - lens[2]), - fabsf(lens[2] - lens[0]), - fabsf(lens[0] - lens[1]), - }; + const float lens[3] = { + len_v3v3(verts[0]->co, verts[1]->co), + len_v3v3(verts[1]->co, verts[2]->co), + len_v3v3(verts[2]->co, verts[0]->co), + }; + const float difs[3] = { + fabsf(lens[1] - lens[2]), + fabsf(lens[2] - lens[0]), + fabsf(lens[0] - lens[1]), + }; #endif - int order[3] = {0, 1, 2}; - axis_sort_v3(difs, order); + int order[3] = {0, 1, 2}; + axis_sort_v3(difs, order); - return order[0]; + return order[0]; } /** @@ -366,11 +365,11 @@ static int bm_vert_tri_find_unique_edge(BMVert *verts[3]) */ void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3]) { - const int index = bm_vert_tri_find_unique_edge(verts); + const int index = bm_vert_tri_find_unique_edge(verts); - sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co); + sub_v3_v3v3(r_tangent, verts[index]->co, verts[(index + 1) % 3]->co); - normalize_v3(r_tangent); + normalize_v3(r_tangent); } /** @@ -383,29 +382,28 @@ void BM_vert_tri_calc_tangent_edge(BMVert *verts[3], float r_tangent[3]) */ void BM_vert_tri_calc_tangent_edge_pair(BMVert *verts[3], float r_tangent[3]) { - const int index = bm_vert_tri_find_unique_edge(verts); + const int index = bm_vert_tri_find_unique_edge(verts); - const float *v_a = verts[index]->co; - const float *v_b = verts[(index + 1) % 3]->co; - const float *v_other = verts[(index + 2) % 3]->co; + const float *v_a = verts[index]->co; + const float *v_b = verts[(index + 1) % 3]->co; + const float *v_other = verts[(index + 2) % 3]->co; - mid_v3_v3v3(r_tangent, v_a, v_b); - sub_v3_v3v3(r_tangent, v_other, r_tangent); + mid_v3_v3v3(r_tangent, v_a, v_b); + sub_v3_v3v3(r_tangent, v_other, r_tangent); - normalize_v3(r_tangent); + normalize_v3(r_tangent); } /** * Compute the tangent of the face, using the longest edge. */ -void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3]) { - const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); + const BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); - sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co); - - normalize_v3(r_tangent); + sub_v3_v3v3(r_tangent, l_long->v->co, l_long->next->v->co); + normalize_v3(r_tangent); } /** @@ -413,64 +411,64 @@ void BM_face_calc_tangent_edge(const BMFace *f, float r_tangent[3]) * * \param r_tangent: Calculated unit length tangent (return value). */ -void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3]) { - if (f->len == 3) { - BMVert *verts[3]; - - BM_face_as_array_vert_tri((BMFace *)f, verts); - - BM_vert_tri_calc_tangent_edge_pair(verts, r_tangent); - } - else if (f->len == 4) { - /* Use longest edge pair */ - BMVert *verts[4]; - float vec[3], vec_a[3], vec_b[3]; - - 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); - add_v3_v3v3(r_tangent, vec_a, vec_b); - - sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co); - sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co); - add_v3_v3v3(vec, vec_a, vec_b); - /* use the longest edge length */ - if (len_squared_v3(r_tangent) < len_squared_v3(vec)) { - copy_v3_v3(r_tangent, vec); - } - } - else { - /* For ngons use two longest disconnected edges */ - BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); - BMLoop *l_long_other = NULL; - - float len_max_sq = 0.0f; - float vec_a[3], vec_b[3]; - - BMLoop *l_iter = l_long->prev->prev; - BMLoop *l_last = l_long->next; - - do { - const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); - if (len_sq >= len_max_sq) { - l_long_other = l_iter; - len_max_sq = len_sq; - } - } while ((l_iter = l_iter->prev) != l_last); - - sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co); - sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co); - add_v3_v3v3(r_tangent, vec_a, vec_b); - - /* Edges may not be opposite side of the ngon, - * this could cause problems for ngons with multiple-aligned edges of the same length. - * Fallback to longest edge. */ - if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) { - normalize_v3_v3(r_tangent, vec_a); - } - } + if (f->len == 3) { + BMVert *verts[3]; + + BM_face_as_array_vert_tri((BMFace *)f, verts); + + BM_vert_tri_calc_tangent_edge_pair(verts, r_tangent); + } + else if (f->len == 4) { + /* Use longest edge pair */ + BMVert *verts[4]; + float vec[3], vec_a[3], vec_b[3]; + + 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); + add_v3_v3v3(r_tangent, vec_a, vec_b); + + sub_v3_v3v3(vec_a, verts[0]->co, verts[3]->co); + sub_v3_v3v3(vec_b, verts[1]->co, verts[2]->co); + add_v3_v3v3(vec, vec_a, vec_b); + /* use the longest edge length */ + if (len_squared_v3(r_tangent) < len_squared_v3(vec)) { + copy_v3_v3(r_tangent, vec); + } + } + else { + /* For ngons use two longest disconnected edges */ + BMLoop *l_long = BM_face_find_longest_loop((BMFace *)f); + BMLoop *l_long_other = NULL; + + float len_max_sq = 0.0f; + float vec_a[3], vec_b[3]; + + BMLoop *l_iter = l_long->prev->prev; + BMLoop *l_last = l_long->next; + + do { + const float len_sq = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); + if (len_sq >= len_max_sq) { + l_long_other = l_iter; + len_max_sq = len_sq; + } + } while ((l_iter = l_iter->prev) != l_last); + + sub_v3_v3v3(vec_a, l_long->next->v->co, l_long->v->co); + sub_v3_v3v3(vec_b, l_long_other->v->co, l_long_other->next->v->co); + add_v3_v3v3(r_tangent, vec_a, vec_b); + + /* Edges may not be opposite side of the ngon, + * this could cause problems for ngons with multiple-aligned edges of the same length. + * Fallback to longest edge. */ + if (UNLIKELY(normalize_v3(r_tangent) == 0.0f)) { + normalize_v3_v3(r_tangent, vec_a); + } + } } /** @@ -478,35 +476,36 @@ void BM_face_calc_tangent_edge_pair(const BMFace *f, float r_tangent[3]) * * \param r_tangent: Calculated unit length tangent (return value). */ -void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - - /* incase of degenerate faces */ - zero_v3(r_tangent); - - /* warning: O(n^2) loop here, take care! */ - float dist_max_sq = 0.0f; - do { - BMLoop *l_iter_other = l_iter->next; - BMLoop *l_iter_last = l_iter->prev; - do { - BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co)); - float co_other[3], vec[3]; - closest_to_line_segment_v3(co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co); - sub_v3_v3v3(vec, l_iter->v->co, co_other); - - const float dist_sq = len_squared_v3(vec); - if (dist_sq > dist_max_sq) { - dist_max_sq = dist_sq; - copy_v3_v3(r_tangent, vec); - } - } while ((l_iter_other = l_iter_other->next) != l_iter_last); - } while ((l_iter = l_iter->next) != l_first); - - normalize_v3(r_tangent); + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + + /* incase of degenerate faces */ + zero_v3(r_tangent); + + /* warning: O(n^2) loop here, take care! */ + float dist_max_sq = 0.0f; + do { + BMLoop *l_iter_other = l_iter->next; + BMLoop *l_iter_last = l_iter->prev; + do { + BLI_assert(!ELEM(l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co)); + float co_other[3], vec[3]; + closest_to_line_segment_v3( + co_other, l_iter->v->co, l_iter_other->v->co, l_iter_other->next->v->co); + sub_v3_v3v3(vec, l_iter->v->co, co_other); + + const float dist_sq = len_squared_v3(vec); + if (dist_sq > dist_max_sq) { + dist_max_sq = dist_sq; + copy_v3_v3(r_tangent, vec); + } + } while ((l_iter_other = l_iter_other->next) != l_iter_last); + } while ((l_iter = l_iter->next) != l_first); + + normalize_v3(r_tangent); } /** @@ -514,32 +513,32 @@ void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3]) * * \note The logic is almost identical to #BM_face_calc_tangent_edge_diagonal */ -void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) +void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) { - BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - - /* incase of degenerate faces */ - zero_v3(r_tangent); - - /* warning: O(n^2) loop here, take care! */ - float dist_max_sq = 0.0f; - do { - BMLoop *l_iter_other = l_iter->next; - do { - float vec[3]; - sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co); - - const float dist_sq = len_squared_v3(vec); - if (dist_sq > dist_max_sq) { - dist_max_sq = dist_sq; - copy_v3_v3(r_tangent, vec); - } - } while ((l_iter_other = l_iter_other->next) != l_iter); - } while ((l_iter = l_iter->next) != l_first); - - normalize_v3(r_tangent); + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + + /* incase of degenerate faces */ + zero_v3(r_tangent); + + /* warning: O(n^2) loop here, take care! */ + float dist_max_sq = 0.0f; + do { + BMLoop *l_iter_other = l_iter->next; + do { + float vec[3]; + sub_v3_v3v3(vec, l_iter->v->co, l_iter_other->v->co); + + const float dist_sq = len_squared_v3(vec); + if (dist_sq > dist_max_sq) { + dist_max_sq = dist_sq; + copy_v3_v3(r_tangent, vec); + } + } while ((l_iter_other = l_iter_other->next) != l_iter); + } while ((l_iter = l_iter->next) != l_first); + + normalize_v3(r_tangent); } /** @@ -549,20 +548,20 @@ void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3]) */ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3]) { - if (f->len == 3) { - /* most 'unique' edge of a triangle */ - BMVert *verts[3]; - BM_face_as_array_vert_tri((BMFace *)f, verts); - BM_vert_tri_calc_tangent_edge(verts, r_tangent); - } - else if (f->len == 4) { - /* longest edge pair of a quad */ - BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent); - } - else { - /* longest edge of an ngon */ - BM_face_calc_tangent_edge((BMFace *)f, r_tangent); - } + if (f->len == 3) { + /* most 'unique' edge of a triangle */ + BMVert *verts[3]; + BM_face_as_array_vert_tri((BMFace *)f, verts); + BM_vert_tri_calc_tangent_edge(verts, r_tangent); + } + else if (f->len == 4) { + /* longest edge pair of a quad */ + BM_face_calc_tangent_edge_pair((BMFace *)f, r_tangent); + } + else { + /* longest edge of an ngon */ + BM_face_calc_tangent_edge((BMFace *)f, r_tangent); + } } /** @@ -570,11 +569,11 @@ void BM_face_calc_tangent_auto(const BMFace *f, float r_tangent[3]) */ void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]) { - const BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - minmax_v3v3_v3(min, max, l_iter->v->co); - } while ((l_iter = l_iter->next) != l_first); + const BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + minmax_v3v3_v3(min, max, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); } /** @@ -582,17 +581,17 @@ void BM_face_calc_bounds_expand(const BMFace *f, float min[3], float max[3]) */ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) { - const BMLoop *l_iter, *l_first; - float min[3], max[3]; + const BMLoop *l_iter, *l_first; + float min[3], max[3]; - INIT_MINMAX(min, max); + INIT_MINMAX(min, max); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - minmax_v3v3_v3(min, max, l_iter->v->co); - } while ((l_iter = l_iter->next) != l_first); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + minmax_v3v3_v3(min, max, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); - mid_v3_v3v3(r_cent, min, max); + mid_v3_v3v3(r_cent, min, max); } /** @@ -600,15 +599,15 @@ void BM_face_calc_center_bounds(const BMFace *f, float r_cent[3]) */ void BM_face_calc_center_median(const BMFace *f, float r_cent[3]) { - const BMLoop *l_iter, *l_first; + const BMLoop *l_iter, *l_first; - zero_v3(r_cent); + zero_v3(r_cent); - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - add_v3_v3(r_cent, l_iter->v->co); - } while ((l_iter = l_iter->next) != l_first); - mul_v3_fl(r_cent, 1.0f / (float) f->len); + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + add_v3_v3(r_cent, l_iter->v->co); + } while ((l_iter = l_iter->next) != l_first); + mul_v3_fl(r_cent, 1.0f / (float)f->len); } /** @@ -617,27 +616,26 @@ void BM_face_calc_center_median(const BMFace *f, float r_cent[3]) */ void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3]) { - const BMLoop *l_iter; - const BMLoop *l_first; - float totw = 0.0f; - float w_prev; - - zero_v3(r_cent); - - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - w_prev = BM_edge_calc_length(l_iter->prev->e); - do { - const float w_curr = BM_edge_calc_length(l_iter->e); - const float w = (w_curr + w_prev); - madd_v3_v3fl(r_cent, l_iter->v->co, w); - totw += w; - w_prev = w_curr; - } while ((l_iter = l_iter->next) != l_first); - - if (totw != 0.0f) { - mul_v3_fl(r_cent, 1.0f / (float) totw); - } + const BMLoop *l_iter; + const BMLoop *l_first; + float totw = 0.0f; + float w_prev; + + zero_v3(r_cent); + + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + w_prev = BM_edge_calc_length(l_iter->prev->e); + do { + const float w_curr = BM_edge_calc_length(l_iter->e); + const float w = (w_curr + w_prev); + madd_v3_v3fl(r_cent, l_iter->v->co, w); + totw += w; + w_prev = w_curr; + } while ((l_iter = l_iter->next) != l_first); + + if (totw != 0.0f) { + mul_v3_fl(r_cent, 1.0f / (float)totw); + } } /** @@ -648,17 +646,17 @@ void BM_face_calc_center_median_weighted(const BMFace *f, float r_cent[3]) */ void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nverts) { - float mat[3][3]; - float co[3]; - uint i; + float mat[3][3]; + float co[3]; + uint i; - co[2] = 0.0f; + co[2] = 0.0f; - axis_dominant_v3_to_m3(mat, normal); - for (i = 0; i < nverts; i++) { - mul_v2_m3v3(co, mat, verts[i]); - copy_v3_v3(verts[i], co); - } + axis_dominant_v3_to_m3(mat, normal); + for (i = 0; i < nverts; i++) { + mul_v2_m3v3(co, mat, verts[i]); + copy_v3_v3(verts[i], co); + } } /** @@ -666,119 +664,119 @@ void poly_rotate_plane(const float normal[3], float (*verts)[3], const uint nver */ void BM_edge_normals_update(BMEdge *e) { - BMIter iter; - BMFace *f; + BMIter iter; + BMFace *f; - BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { - BM_face_normal_update(f); - } + BM_ITER_ELEM (f, &iter, e, BM_FACES_OF_EDGE) { + BM_face_normal_update(f); + } - BM_vert_normal_update(e->v1); - BM_vert_normal_update(e->v2); + BM_vert_normal_update(e->v1); + BM_vert_normal_update(e->v2); } static void bm_loop_normal_accum(const BMLoop *l, float no[3]) { - float vec1[3], vec2[3], fac; + float vec1[3], vec2[3], fac; - /* 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); + /* 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); - fac = saacos(-dot_v3v3(vec1, vec2)); + fac = saacos(-dot_v3v3(vec1, vec2)); - madd_v3_v3fl(no, l->f->no, fac); + madd_v3_v3fl(no, l->f->no, fac); } bool BM_vert_calc_normal_ex(const BMVert *v, const char hflag, float r_no[3]) { - int len = 0; - - zero_v3(r_no); - - 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) { - normalize_v3(r_no); - return true; - } - else { - return false; - } + int len = 0; + + zero_v3(r_no); + + 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) { + normalize_v3(r_no); + return true; + } + else { + return false; + } } bool BM_vert_calc_normal(const BMVert *v, float r_no[3]) { - int len = 0; - - zero_v3(r_no); - - 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); - } - - if (len) { - normalize_v3(r_no); - return true; - } - else { - return false; - } + int len = 0; + + zero_v3(r_no); + + 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); + } + + if (len) { + normalize_v3(r_no); + return true; + } + else { + return false; + } } void BM_vert_normal_update_all(BMVert *v) { - int len = 0; - - zero_v3(v->no); - - 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) { - normalize_v3(v->no); - } + int len = 0; + + zero_v3(v->no); + + 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) { + normalize_v3(v->no); + } } /** @@ -786,7 +784,7 @@ void BM_vert_normal_update_all(BMVert *v) */ void BM_vert_normal_update(BMVert *v) { - BM_vert_calc_normal(v, v->no); + BM_vert_calc_normal(v, v->no); } /** @@ -801,73 +799,68 @@ void BM_vert_normal_update(BMVert *v) float BM_face_calc_normal(const BMFace *f, float r_no[3]) { - BMLoop *l; - - /* common cases first */ - switch (f->len) { - case 4: - { - const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; - const float *co2 = (l = l->next)->v->co; - const float *co3 = (l = l->next)->v->co; - const float *co4 = (l->next)->v->co; - - return normal_quad_v3(r_no, co1, co2, co3, co4); - } - case 3: - { - const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; - const float *co2 = (l = l->next)->v->co; - const float *co3 = (l->next)->v->co; - - return normal_tri_v3(r_no, co1, co2, co3); - } - default: - { - return bm_face_calc_poly_normal(f, r_no); - } - } + BMLoop *l; + + /* common cases first */ + switch (f->len) { + case 4: { + const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; + const float *co2 = (l = l->next)->v->co; + const float *co3 = (l = l->next)->v->co; + const float *co4 = (l->next)->v->co; + + return normal_quad_v3(r_no, co1, co2, co3, co4); + } + case 3: { + const float *co1 = (l = BM_FACE_FIRST_LOOP(f))->v->co; + const float *co2 = (l = l->next)->v->co; + const float *co3 = (l->next)->v->co; + + return normal_tri_v3(r_no, co1, co2, co3); + } + default: { + return bm_face_calc_poly_normal(f, r_no); + } + } } void BM_face_normal_update(BMFace *f) { - BM_face_calc_normal(f, f->no); + BM_face_calc_normal(f, f->no); } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -float BM_face_calc_normal_vcos( - const BMesh *bm, const BMFace *f, float r_no[3], - float const (*vertexCos)[3]) +float BM_face_calc_normal_vcos(const BMesh *bm, + const BMFace *f, + float r_no[3], + float const (*vertexCos)[3]) { - BMLoop *l; - - /* must have valid index data */ - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - (void)bm; - - /* common cases first */ - switch (f->len) { - case 4: - { - const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; - const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; - const float *co3 = vertexCos[BM_elem_index_get((l = l->next)->v)]; - const float *co4 = vertexCos[BM_elem_index_get((l->next)->v)]; - - return normal_quad_v3(r_no, co1, co2, co3, co4); - } - case 3: - { - const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; - const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; - const float *co3 = vertexCos[BM_elem_index_get((l->next)->v)]; - - return normal_tri_v3(r_no, co1, co2, co3); - } - default: - { - return bm_face_calc_poly_normal_vertex_cos(f, r_no, vertexCos); - } - } + BMLoop *l; + + /* must have valid index data */ + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + (void)bm; + + /* common cases first */ + switch (f->len) { + case 4: { + const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; + const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; + const float *co3 = vertexCos[BM_elem_index_get((l = l->next)->v)]; + const float *co4 = vertexCos[BM_elem_index_get((l->next)->v)]; + + return normal_quad_v3(r_no, co1, co2, co3, co4); + } + case 3: { + const float *co1 = vertexCos[BM_elem_index_get((l = BM_FACE_FIRST_LOOP(f))->v)]; + const float *co2 = vertexCos[BM_elem_index_get((l = l->next)->v)]; + const float *co3 = vertexCos[BM_elem_index_get((l->next)->v)]; + + return normal_tri_v3(r_no, co1, co2, co3); + } + default: { + return bm_face_calc_poly_normal_vertex_cos(f, r_no, vertexCos); + } + } } /** @@ -875,34 +868,35 @@ float BM_face_calc_normal_vcos( */ float BM_face_calc_normal_subset(const BMLoop *l_first, const BMLoop *l_last, float r_no[3]) { - const float *v_prev, *v_curr; + const float *v_prev, *v_curr; - /* Newell's Method */ - const BMLoop *l_iter = l_first; - const BMLoop *l_term = l_last->next; + /* Newell's Method */ + const BMLoop *l_iter = l_first; + const BMLoop *l_term = l_last->next; - zero_v3(r_no); + zero_v3(r_no); - v_prev = l_last->v->co; - do { - v_curr = l_iter->v->co; - add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); - v_prev = v_curr; - } while ((l_iter = l_iter->next) != l_term); + v_prev = l_last->v->co; + do { + v_curr = l_iter->v->co; + add_newell_cross_v3_v3v3(r_no, v_prev, v_curr); + v_prev = v_curr; + } while ((l_iter = l_iter->next) != l_term); - return normalize_v3(r_no); + return normalize_v3(r_no); } /* exact same as 'BM_face_calc_normal' but accepts vertex coords */ -void BM_face_calc_center_median_vcos( - const BMesh *bm, const BMFace *f, float r_cent[3], - float const (*vertexCos)[3]) +void BM_face_calc_center_median_vcos(const BMesh *bm, + const BMFace *f, + float r_cent[3], + float const (*vertexCos)[3]) { - /* must have valid index data */ - BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); - (void)bm; + /* must have valid index data */ + BLI_assert((bm->elem_index_dirty & BM_VERT) == 0); + (void)bm; - bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos); + bm_face_calc_poly_center_median_vertex_cos(f, r_cent, vertexCos); } /** @@ -911,18 +905,19 @@ void BM_face_calc_center_median_vcos( * Reverses the winding of a face. * \note This updates the calculated normal. */ -void BM_face_normal_flip_ex( - BMesh *bm, BMFace *f, - const int cd_loop_mdisp_offset, const bool use_loop_mdisp_flip) +void BM_face_normal_flip_ex(BMesh *bm, + BMFace *f, + const int cd_loop_mdisp_offset, + const bool use_loop_mdisp_flip) { - bmesh_kernel_loop_reverse(bm, f, cd_loop_mdisp_offset, use_loop_mdisp_flip); - negate_v3(f->no); + bmesh_kernel_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); + 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); } /** @@ -937,24 +932,24 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f) */ 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); + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); - float co_2d[2]; - BMLoop *l_iter; - int i; + float co_2d[2]; + BMLoop *l_iter; + int i; - BLI_assert(BM_face_is_normal_valid(f)); + BLI_assert(BM_face_is_normal_valid(f)); - axis_dominant_v3_to_m3(axis_mat, f->no); + axis_dominant_v3_to_m3(axis_mat, f->no); - mul_v2_m3v3(co_2d, axis_mat, co); + mul_v2_m3v3(co_2d, axis_mat, co); - for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) { - 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) { + mul_v2_m3v3(projverts[i], axis_mat, l_iter->v->co); + } - return isect_point_poly_v2(co_2d, projverts, f->len, false); + return isect_point_poly_v2(co_2d, projverts, f->len, false); } /** @@ -980,236 +975,226 @@ bool BM_face_point_inside_test(const BMFace *f, const float co[3]) * * \note use_tag tags new flags and edges. */ -void BM_face_triangulate( - BMesh *bm, BMFace *f, - BMFace **r_faces_new, - 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, - /* use for ngons only! */ - MemArena *pf_arena, - - /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ - struct Heap *pf_heap) +void BM_face_triangulate(BMesh *bm, + BMFace *f, + BMFace **r_faces_new, + 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, + /* use for ngons only! */ + MemArena *pf_arena, + + /* use for MOD_TRIANGULATE_NGON_BEAUTY only! */ + struct Heap *pf_heap) { - 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; - - 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)); - - BLI_assert(f->len > 3); - - { - BMLoop **loops = BLI_array_alloca(loops, f->len); - uint (*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; - } - 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 { - /* 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; - } - break; - } - } - - loops[0] = l_v1; - loops[1] = l_v1->next; - loops[2] = l_v2; - loops[3] = l_v2->next; - - ARRAY_SET_ITEMS(tris[0], 0, 1, 2); - ARRAY_SET_ITEMS(tris[1], 0, 2, 3); - } - else { - BMLoop *l_iter; - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - - 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); - } - - BLI_polyfill_calc_arena(projverts, f->len, 1, tris, - pf_arena); - - if (use_beauty) { - BLI_polyfill_beautify( - projverts, f->len, tris, - pf_arena, pf_heap); - } - - BLI_memarena_clear(pf_arena); - } - - if (cd_loop_mdisp_offset != -1) { - BM_face_calc_center_median(f, f_center); - } - - /* loop over calculated triangles and create new geometry */ - for (i = 0; i < totfilltri; i++) { - BMLoop *l_tri[3] = { - loops[tris[i][0]], - loops[tris[i][1]], - loops[tris[i][2]]}; - - BMVert *v_tri[3] = { - l_tri[0]->v, - l_tri[1]->v, - l_tri[2]->v}; - - f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true); - l_new = BM_FACE_FIRST_LOOP(f_new); - - 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); - BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev); - - /* add all but the last face which is swapped and removed (below) */ - if (i != last_tri) { - if (use_tag) { - BM_elem_flag_enable(f_new, BM_ELEM_TAG); - } - if (r_faces_new) { - r_faces_new[nf_i++] = f_new; - } - } - - if (use_tag || r_edges_new) { - /* new faces loops */ - BMLoop *l_iter; - - l_iter = l_first = l_new; - do { - BMEdge *e = l_iter->e; - /* 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 */ - bool is_new_edge = (l_iter == l_iter->radial_next); - - if (is_new_edge) { - if (use_tag) { - BM_elem_flag_enable(e, BM_ELEM_TAG); - } - if (r_edges_new) { - r_edges_new[ne_i++] = e; - } - } - /* 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_median(f_new, f_new_center); - BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset); - } - } - - { - /* 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); - } - } - bm->elem_index_dirty |= BM_FACE; - - if (r_faces_new_tot) { - *r_faces_new_tot = nf_i; - } - - if (r_edges_new_tot) { - *r_edges_new_tot = ne_i; - } + 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; + + 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)); + + BLI_assert(f->len > 3); + + { + BMLoop **loops = BLI_array_alloca(loops, f->len); + uint(*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; + } + 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 { + /* 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; + } + break; + } + } + + loops[0] = l_v1; + loops[1] = l_v1->next; + loops[2] = l_v2; + loops[3] = l_v2->next; + + ARRAY_SET_ITEMS(tris[0], 0, 1, 2); + ARRAY_SET_ITEMS(tris[1], 0, 2, 3); + } + else { + BMLoop *l_iter; + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); + + 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); + } + + BLI_polyfill_calc_arena(projverts, f->len, 1, tris, pf_arena); + + if (use_beauty) { + BLI_polyfill_beautify(projverts, f->len, tris, pf_arena, pf_heap); + } + + BLI_memarena_clear(pf_arena); + } + + if (cd_loop_mdisp_offset != -1) { + BM_face_calc_center_median(f, f_center); + } + + /* loop over calculated triangles and create new geometry */ + for (i = 0; i < totfilltri; i++) { + BMLoop *l_tri[3] = {loops[tris[i][0]], loops[tris[i][1]], loops[tris[i][2]]}; + + BMVert *v_tri[3] = {l_tri[0]->v, l_tri[1]->v, l_tri[2]->v}; + + f_new = BM_face_create_verts(bm, v_tri, 3, f, BM_CREATE_NOP, true); + l_new = BM_FACE_FIRST_LOOP(f_new); + + 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); + BM_elem_attrs_copy(bm, bm, l_tri[2], l_new->prev); + + /* add all but the last face which is swapped and removed (below) */ + if (i != last_tri) { + if (use_tag) { + BM_elem_flag_enable(f_new, BM_ELEM_TAG); + } + if (r_faces_new) { + r_faces_new[nf_i++] = f_new; + } + } + + if (use_tag || r_edges_new) { + /* new faces loops */ + BMLoop *l_iter; + + l_iter = l_first = l_new; + do { + BMEdge *e = l_iter->e; + /* 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 */ + bool is_new_edge = (l_iter == l_iter->radial_next); + + if (is_new_edge) { + if (use_tag) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + } + if (r_edges_new) { + r_edges_new[ne_i++] = e; + } + } + /* 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_median(f_new, f_new_center); + BM_face_interp_multires_ex(bm, f_new, f, f_new_center, f_center, cd_loop_mdisp_offset); + } + } + + { + /* 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); + } + } + bm->elem_index_dirty |= BM_FACE; + + if (r_faces_new_tot) { + *r_faces_new_tot = nf_i; + } + + if (r_edges_new_tot) { + *r_edges_new_tot = ne_i; + } } /** @@ -1222,101 +1207,97 @@ void BM_face_triangulate( */ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) { - float out[2] = {-FLT_MAX, -FLT_MAX}; - float center[2] = {0.0f, 0.0f}; - float axis_mat[3][3]; - float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len); - BMLoop *l; - int i, i_prev, j; - - BLI_assert(BM_face_is_normal_valid(f)); - - axis_dominant_v3_to_m3(axis_mat, f->no); - - for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { - mul_v2_m3v3(projverts[i], axis_mat, l->v->co); - add_v2_v2(center, projverts[i]); - } - - /* first test for completely convex face */ - if (is_poly_convex_v2(projverts, f->len)) { - return; - } - - mul_v2_fl(center, 1.0f / f->len); - - for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { - BM_elem_index_set(l, i); /* set_dirty */ - - /* center the projection for maximum accuracy */ - sub_v2_v2(projverts[i], center); - - out[0] = max_ff(out[0], projverts[i][0]); - out[1] = max_ff(out[1], projverts[i][1]); - } - bm->elem_index_dirty |= BM_LOOP; - - /* ensure we are well outside the face bounds (value is arbitrary) */ - add_v2_fl(out, 1.0f); - - for (i = 0; i < len; i++) { - edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])]; - edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])]; - } - - /* do convexity test */ - for (i = 0; i < len; i++) { - float mid[2]; - mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]); - - int isect = 0; - int j_prev; - for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) { - const float *f_edge[2] = {projverts[j_prev], projverts[j]}; - if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) { - isect++; - } - } - - if (isect % 2 == 0) { - loops[i][0] = NULL; - } - } + float out[2] = {-FLT_MAX, -FLT_MAX}; + float center[2] = {0.0f, 0.0f}; + float axis_mat[3][3]; + float(*projverts)[2] = BLI_array_alloca(projverts, f->len); + const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len); + BMLoop *l; + int i, i_prev, j; + + BLI_assert(BM_face_is_normal_valid(f)); + + axis_dominant_v3_to_m3(axis_mat, f->no); + + for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { + mul_v2_m3v3(projverts[i], axis_mat, l->v->co); + add_v2_v2(center, projverts[i]); + } + + /* first test for completely convex face */ + if (is_poly_convex_v2(projverts, f->len)) { + return; + } + + mul_v2_fl(center, 1.0f / f->len); + + for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { + BM_elem_index_set(l, i); /* set_dirty */ + + /* center the projection for maximum accuracy */ + sub_v2_v2(projverts[i], center); + + out[0] = max_ff(out[0], projverts[i][0]); + out[1] = max_ff(out[1], projverts[i][1]); + } + bm->elem_index_dirty |= BM_LOOP; + + /* ensure we are well outside the face bounds (value is arbitrary) */ + add_v2_fl(out, 1.0f); + + for (i = 0; i < len; i++) { + edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])]; + edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])]; + } + + /* do convexity test */ + for (i = 0; i < len; i++) { + float mid[2]; + mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]); + + int isect = 0; + int j_prev; + for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) { + const float *f_edge[2] = {projverts[j_prev], projverts[j]}; + if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) { + isect++; + } + } + + if (isect % 2 == 0) { + loops[i][0] = NULL; + } + } #define EDGE_SHARE_VERT(e1, e2) \ - ((ELEM((e1)[0], (e2)[0], (e2)[1])) || \ - (ELEM((e1)[1], (e2)[0], (e2)[1]))) - - /* do line crossing tests */ - for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) { - const float *f_edge[2] = {projverts[i_prev], projverts[i]}; - for (j = 0; j < len; j++) { - if ((loops[j][0] != NULL) && - !EDGE_SHARE_VERT(f_edge, edgeverts[j])) - { - if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { - loops[j][0] = NULL; - } - } - } - } - - /* self intersect tests */ - for (i = 0; i < len; i++) { - if (loops[i][0]) { - for (j = i + 1; j < len; j++) { - if ((loops[j][0] != NULL) && - !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j])) - { - if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { - loops[i][0] = NULL; - break; - } - } - } - } - } + ((ELEM((e1)[0], (e2)[0], (e2)[1])) || (ELEM((e1)[1], (e2)[0], (e2)[1]))) + + /* do line crossing tests */ + for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) { + const float *f_edge[2] = {projverts[i_prev], projverts[i]}; + for (j = 0; j < len; j++) { + if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(f_edge, edgeverts[j])) { + if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { + loops[j][0] = NULL; + } + } + } + } + + /* self intersect tests */ + for (i = 0; i < len; i++) { + if (loops[i][0]) { + for (j = i + 1; j < len; j++) { + if ((loops[j][0] != NULL) && !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j])) { + if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) == + ISECT_LINE_LINE_CROSS) { + loops[i][0] = NULL; + break; + } + } + } + } + } #undef EDGE_SHARE_VERT } @@ -1327,14 +1308,15 @@ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int l */ void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) { - int i; - - for (i = 0; i < len; i++) { - BMLoop *l_a_dummy, *l_b_dummy; - if (f != BM_vert_pair_share_face_by_angle(loops[i][0]->v, loops[i][1]->v, &l_a_dummy, &l_b_dummy, false)) { - loops[i][0] = NULL; - } - } + int i; + + for (i = 0; i < len; i++) { + BMLoop *l_a_dummy, *l_b_dummy; + if (f != BM_vert_pair_share_face_by_angle( + loops[i][0]->v, loops[i][1]->v, &l_a_dummy, &l_b_dummy, false)) { + loops[i][0] = NULL; + } + } } /** @@ -1345,13 +1327,15 @@ void BM_face_splits_check_optimal(BMFace *f, BMLoop *(*loops)[2], int len) */ void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 3); + BLI_assert(f->len == 3); - r_verts[0] = l->v; l = l->next; - r_verts[1] = l->v; l = l->next; - r_verts[2] = l->v; + r_verts[0] = l->v; + l = l->next; + r_verts[1] = l->v; + l = l->next; + r_verts[2] = l->v; } /** @@ -1360,17 +1344,19 @@ void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) */ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 4); + BLI_assert(f->len == 4); - r_verts[0] = l->v; l = l->next; - r_verts[1] = l->v; l = l->next; - r_verts[2] = l->v; l = l->next; - r_verts[3] = l->v; + r_verts[0] = l->v; + l = l->next; + r_verts[1] = l->v; + l = l->next; + r_verts[2] = l->v; + l = l->next; + r_verts[3] = l->v; } - /** * Small utility functions for fast access * @@ -1379,13 +1365,15 @@ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) */ void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 3); + BLI_assert(f->len == 3); - r_loops[0] = l; l = l->next; - r_loops[1] = l; l = l->next; - r_loops[2] = l; + r_loops[0] = l; + l = l->next; + r_loops[1] = l; + l = l->next; + r_loops[2] = l; } /** @@ -1394,17 +1382,19 @@ void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) */ void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) { - BMLoop *l = BM_FACE_FIRST_LOOP(f); + BMLoop *l = BM_FACE_FIRST_LOOP(f); - BLI_assert(f->len == 4); + BLI_assert(f->len == 4); - r_loops[0] = l; l = l->next; - r_loops[1] = l; l = l->next; - r_loops[2] = l; l = l->next; - r_loops[3] = l; + r_loops[0] = l; + l = l->next; + r_loops[1] = l; + l = l->next; + r_loops[2] = l; + l = l->next; + r_loops[3] = l; } - /** * \brief BM_mesh_calc_tessellation get the looptris and its number from a certain bmesh * \param looptris: @@ -1413,287 +1403,280 @@ void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) */ 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 */ + /* use this to avoid locking pthread for _every_ polygon + * and calling the fill function */ #define USE_TESSFACE_SPEEDUP - /* this assumes all faces can be scan-filled, which isn't always true, - * worst case we over alloc a little which is acceptable */ + /* this assumes all faces can be scan-filled, which isn't always true, + * worst case we over alloc a little which is acceptable */ #ifndef NDEBUG - const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); + const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); #endif - BMIter iter; - BMFace *efa; - int i = 0; + BMIter iter; + BMFace *efa; + int i = 0; - MemArena *arena = NULL; + MemArena *arena = NULL; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - /* don't consider two-edged faces */ - if (UNLIKELY(efa->len < 3)) { - /* do nothing */ - } + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + /* don't consider two-edged faces */ + if (UNLIKELY(efa->len < 3)) { + /* do nothing */ + } #ifdef USE_TESSFACE_SPEEDUP - /* no need to ensure the loop order, we know its ok */ - - else if (efa->len == 3) { -#if 0 - int j; - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { - looptris[i][j] = l; - } - i += 1; -#else - /* more cryptic but faster */ - BMLoop *l; - BMLoop **l_ptr = looptris[i++]; - l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); - l_ptr[1] = l = l->next; - l_ptr[2] = l->next; -#endif - } - else if (efa->len == 4) { -#if 0 - BMLoop *ltmp[4]; - int j; - BLI_array_grow_items(looptris, 2); - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { - ltmp[j] = l; - } - - looptris[i][0] = ltmp[0]; - looptris[i][1] = ltmp[1]; - looptris[i][2] = ltmp[2]; - i += 1; - - looptris[i][0] = ltmp[0]; - looptris[i][1] = ltmp[2]; - looptris[i][2] = ltmp[3]; - i += 1; -#else - /* more cryptic but faster */ - BMLoop *l; - BMLoop **l_ptr_a = looptris[i++]; - BMLoop **l_ptr_b = looptris[i++]; - (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa)); - (l_ptr_a[1] = l = l->next); - (l_ptr_a[2] = l_ptr_b[1] = l = l->next); - ( l_ptr_b[2] = l->next); -#endif - - if (UNLIKELY(is_quad_flip_v3_first_third_fast( - l_ptr_a[0]->v->co, - l_ptr_a[1]->v->co, - l_ptr_a[2]->v->co, - l_ptr_b[2]->v->co))) - { - /* flip out of degenerate 0-2 state. */ - l_ptr_a[2] = l_ptr_b[2]; - l_ptr_b[0] = l_ptr_a[1]; - } - } + /* no need to ensure the loop order, we know its ok */ + + else if (efa->len == 3) { +# if 0 + int j; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { + looptris[i][j] = l; + } + i += 1; +# else + /* more cryptic but faster */ + BMLoop *l; + BMLoop **l_ptr = looptris[i++]; + l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); + l_ptr[1] = l = l->next; + l_ptr[2] = l->next; +# endif + } + else if (efa->len == 4) { +# if 0 + BMLoop *ltmp[4]; + int j; + BLI_array_grow_items(looptris, 2); + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, j) { + ltmp[j] = l; + } + + looptris[i][0] = ltmp[0]; + looptris[i][1] = ltmp[1]; + looptris[i][2] = ltmp[2]; + i += 1; + + looptris[i][0] = ltmp[0]; + looptris[i][1] = ltmp[2]; + looptris[i][2] = ltmp[3]; + i += 1; +# else + /* more cryptic but faster */ + BMLoop *l; + BMLoop **l_ptr_a = looptris[i++]; + BMLoop **l_ptr_b = looptris[i++]; + (l_ptr_a[0] = l_ptr_b[0] = l = BM_FACE_FIRST_LOOP(efa)); + (l_ptr_a[1] = l = l->next); + (l_ptr_a[2] = l_ptr_b[1] = l = l->next); + (l_ptr_b[2] = l->next); +# endif + + if (UNLIKELY(is_quad_flip_v3_first_third_fast( + l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co))) { + /* flip out of degenerate 0-2 state. */ + l_ptr_a[2] = l_ptr_b[2]; + l_ptr_b[0] = l_ptr_a[1]; + } + } #endif /* USE_TESSFACE_SPEEDUP */ - else { - int j; + else { + int j; - BMLoop *l_iter; - BMLoop *l_first; - BMLoop **l_arr; + BMLoop *l_iter; + BMLoop *l_first; + BMLoop **l_arr; - float axis_mat[3][3]; - float (*projverts)[2]; - uint (*tris)[3]; + float axis_mat[3][3]; + float(*projverts)[2]; + uint(*tris)[3]; - const int totfilltri = efa->len - 2; + const int totfilltri = efa->len - 2; - if (UNLIKELY(arena == NULL)) { - arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - } + if (UNLIKELY(arena == NULL)) { + arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + } - tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri); - l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len); - projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len); + tris = BLI_memarena_alloc(arena, sizeof(*tris) * totfilltri); + l_arr = BLI_memarena_alloc(arena, sizeof(*l_arr) * efa->len); + projverts = BLI_memarena_alloc(arena, sizeof(*projverts) * efa->len); - axis_dominant_v3_to_m3_negate(axis_mat, efa->no); + axis_dominant_v3_to_m3_negate(axis_mat, efa->no); - j = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - l_arr[j] = l_iter; - mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); - j++; - } while ((l_iter = l_iter->next) != l_first); + j = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + l_arr[j] = l_iter; + mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); + j++; + } while ((l_iter = l_iter->next) != l_first); - BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, arena); + BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, arena); - for (j = 0; j < totfilltri; j++) { - BMLoop **l_ptr = looptris[i++]; - uint *tri = tris[j]; + for (j = 0; j < totfilltri; j++) { + BMLoop **l_ptr = looptris[i++]; + uint *tri = tris[j]; - l_ptr[0] = l_arr[tri[0]]; - l_ptr[1] = l_arr[tri[1]]; - l_ptr[2] = l_arr[tri[2]]; - } + l_ptr[0] = l_arr[tri[0]]; + l_ptr[1] = l_arr[tri[1]]; + l_ptr[2] = l_arr[tri[2]]; + } - BLI_memarena_clear(arena); - } - } + BLI_memarena_clear(arena); + } + } - if (arena) { - BLI_memarena_free(arena); - arena = NULL; - } + if (arena) { + BLI_memarena_free(arena); + arena = NULL; + } - *r_looptris_tot = i; + *r_looptris_tot = i; - BLI_assert(i <= looptris_tot); + BLI_assert(i <= looptris_tot); #undef USE_TESSFACE_SPEEDUP - } - /** * A version of #BM_mesh_calc_tessellation that avoids degenerate triangles. */ void BM_mesh_calc_tessellation_beauty(BMesh *bm, BMLoop *(*looptris)[3], int *r_looptris_tot) { - /* this assumes all faces can be scan-filled, which isn't always true, - * worst case we over alloc a little which is acceptable */ + /* this assumes all faces can be scan-filled, which isn't always true, + * worst case we over alloc a little which is acceptable */ #ifndef NDEBUG - const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); + const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); #endif - BMIter iter; - BMFace *efa; - int i = 0; - - MemArena *pf_arena = NULL; - - /* use_beauty */ - Heap *pf_heap = NULL; - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - /* don't consider two-edged faces */ - if (UNLIKELY(efa->len < 3)) { - /* do nothing */ - } - else if (efa->len == 3) { - BMLoop *l; - BMLoop **l_ptr = looptris[i++]; - l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); - l_ptr[1] = l = l->next; - l_ptr[2] = l->next; - } - else if (efa->len == 4) { - BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa); - BMLoop *l_v2 = l_v1->next; - BMLoop *l_v3 = l_v2->next; - BMLoop *l_v4 = l_v1->prev; - - /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need! - * It's meant for rotating edges, it also calculates a new normal. - * - * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal. - */ + BMIter iter; + BMFace *efa; + int i = 0; + + MemArena *pf_arena = NULL; + + /* use_beauty */ + Heap *pf_heap = NULL; + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + /* don't consider two-edged faces */ + if (UNLIKELY(efa->len < 3)) { + /* do nothing */ + } + else if (efa->len == 3) { + BMLoop *l; + BMLoop **l_ptr = looptris[i++]; + l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); + l_ptr[1] = l = l->next; + l_ptr[2] = l->next; + } + else if (efa->len == 4) { + BMLoop *l_v1 = BM_FACE_FIRST_LOOP(efa); + BMLoop *l_v2 = l_v1->next; + BMLoop *l_v3 = l_v2->next; + BMLoop *l_v4 = l_v1->prev; + + /* #BM_verts_calc_rotate_beauty performs excessive checks we don't need! + * It's meant for rotating edges, it also calculates a new normal. + * + * Use #BLI_polyfill_beautify_quad_rotate_calc since we have the normal. + */ #if 0 - const bool split_13 = (BM_verts_calc_rotate_beauty( - l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f); + const bool split_13 = (BM_verts_calc_rotate_beauty( + l_v1->v, l_v2->v, l_v3->v, l_v4->v, 0, 0) < 0.0f); #else - float axis_mat[3][3], v_quad[4][2]; - axis_dominant_v3_to_m3(axis_mat, efa->no); - mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co); - mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co); - mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co); - mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co); - - const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc( - v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f; + float axis_mat[3][3], v_quad[4][2]; + axis_dominant_v3_to_m3(axis_mat, efa->no); + mul_v2_m3v3(v_quad[0], axis_mat, l_v1->v->co); + mul_v2_m3v3(v_quad[1], axis_mat, l_v2->v->co); + mul_v2_m3v3(v_quad[2], axis_mat, l_v3->v->co); + mul_v2_m3v3(v_quad[3], axis_mat, l_v4->v->co); + + const bool split_13 = BLI_polyfill_beautify_quad_rotate_calc( + v_quad[0], v_quad[1], v_quad[2], v_quad[3]) < 0.0f; #endif - BMLoop **l_ptr_a = looptris[i++]; - BMLoop **l_ptr_b = looptris[i++]; - if (split_13) { - l_ptr_a[0] = l_v1; - l_ptr_a[1] = l_v2; - l_ptr_a[2] = l_v3; - - l_ptr_b[0] = l_v1; - l_ptr_b[1] = l_v3; - l_ptr_b[2] = l_v4; - } - else { - l_ptr_a[0] = l_v1; - l_ptr_a[1] = l_v2; - l_ptr_a[2] = l_v4; - - l_ptr_b[0] = l_v2; - l_ptr_b[1] = l_v3; - l_ptr_b[2] = l_v4; - } - } - else { - int j; - - BMLoop *l_iter; - BMLoop *l_first; - BMLoop **l_arr; - - float axis_mat[3][3]; - float (*projverts)[2]; - unsigned int (*tris)[3]; - - const int totfilltri = efa->len - 2; - - if (UNLIKELY(pf_arena == NULL)) { - pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); - } - - tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri); - l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len); - projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len); - - axis_dominant_v3_to_m3_negate(axis_mat, efa->no); - - j = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - l_arr[j] = l_iter; - mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); - j++; - } while ((l_iter = l_iter->next) != l_first); - - BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena); - - BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap); - - for (j = 0; j < totfilltri; j++) { - BMLoop **l_ptr = looptris[i++]; - unsigned int *tri = tris[j]; - - l_ptr[0] = l_arr[tri[0]]; - l_ptr[1] = l_arr[tri[1]]; - l_ptr[2] = l_arr[tri[2]]; - } - - BLI_memarena_clear(pf_arena); - } - } - - if (pf_arena) { - BLI_memarena_free(pf_arena); - - BLI_heap_free(pf_heap, NULL); - } - - *r_looptris_tot = i; - - BLI_assert(i <= looptris_tot); - + BMLoop **l_ptr_a = looptris[i++]; + BMLoop **l_ptr_b = looptris[i++]; + if (split_13) { + l_ptr_a[0] = l_v1; + l_ptr_a[1] = l_v2; + l_ptr_a[2] = l_v3; + + l_ptr_b[0] = l_v1; + l_ptr_b[1] = l_v3; + l_ptr_b[2] = l_v4; + } + else { + l_ptr_a[0] = l_v1; + l_ptr_a[1] = l_v2; + l_ptr_a[2] = l_v4; + + l_ptr_b[0] = l_v2; + l_ptr_b[1] = l_v3; + l_ptr_b[2] = l_v4; + } + } + else { + int j; + + BMLoop *l_iter; + BMLoop *l_first; + BMLoop **l_arr; + + float axis_mat[3][3]; + float(*projverts)[2]; + unsigned int(*tris)[3]; + + const int totfilltri = efa->len - 2; + + if (UNLIKELY(pf_arena == NULL)) { + pf_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + pf_heap = BLI_heap_new_ex(BLI_POLYFILL_ALLOC_NGON_RESERVE); + } + + tris = BLI_memarena_alloc(pf_arena, sizeof(*tris) * totfilltri); + l_arr = BLI_memarena_alloc(pf_arena, sizeof(*l_arr) * efa->len); + projverts = BLI_memarena_alloc(pf_arena, sizeof(*projverts) * efa->len); + + axis_dominant_v3_to_m3_negate(axis_mat, efa->no); + + j = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + l_arr[j] = l_iter; + mul_v2_m3v3(projverts[j], axis_mat, l_iter->v->co); + j++; + } while ((l_iter = l_iter->next) != l_first); + + BLI_polyfill_calc_arena(projverts, efa->len, 1, tris, pf_arena); + + BLI_polyfill_beautify(projverts, efa->len, tris, pf_arena, pf_heap); + + for (j = 0; j < totfilltri; j++) { + BMLoop **l_ptr = looptris[i++]; + unsigned int *tri = tris[j]; + + l_ptr[0] = l_arr[tri[0]]; + l_ptr[1] = l_arr[tri[1]]; + l_ptr[2] = l_arr[tri[2]]; + } + + BLI_memarena_clear(pf_arena); + } + } + + if (pf_arena) { + BLI_memarena_free(pf_arena); + + BLI_heap_free(pf_heap, NULL); + } + + *r_looptris_tot = i; + + BLI_assert(i <= looptris_tot); } |