Commit: 8a1860bd9aecddf611b64e3e842bdc8c76f15cc6 Author: Campbell Barton Date: Mon Jun 14 22:56:03 2021 +1000 Branches: master https://developer.blender.org/rB8a1860bd9aecddf611b64e3e842bdc8c76f15cc6
BMesh: support face-normal calculation in normal & looptri functions Support calculating face normals when tessellating. When this is done before updating vertex normals it gives ~20% performance improvement. Now vertex normal calculation only needs to perform a single pass on the mesh vertices when called after tessellation. Extended versions of normal & looptri update functions have been added: - BM_mesh_calc_tessellation_ex - BM_mesh_normals_update_ex Most callers don't need to be aware of this detail by using: - BKE_editmesh_looptri_and_normals_calc - BKE_editmesh_looptri_and_normals_calc_with_partial - EDBM_update also takes advantage of this, where calling EDBM_update with calc_looptri & calc_normals enabled uses the faster normal updating logic. =================================================================== M source/blender/blenkernel/BKE_editmesh.h M source/blender/blenkernel/intern/editmesh.c M source/blender/bmesh/intern/bmesh_mesh_normals.c M source/blender/bmesh/intern/bmesh_mesh_normals.h M source/blender/bmesh/intern/bmesh_mesh_tessellate.c M source/blender/bmesh/intern/bmesh_mesh_tessellate.h M source/blender/editors/include/ED_mesh.h M source/blender/editors/mesh/editmesh_utils.c M source/blender/editors/object/object_edit.c M source/blender/editors/object/object_hook.c M source/blender/editors/object/object_relations.c M source/blender/editors/transform/transform_convert_mesh.c M source/blender/editors/transform/transform_convert_mesh_skin.c M source/blender/makesrna/intern/rna_object.c =================================================================== diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 3a1eedfd807..075a9bc0eac 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -34,6 +34,7 @@ extern "C" { struct BMLoop; struct BMesh; struct BMPartialUpdate; +struct BMeshCalcTessellation_Params; struct BoundBox; struct Depsgraph; struct Mesh; @@ -85,8 +86,17 @@ typedef struct BMEditMesh { } BMEditMesh; /* editmesh.c */ +void BKE_editmesh_looptri_calc_ex(BMEditMesh *em, + const struct BMeshCalcTessellation_Params *params); void BKE_editmesh_looptri_calc(BMEditMesh *em); +void BKE_editmesh_looptri_calc_with_partial_ex(BMEditMesh *em, + struct BMPartialUpdate *bmpinfo, + const struct BMeshCalcTessellation_Params *params); void BKE_editmesh_looptri_calc_with_partial(BMEditMesh *em, struct BMPartialUpdate *bmpinfo); +void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em, + struct BMPartialUpdate *bmpinfo); + +void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em); BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate); BMEditMesh *BKE_editmesh_copy(BMEditMesh *em); diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 472de1f3c77..b908df267c4 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -96,7 +96,8 @@ BMEditMesh *BKE_editmesh_from_object(Object *ob) return ((Mesh *)ob->data)->edit_mesh; } -static void editmesh_tessface_calc_intern(BMEditMesh *em) +static void editmesh_tessface_calc_intern(BMEditMesh *em, + const struct BMeshCalcTessellation_Params *params) { /* allocating space before calculating the tessellation */ @@ -130,12 +131,13 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em) em->tottri = looptris_tot; /* after allocating the em->looptris, we're ready to tessellate */ - BM_mesh_calc_tessellation(em->bm, em->looptris); + BM_mesh_calc_tessellation_ex(em->bm, em->looptris, params); } -void BKE_editmesh_looptri_calc(BMEditMesh *em) +void BKE_editmesh_looptri_calc_ex(BMEditMesh *em, + const struct BMeshCalcTessellation_Params *params) { - editmesh_tessface_calc_intern(em); + editmesh_tessface_calc_intern(em, params); /* commented because editbmesh_build_data() ensures we get tessfaces */ #if 0 @@ -149,12 +151,58 @@ void BKE_editmesh_looptri_calc(BMEditMesh *em) #endif } -void BKE_editmesh_looptri_calc_with_partial(BMEditMesh *em, struct BMPartialUpdate *bmpinfo) +void BKE_editmesh_looptri_calc(BMEditMesh *em) +{ + BKE_editmesh_looptri_calc_ex(em, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = false, + }); +} + +/** + * Performing the face normal calculation at the same time as tessellation + * gives a reasonable performance boost (approx ~20% faster). + */ +void BKE_editmesh_looptri_and_normals_calc(BMEditMesh *em) +{ + BKE_editmesh_looptri_calc_ex(em, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = true, + }); + BM_mesh_normals_update_ex(em->bm, + &(const struct BMeshNormalsUpdate_Params){ + .face_normals = false, + }); +} + +void BKE_editmesh_looptri_calc_with_partial_ex(BMEditMesh *em, + struct BMPartialUpdate *bmpinfo, + const struct BMeshCalcTessellation_Params *params) { BLI_assert(em->tottri == poly_to_tri_count(em->bm->totface, em->bm->totloop)); BLI_assert(em->looptris != NULL); - BM_mesh_calc_tessellation_with_partial(em->bm, em->looptris, bmpinfo); + BM_mesh_calc_tessellation_with_partial_ex(em->bm, em->looptris, bmpinfo, params); +} + +void BKE_editmesh_looptri_calc_with_partial(BMEditMesh *em, struct BMPartialUpdate *bmpinfo) +{ + BKE_editmesh_looptri_calc_with_partial_ex(em, bmpinfo, false); +} + +void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em, + struct BMPartialUpdate *bmpinfo) +{ + BKE_editmesh_looptri_calc_with_partial_ex(em, + bmpinfo, + &(const struct BMeshCalcTessellation_Params){ + .face_normals = true, + }); + BM_mesh_normals_update_with_partial_ex(em->bm, + bmpinfo, + &(const struct BMeshNormalsUpdate_Params){ + .face_normals = false, + }); } void BKE_editmesh_free_derivedmesh(BMEditMesh *em) diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c index bf30f3a52e1..bddd3da98b7 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.c +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c @@ -240,19 +240,29 @@ static void bm_face_calc_normals_cb(void *UNUSED(userdata), * * Updates the normals of a mesh. */ -void BM_mesh_normals_update(BMesh *bm) +void BM_mesh_normals_update_ex(BMesh *bm, const struct BMeshNormalsUpdate_Params *params) { - /* Calculate all face normals. */ - TaskParallelSettings settings; - BLI_parallel_mempool_settings_defaults(&settings); - settings.use_threading = bm->totedge >= BM_OMP_LIMIT; + if (params->face_normals) { + /* Calculate all face normals. */ + TaskParallelSettings settings; + BLI_parallel_mempool_settings_defaults(&settings); + settings.use_threading = bm->totedge >= BM_OMP_LIMIT; - BM_iter_parallel(bm, BM_FACES_OF_MESH, bm_face_calc_normals_cb, NULL, &settings); + BM_iter_parallel(bm, BM_FACES_OF_MESH, bm_face_calc_normals_cb, NULL, &settings); + } /* Add weighted face normals to vertices, and normalize vert normals. */ bm_mesh_verts_calc_normals(bm, NULL, NULL, NULL); } +void BM_mesh_normals_update(BMesh *bm) +{ + BM_mesh_normals_update_ex(bm, + &(const struct BMeshNormalsUpdate_Params){ + .face_normals = true, + }); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -277,7 +287,9 @@ static void bm_partial_verts_parallel_range_calc_normal_cb( * A version of #BM_mesh_normals_update that updates a subset of geometry, * used to avoid the overhead of updating everything. */ -void BM_mesh_normals_update_with_partial(BMesh *UNUSED(bm), const BMPartialUpdate *bmpinfo) +void BM_mesh_normals_update_with_partial_ex(BMesh *UNUSED(bm), + const BMPartialUpdate *bmpinfo, + const struct BMeshNormalsUpdate_Params *params) { BLI_assert(bmpinfo->params.do_normals); @@ -290,14 +302,25 @@ void BM_mesh_normals_update_with_partial(BMesh *UNUSED(bm), const BMPartialUpdat BLI_parallel_range_settings_defaults(&settings); /* Faces. */ - BLI_task_parallel_range( - 0, faces_len, faces, bm_partial_faces_parallel_range_calc_normals_cb, &settings); + if (params->face_normals) { + BLI_task_parallel_range( + 0, faces_len, faces, bm_partial_faces_parallel_range_calc_normals_cb, &settings); + } /* Verts. */ BLI_task_parallel_range( 0, verts_len, verts, bm_partial_verts_parallel_range_calc_normal_cb, &settings); } +void BM_mesh_normals_update_with_partial(BMesh *bm, const BMPartialUpdate *bmpinfo) +{ + BM_mesh_normals_update_with_partial_ex(bm, + bmpinfo, + &(const struct BMeshNormalsUpdate_Params){ + .face_normals = true, + }); +} + /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.h b/source/blender/bmesh/intern/bmesh_mesh_normals.h index 41191340e9e..ecd627d4bfe 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_normals.h +++ b/source/blender/bmesh/intern/bmesh_mesh_normals.h @@ -22,7 +22,19 @@ #include "bmesh_class.h" +struct BMeshNormalsUpdate_Params { + /** + * When calculating tessellation as well as normals, tessellate & calculate face normals + * for improved performance. See #BMeshCalcTessellation_Params + */ + bool face_normals; +}; + +void BM_mesh_normals_update_ex(BMesh *bm, const struct BMeshNormalsUpdate_Params *param); void BM_mesh_normals_update(BMesh *bm); +void BM_mesh_normals_update_with_partial_ex(BMesh *bm, + const struct BMPartialUpdate *bmpinfo, + const struct BMeshNormalsUpdate_Params *param); void BM_mesh_normals_update_with_partial(BMesh *bm, const struct BMPartialUpdate *bmpinfo); void BM_verts_calc_normal_vcos(BMesh *bm, 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], + @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs