diff options
Diffstat (limited to 'source/blender/bmesh/intern/bmesh_mesh_tessellate.c')
-rw-r--r-- | source/blender/bmesh/intern/bmesh_mesh_tessellate.c | 161 |
1 files changed, 133 insertions, 28 deletions
diff --git a/source/blender/bmesh/intern/bmesh_mesh_tessellate.c b/source/blender/bmesh/intern/bmesh_mesh_tessellate.c index 7a95e52ce25..4092ad22ef9 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_tessellate.c +++ b/source/blender/bmesh/intern/bmesh_mesh_tessellate.c @@ -50,9 +50,13 @@ /** \name Default Mesh Tessellation * \{ */ -static int mesh_calc_tessellation_for_face(BMLoop *(*looptris)[3], - BMFace *efa, - MemArena **pf_arena_p) +/** + * \param face_normal: This will be optimized out as a constant. + */ +BLI_INLINE int mesh_calc_tessellation_for_face_impl(BMLoop *(*looptris)[3], + BMFace *efa, + MemArena **pf_arena_p, + const bool face_normal) { switch (efa->len) { case 3: { @@ -62,6 +66,9 @@ static int mesh_calc_tessellation_for_face(BMLoop *(*looptris)[3], l_ptr[0] = l = BM_FACE_FIRST_LOOP(efa); l_ptr[1] = l = l->next; l_ptr[2] = l->next; + if (face_normal) { + normal_tri_v3(efa->no, l_ptr[0]->v->co, l_ptr[1]->v->co, l_ptr[2]->v->co); + } return 1; } case 4: { @@ -74,6 +81,11 @@ static int mesh_calc_tessellation_for_face(BMLoop *(*looptris)[3], (l_ptr_a[2] = l_ptr_b[1] = l = l->next); (l_ptr_b[2] = l->next); + if (face_normal) { + normal_quad_v3( + efa->no, l_ptr_a[0]->v->co, l_ptr_a[1]->v->co, l_ptr_a[2]->v->co, l_ptr_b[2]->v->co); + } + 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. */ @@ -83,6 +95,10 @@ static int mesh_calc_tessellation_for_face(BMLoop *(*looptris)[3], return 2; } default: { + if (face_normal) { + BM_face_calc_normal(efa, efa->no); + } + BMLoop *l_iter, *l_first; BMLoop **l_arr; @@ -128,13 +144,29 @@ static int mesh_calc_tessellation_for_face(BMLoop *(*looptris)[3], } } +static int mesh_calc_tessellation_for_face(BMLoop *(*looptris)[3], + BMFace *efa, + MemArena **pf_arena_p) +{ + return mesh_calc_tessellation_for_face_impl(looptris, efa, pf_arena_p, false); +} + +static int mesh_calc_tessellation_for_face_with_normal(BMLoop *(*looptris)[3], + BMFace *efa, + MemArena **pf_arena_p) +{ + return mesh_calc_tessellation_for_face_impl(looptris, efa, pf_arena_p, true); +} + /** * \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 */ -static void bm_mesh_calc_tessellation__single_threaded(BMesh *bm, BMLoop *(*looptris)[3]) +static void bm_mesh_calc_tessellation__single_threaded(BMesh *bm, + BMLoop *(*looptris)[3], + const char face_normals) { #ifndef NDEBUG const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop); @@ -146,9 +178,18 @@ static void bm_mesh_calc_tessellation__single_threaded(BMesh *bm, BMLoop *(*loop MemArena *pf_arena = NULL; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BLI_assert(efa->len >= 3); - i += mesh_calc_tessellation_for_face(looptris + i, efa, &pf_arena); + if (face_normals) { + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + BLI_assert(efa->len >= 3); + BM_face_calc_normal(efa, efa->no); + i += mesh_calc_tessellation_for_face_with_normal(looptris + i, efa, &pf_arena); + } + } + else { + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + BLI_assert(efa->len >= 3); + i += mesh_calc_tessellation_for_face(looptris + i, efa, &pf_arena); + } } if (pf_arena) { @@ -175,6 +216,18 @@ static void mesh_calc_tessellation_for_face_fn(void *__restrict userdata, mesh_calc_tessellation_for_face(looptris + offset, f, &tls_data->pf_arena); } +static void mesh_calc_tessellation_for_face_with_normals_fn(void *__restrict userdata, + MempoolIterData *mp_f, + const TaskParallelTLS *__restrict tls) +{ + struct TessellationUserTLS *tls_data = tls->userdata_chunk; + BMLoop *(*looptris)[3] = userdata; + BMFace *f = (BMFace *)mp_f; + BMLoop *l = BM_FACE_FIRST_LOOP(f); + const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2); + mesh_calc_tessellation_for_face_with_normal(looptris + offset, f, &tls_data->pf_arena); +} + static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict UNUSED(userdata), void *__restrict tls_v) { @@ -184,7 +237,9 @@ static void mesh_calc_tessellation_for_face_free_fn(const void *__restrict UNUSE } } -static void bm_mesh_calc_tessellation__multi_threaded(BMesh *bm, BMLoop *(*looptris)[3]) +static void bm_mesh_calc_tessellation__multi_threaded(BMesh *bm, + BMLoop *(*looptris)[3], + const char face_normals) { BM_mesh_elem_index_ensure(bm, BM_LOOP | BM_FACE); @@ -194,19 +249,31 @@ static void bm_mesh_calc_tessellation__multi_threaded(BMesh *bm, BMLoop *(*loopt settings.userdata_chunk = &tls_dummy; settings.userdata_chunk_size = sizeof(tls_dummy); settings.func_free = mesh_calc_tessellation_for_face_free_fn; - BM_iter_parallel(bm, BM_FACES_OF_MESH, mesh_calc_tessellation_for_face_fn, looptris, &settings); + BM_iter_parallel(bm, + BM_FACES_OF_MESH, + face_normals ? mesh_calc_tessellation_for_face_with_normals_fn : + mesh_calc_tessellation_for_face_fn, + looptris, + &settings); } -void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3]) +void BM_mesh_calc_tessellation_ex(BMesh *bm, + BMLoop *(*looptris)[3], + const struct BMeshCalcTessellation_Params *params) { if (bm->totface < BM_FACE_TESSELLATE_THREADED_LIMIT) { - bm_mesh_calc_tessellation__single_threaded(bm, looptris); + bm_mesh_calc_tessellation__single_threaded(bm, looptris, params->face_normals); } else { - bm_mesh_calc_tessellation__multi_threaded(bm, looptris); + bm_mesh_calc_tessellation__multi_threaded(bm, looptris, params->face_normals); } } +void BM_mesh_calc_tessellation(BMesh *bm, BMLoop *(*looptris)[3]) +{ + BM_mesh_calc_tessellation_ex(bm, looptris, false); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -234,6 +301,17 @@ static void mesh_calc_tessellation_for_face_partial_fn(void *__restrict userdata mesh_calc_tessellation_for_face(data->looptris + offset, f, &tls_data->pf_arena); } +static void mesh_calc_tessellation_for_face_partial_with_normals_fn( + void *__restrict userdata, const int index, const TaskParallelTLS *__restrict tls) +{ + struct PartialTessellationUserTLS *tls_data = tls->userdata_chunk; + struct PartialTessellationUserData *data = userdata; + BMFace *f = data->faces[index]; + BMLoop *l = BM_FACE_FIRST_LOOP(f); + const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2); + mesh_calc_tessellation_for_face_with_normal(data->looptris + offset, f, &tls_data->pf_arena); +} + static void mesh_calc_tessellation_for_face_partial_free_fn( const void *__restrict UNUSED(userdata), void *__restrict tls_v) { @@ -243,8 +321,10 @@ static void mesh_calc_tessellation_for_face_partial_free_fn( } } -static void bm_mesh_calc_tessellation_with_partial__multi_threaded(BMLoop *(*looptris)[3], - const BMPartialUpdate *bmpinfo) +static void bm_mesh_calc_tessellation_with_partial__multi_threaded( + BMLoop *(*looptris)[3], + const BMPartialUpdate *bmpinfo, + const struct BMeshCalcTessellation_Params *params) { const int faces_len = bmpinfo->faces_len; BMFace **faces = bmpinfo->faces; @@ -261,23 +341,40 @@ static void bm_mesh_calc_tessellation_with_partial__multi_threaded(BMLoop *(*loo settings.userdata_chunk_size = sizeof(tls_dummy); settings.func_free = mesh_calc_tessellation_for_face_partial_free_fn; - BLI_task_parallel_range( - 0, faces_len, &data, mesh_calc_tessellation_for_face_partial_fn, &settings); + BLI_task_parallel_range(0, + faces_len, + &data, + params->face_normals ? + mesh_calc_tessellation_for_face_partial_with_normals_fn : + mesh_calc_tessellation_for_face_partial_fn, + &settings); } -static void bm_mesh_calc_tessellation_with_partial__single_threaded(BMLoop *(*looptris)[3], - const BMPartialUpdate *bmpinfo) +static void bm_mesh_calc_tessellation_with_partial__single_threaded( + BMLoop *(*looptris)[3], + const BMPartialUpdate *bmpinfo, + const struct BMeshCalcTessellation_Params *params) { const int faces_len = bmpinfo->faces_len; BMFace **faces = bmpinfo->faces; MemArena *pf_arena = NULL; - for (int index = 0; index < faces_len; index++) { - BMFace *f = faces[index]; - BMLoop *l = BM_FACE_FIRST_LOOP(f); - const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2); - mesh_calc_tessellation_for_face(looptris + offset, f, &pf_arena); + if (params->face_normals) { + for (int index = 0; index < faces_len; index++) { + BMFace *f = faces[index]; + BMLoop *l = BM_FACE_FIRST_LOOP(f); + const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2); + mesh_calc_tessellation_for_face_with_normal(looptris + offset, f, &pf_arena); + } + } + else { + for (int index = 0; index < faces_len; index++) { + BMFace *f = faces[index]; + BMLoop *l = BM_FACE_FIRST_LOOP(f); + const int offset = BM_elem_index_get(l) - (BM_elem_index_get(f) * 2); + mesh_calc_tessellation_for_face(looptris + offset, f, &pf_arena); + } } if (pf_arena) { @@ -285,22 +382,30 @@ static void bm_mesh_calc_tessellation_with_partial__single_threaded(BMLoop *(*lo } } -void BM_mesh_calc_tessellation_with_partial(BMesh *bm, - BMLoop *(*looptris)[3], - const BMPartialUpdate *bmpinfo) +void BM_mesh_calc_tessellation_with_partial_ex(BMesh *bm, + BMLoop *(*looptris)[3], + const BMPartialUpdate *bmpinfo, + const struct BMeshCalcTessellation_Params *params) { BLI_assert(bmpinfo->params.do_tessellate); BM_mesh_elem_index_ensure(bm, BM_LOOP | BM_FACE); if (bmpinfo->faces_len < BM_FACE_TESSELLATE_THREADED_LIMIT) { - bm_mesh_calc_tessellation_with_partial__single_threaded(looptris, bmpinfo); + bm_mesh_calc_tessellation_with_partial__single_threaded(looptris, bmpinfo, params); } else { - bm_mesh_calc_tessellation_with_partial__multi_threaded(looptris, bmpinfo); + bm_mesh_calc_tessellation_with_partial__multi_threaded(looptris, bmpinfo, params); } } +void BM_mesh_calc_tessellation_with_partial(BMesh *bm, + BMLoop *(*looptris)[3], + const BMPartialUpdate *bmpinfo) +{ + BM_mesh_calc_tessellation_with_partial_ex(bm, looptris, bmpinfo, false); +} + /** \} */ /* -------------------------------------------------------------------- */ |