From deaff945d0b965d1e588cdecd084080b07db2e1f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 25 May 2020 20:16:42 +1000 Subject: Mesh: skip conversion from edit-mesh to mesh in edit-mode This resolves a performance regression in 2.8x where every edit-mode update performed an edit-mesh to mesh conversion. Now the conversion will be lazily initialized if/when it's required. New BKE_mesh_wrapper_* functions abstract over mesh data access. Currently only edit-mesh and regular meshes are supported. In the future sub-surface meshes may be supported too. --- source/blender/blenkernel/BKE_editmesh_cache.h | 5 + source/blender/blenkernel/BKE_mesh.h | 23 +- source/blender/blenkernel/BKE_modifier.h | 3 + source/blender/blenkernel/CMakeLists.txt | 1 + source/blender/blenkernel/intern/DerivedMesh.c | 52 ++-- source/blender/blenkernel/intern/crazyspace.c | 2 +- source/blender/blenkernel/intern/editmesh.c | 3 +- source/blender/blenkernel/intern/editmesh_cache.c | 44 ++++ source/blender/blenkernel/intern/mesh.c | 24 +- source/blender/blenkernel/intern/mesh_convert.c | 4 + source/blender/blenkernel/intern/mesh_evaluate.c | 16 ++ source/blender/blenkernel/intern/mesh_iterators.c | 272 +++++++++++++++------ source/blender/blenkernel/intern/mesh_wrapper.c | 165 +++++++++++++ source/blender/blenkernel/intern/modifier.c | 35 ++- source/blender/blenkernel/intern/object.c | 3 +- source/blender/bmesh/intern/bmesh_query.c | 44 ++++ source/blender/bmesh/intern/bmesh_query.h | 10 + .../blender/draw/intern/draw_cache_extract_mesh.c | 185 ++++++++++---- source/blender/draw/intern/draw_cache_impl_mesh.c | 26 +- source/blender/editors/space_view3d/view3d_walk.c | 23 +- source/blender/makesdna/DNA_mesh_types.h | 24 +- source/blender/modifiers/intern/MOD_armature.c | 5 + source/blender/modifiers/intern/MOD_cast.c | 7 +- .../modifiers/intern/MOD_correctivesmooth.c | 5 + source/blender/modifiers/intern/MOD_curve.c | 5 + source/blender/modifiers/intern/MOD_displace.c | 5 + .../blender/modifiers/intern/MOD_laplaciandeform.c | 6 + .../blender/modifiers/intern/MOD_laplaciansmooth.c | 5 + source/blender/modifiers/intern/MOD_lattice.c | 5 + source/blender/modifiers/intern/MOD_meshdeform.c | 5 + source/blender/modifiers/intern/MOD_shrinkwrap.c | 5 + source/blender/modifiers/intern/MOD_simpledeform.c | 5 + source/blender/modifiers/intern/MOD_smooth.c | 3 + source/blender/modifiers/intern/MOD_util.c | 11 +- source/blender/modifiers/intern/MOD_warp.c | 5 + source/blender/modifiers/intern/MOD_wave.c | 5 + 36 files changed, 861 insertions(+), 185 deletions(-) create mode 100644 source/blender/blenkernel/intern/mesh_wrapper.c (limited to 'source') diff --git a/source/blender/blenkernel/BKE_editmesh_cache.h b/source/blender/blenkernel/BKE_editmesh_cache.h index c6a2541e0a7..6c812098b2e 100644 --- a/source/blender/blenkernel/BKE_editmesh_cache.h +++ b/source/blender/blenkernel/BKE_editmesh_cache.h @@ -33,6 +33,11 @@ void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, struct EditMe void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, struct EditMeshData *emd); +bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em, + struct EditMeshData *emd, + float min[3], + float max[3]); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index f14b9a30d99..52d458c108d 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -85,12 +85,6 @@ struct Mesh *BKE_mesh_from_bmesh_for_eval_nomain(struct BMesh *bm, const struct CustomData_MeshMasks *cd_mask_extra, const struct Mesh *me_settings); -struct Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap( - struct BMEditMesh *em, - const struct CustomData_MeshMasks *cd_mask_extra, - float (*vertexCos)[3], - const struct Mesh *me_settings); - int poly_find_loop_from_vert(const struct MPoly *poly, const struct MLoop *loopstart, uint vert); int poly_get_adj_loops_from_vert(const struct MPoly *poly, const struct MLoop *mloop, @@ -673,6 +667,23 @@ void BKE_mesh_calc_edges_loose(struct Mesh *mesh); void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select); void BKE_mesh_calc_edges_tessface(struct Mesh *mesh); +/* *** mesh_geomtype.c *** */ +struct Mesh *BKE_mesh_wrapper_from_editmesh_with_coords( + struct BMEditMesh *em, + const struct CustomData_MeshMasks *cd_mask_extra, + float (*vertexCos)[3], + const struct Mesh *me_settings); +struct Mesh *BKE_mesh_wrapper_from_editmesh(struct BMEditMesh *em, + const struct CustomData_MeshMasks *cd_mask_extra, + const struct Mesh *me_settings); +void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me); +bool BKE_mesh_wrapper_minmax(const struct Mesh *me, float min[3], float max[3]); +void BKE_mesh_wrapper_normals_update(struct Mesh *me); + +/* In DerivedMesh.c */ +void BKE_mesh_wrapper_deferred_finalize(struct Mesh *me_eval, + const CustomData_MeshMasks *final_datamask); + /* **** Depsgraph evaluation **** */ void BKE_mesh_eval_geometry(struct Depsgraph *depsgraph, struct Mesh *mesh); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 58c0b6b71e0..a7bf345567f 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -101,6 +101,9 @@ typedef enum { /* For modifiers that use CD_PREVIEW_MCOL for preview. */ eModifierTypeFlag_UsesPreview = (1 << 9), eModifierTypeFlag_AcceptsVertexCosOnly = (1 << 10), + + /** Accepts #BMesh input (without conversion). */ + eModifierTypeFlag_AcceptsBMesh = (1 << 11), } ModifierTypeFlag; /* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 220bafa2187..817fe849eab 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -168,6 +168,7 @@ set(SRC intern/mesh_runtime.c intern/mesh_tangent.c intern/mesh_validate.c + intern/mesh_wrapper.c intern/modifier.c intern/movieclip.c intern/multires.c diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 52fe51afcb2..8f820a873fe 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -90,6 +90,8 @@ static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER; static void mesh_init_origspace(Mesh *mesh); +static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, + const CustomData_MeshMasks *final_datamask); /* -------------------------------------------------------------------- */ @@ -861,6 +863,16 @@ static void mesh_calc_finalize(const Mesh *mesh_input, Mesh *mesh_eval) mesh_eval->edit_mesh = mesh_input->edit_mesh; } +void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval, + const CustomData_MeshMasks *cd_mask_finalize) +{ + if (me_eval->runtime.wrapper_type_finalize & (1 << ME_WRAPPER_TYPE_BMESH)) { + editbmesh_calc_modifier_final_normals(me_eval, cd_mask_finalize); + me_eval->runtime.wrapper_type_finalize &= ~(1 << ME_WRAPPER_TYPE_BMESH); + } + BLI_assert(me_eval->runtime.wrapper_type_finalize == 0); +} + static void mesh_calc_modifiers(struct Depsgraph *depsgraph, Scene *scene, Object *ob, @@ -1391,11 +1403,16 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev return true; } -static void editbmesh_calc_modifier_final_normals(const Mesh *mesh_input, - const CustomData_MeshMasks *final_datamask, - Mesh *mesh_final) +static void editbmesh_calc_modifier_final_normals(Mesh *mesh_final, + const CustomData_MeshMasks *final_datamask) { - const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 || + if (mesh_final->runtime.wrapper_type != ME_WRAPPER_TYPE_MDATA) { + /* Generated at draw time. */ + mesh_final->runtime.wrapper_type_finalize = (1 << mesh_final->runtime.wrapper_type); + return; + } + + const bool do_loop_normals = ((mesh_final->flag & ME_AUTOSMOOTH) != 0 || (final_datamask->lmask & CD_MASK_NORMAL) != 0); /* Some modifiers may need this info from their target (other) object, * simpler to generate it here as well. */ @@ -1501,7 +1518,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, /* Evaluate modifiers up to certain index to get the mesh cage. */ int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); if (r_cage && cageIndex == -1) { - mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap( + mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords( em_input, &final_datamask, NULL, mesh_input); } @@ -1574,12 +1591,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } } else { - mesh_final = BKE_mesh_from_bmesh_for_eval_nomain(em_input->bm, NULL, mesh_input); - ASSERT_IS_VALID_MESH(mesh_final); - - if (deformed_verts) { - BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); - } + mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords( + em_input, NULL, deformed_verts, mesh_input); + deformed_verts = NULL; } /* create an orco derivedmesh in parallel */ @@ -1657,7 +1671,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_mesh_runtime_ensure_edit_data(me_orig); me_orig->runtime.edit_data->vertexCos = MEM_dupallocN(deformed_verts); } - mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap( + mesh_cage = BKE_mesh_wrapper_from_editmesh_with_coords( em_input, &final_datamask, deformed_verts ? MEM_dupallocN(deformed_verts) : NULL, @@ -1689,7 +1703,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } else { /* this is just a copy of the editmesh, no need to calc normals */ - mesh_final = BKE_mesh_from_editmesh_with_coords_thin_wrap( + mesh_final = BKE_mesh_wrapper_from_editmesh_with_coords( em_input, &final_datamask, deformed_verts, mesh_input); deformed_verts = NULL; } @@ -1700,6 +1714,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, /* Add orco coordinates to final and deformed mesh if requested. */ if (final_datamask.vmask & CD_MASK_ORCO) { + /* FIXME(Campbell): avoid the need to convert to mesh data just to add an orco layer. */ + BKE_mesh_wrapper_ensure_mdata(mesh_final); + add_orco_mesh(ob, em_input, mesh_final, mesh_orco, CD_ORCO); } @@ -1707,10 +1724,15 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_id_free(NULL, mesh_orco); } + /* Ensure normals calculation below is correct. */ + BLI_assert((mesh_input->flag & ME_AUTOSMOOTH) == (mesh_final->flag & ME_AUTOSMOOTH)); + BLI_assert(mesh_input->smoothresh == mesh_final->smoothresh); + BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh); + /* Compute normals. */ - editbmesh_calc_modifier_final_normals(mesh_input, &final_datamask, mesh_final); + editbmesh_calc_modifier_final_normals(mesh_final, &final_datamask); if (mesh_cage && (mesh_cage != mesh_final)) { - editbmesh_calc_modifier_final_normals(mesh_input, &final_datamask, mesh_cage); + editbmesh_calc_modifier_final_normals(mesh_cage, &final_datamask); } /* Return final mesh. */ diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index f4acbdca772..6c8438e478e 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -293,7 +293,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra cd_mask_extra = datamasks->mask; BLI_linklist_free((LinkNode *)datamasks, NULL); - me = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, &cd_mask_extra, NULL, me_input); + me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, NULL, me_input); deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts); defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats"); diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 5aaae74e670..c4160d6d253 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -32,6 +32,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_editmesh.h" +#include "BKE_editmesh_cache.h" #include "BKE_lib_id.h" #include "BKE_mesh.h" #include "BKE_mesh_iterators.h" @@ -266,7 +267,7 @@ BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em) float min[3], max[3]; INIT_MINMAX(min, max); if (em->mesh_eval_cage) { - BKE_mesh_minmax(em->mesh_eval_cage, min, max); + BKE_mesh_wrapper_minmax(em->mesh_eval_cage, min, max); } em->bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage"); diff --git a/source/blender/blenkernel/intern/editmesh_cache.c b/source/blender/blenkernel/intern/editmesh_cache.c index 8d3f1e84bcd..5017a48d14e 100644 --- a/source/blender/blenkernel/intern/editmesh_cache.c +++ b/source/blender/blenkernel/intern/editmesh_cache.c @@ -22,11 +22,17 @@ #include "MEM_guardedalloc.h" +#include "BLI_math_vector.h" + #include "DNA_mesh_types.h" #include "BKE_editmesh.h" #include "BKE_editmesh_cache.h" /* own include */ +/* -------------------------------------------------------------------- */ +/** \name Ensure Data (derived from coords) + * \{ */ + void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, EditMeshData *emd) { if (!(emd->vertexCos && (emd->polyNos == NULL))) { @@ -112,3 +118,41 @@ void BKE_editmesh_cache_ensure_poly_centers(BMEditMesh *em, EditMeshData *emd) emd->polyCos = (const float(*)[3])polyCos; } + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Calculate Min/Max + * \{ */ + +bool BKE_editmesh_cache_calc_minmax(struct BMEditMesh *em, + struct EditMeshData *emd, + float min[3], + float max[3]) +{ + BMesh *bm = em->bm; + BMVert *eve; + BMIter iter; + int i; + + if (bm->totvert) { + if (emd->vertexCos) { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + minmax_v3v3_v3(min, max, emd->vertexCos[i]); + } + } + else { + BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { + minmax_v3v3_v3(min, max, eve->co); + } + } + return true; + } + else { + zero_v3(min); + zero_v3(max); + return false; + } +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index aeef287bb87..0d20d25f84c 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -866,26 +866,6 @@ Mesh *BKE_mesh_from_bmesh_for_eval_nomain(BMesh *bm, return mesh; } -/** - * TODO(campbell): support mesh with only an edit-mesh which is lazy initialized. - */ -Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(BMEditMesh *em, - const CustomData_MeshMasks *cd_mask_extra, - float (*vertexCos)[3], - const Mesh *me_settings) -{ - Mesh *me = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, cd_mask_extra, me_settings); - /* Use editmesh directly where possible. */ - me->runtime.is_original = true; - if (vertexCos) { - /* We will own this array in the future. */ - BKE_mesh_vert_coords_apply(me, vertexCos); - MEM_freeN(vertexCos); - me->runtime.is_original = false; - } - return me; -} - BoundBox *BKE_mesh_boundbox_get(Object *ob) { /* This is Object-level data access, @@ -895,7 +875,7 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob) float min[3], max[3]; INIT_MINMAX(min, max); - if (!BKE_mesh_minmax(me, min, max)) { + if (!BKE_mesh_wrapper_minmax(me, min, max)) { min[0] = min[1] = min[2] = -1.0f; max[0] = max[1] = max[2] = 1.0f; } @@ -916,7 +896,7 @@ void BKE_mesh_texspace_calc(Mesh *me) float min[3], max[3]; INIT_MINMAX(min, max); - if (!BKE_mesh_minmax(me, min, max)) { + if (!BKE_mesh_wrapper_minmax(me, min, max)) { min[0] = min[1] = min[2] = -1.0f; max[0] = max[1] = max[2] = 1.0f; } diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 655c70bcf61..f2c84028570 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1076,6 +1076,10 @@ static Mesh *mesh_new_from_mball_object(Object *object) static Mesh *mesh_new_from_mesh(Object *object, Mesh *mesh) { + /* While we could copy this into the new mesh, + * add the data to 'mesh' so future calls to this function don't need to re-convert the data. */ + BKE_mesh_wrapper_ensure_mdata(mesh); + Mesh *mesh_result = NULL; BKE_id_copy_ex(NULL, &mesh->id, diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index f0d19f01aab..433db26ded8 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -46,6 +46,7 @@ #include "BLI_utildefines.h" #include "BKE_customdata.h" +#include "BKE_editmesh_cache.h" #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_multires.h" @@ -396,6 +397,21 @@ void BKE_mesh_ensure_normals(Mesh *mesh) */ void BKE_mesh_ensure_normals_for_display(Mesh *mesh) { + switch ((eMeshWrapperType)mesh->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_MDATA: + /* Run code below. */ + break; + case ME_WRAPPER_TYPE_BMESH: { + struct BMEditMesh *em = mesh->edit_mesh; + EditMeshData *emd = mesh->runtime.edit_data; + if (emd->vertexCos) { + BKE_editmesh_cache_ensure_vert_normals(em, emd); + BKE_editmesh_cache_ensure_poly_normals(em, emd); + } + return; + } + } + float(*poly_nors)[3] = CustomData_get_layer(&mesh->pdata, CD_NORMAL); const bool do_vert_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) != 0; const bool do_poly_normals = (mesh->runtime.cd_dirty_poly & CD_MASK_NORMAL || poly_nors == NULL); diff --git a/source/blender/blenkernel/intern/mesh_iterators.c b/source/blender/blenkernel/intern/mesh_iterators.c index f2ed9456b11..5ecf5ae316d 100644 --- a/source/blender/blenkernel/intern/mesh_iterators.c +++ b/source/blender/blenkernel/intern/mesh_iterators.c @@ -24,6 +24,8 @@ #include "DNA_meshdata_types.h" #include "BKE_customdata.h" +#include "BKE_editmesh.h" +#include "BKE_editmesh_cache.h" #include "BKE_mesh.h" #include "BKE_mesh_iterators.h" @@ -42,23 +44,53 @@ void BKE_mesh_foreach_mapped_vert(Mesh *mesh, void *userData, MeshForeachFlag flag) { - const MVert *mv = mesh->mvert; - const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); - - if (index) { - for (int i = 0; i < mesh->totvert; i++, mv++) { - const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL; - const int orig = *index++; - if (orig == ORIGINDEX_NONE) { - continue; + if (mesh->edit_mesh != NULL) { + BMEditMesh *em = mesh->edit_mesh; + BMesh *bm = em->bm; + BMIter iter; + BMVert *eve; + int i; + if (mesh->runtime.edit_data->vertexCos != NULL) { + const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos; + const float(*vertexNos)[3]; + if (flag & MESH_FOREACH_USE_NORMAL) { + BKE_editmesh_cache_ensure_vert_normals(em, mesh->runtime.edit_data); + vertexNos = mesh->runtime.edit_data->vertexNos; + } + else { + vertexNos = NULL; + } + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? vertexNos[i] : NULL; + func(userData, i, vertexCos[i], no, NULL); + } + } + else { + BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { + const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? eve->no : NULL; + func(userData, i, eve->co, no, NULL); } - func(userData, orig, mv->co, NULL, no); } } else { - for (int i = 0; i < mesh->totvert; i++, mv++) { - const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL; - func(userData, i, mv->co, NULL, no); + const MVert *mv = mesh->mvert; + const int *index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); + + if (index) { + for (int i = 0; i < mesh->totvert; i++, mv++) { + const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL; + const int orig = *index++; + if (orig == ORIGINDEX_NONE) { + continue; + } + func(userData, orig, mv->co, NULL, no); + } + } + else { + for (int i = 0; i < mesh->totvert; i++, mv++) { + const short *no = (flag & MESH_FOREACH_USE_NORMAL) ? mv->no : NULL; + func(userData, i, mv->co, NULL, no); + } } } } @@ -69,22 +101,47 @@ void BKE_mesh_foreach_mapped_edge( void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]), void *userData) { - const MVert *mv = mesh->mvert; - const MEdge *med = mesh->medge; - const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX); + if (mesh->edit_mesh != NULL) { + BMEditMesh *em = mesh->edit_mesh; + BMesh *bm = em->bm; + BMIter iter; + BMEdge *eed; + int i; + if (mesh->runtime.edit_data->vertexCos != NULL) { + const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos; + BM_mesh_elem_index_ensure(bm, BM_VERT); - if (index) { - for (int i = 0; i < mesh->totedge; i++, med++) { - const int orig = *index++; - if (orig == ORIGINDEX_NONE) { - continue; + BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { + func(userData, + i, + vertexCos[BM_elem_index_get(eed->v1)], + vertexCos[BM_elem_index_get(eed->v2)]); + } + } + else { + BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { + func(userData, i, eed->v1->co, eed->v2->co); } - func(userData, orig, mv[med->v1].co, mv[med->v2].co); } } else { - for (int i = 0; i < mesh->totedge; i++, med++) { - func(userData, i, mv[med->v1].co, mv[med->v2].co); + const MVert *mv = mesh->mvert; + const MEdge *med = mesh->medge; + const int *index = CustomData_get_layer(&mesh->edata, CD_ORIGINDEX); + + if (index) { + for (int i = 0; i < mesh->totedge; i++, med++) { + const int orig = *index++; + if (orig == ORIGINDEX_NONE) { + continue; + } + func(userData, orig, mv[med->v1].co, mv[med->v2].co); + } + } + else { + for (int i = 0; i < mesh->totedge; i++, med++) { + func(userData, i, mv[med->v1].co, mv[med->v2].co); + } } } } @@ -99,40 +156,72 @@ void BKE_mesh_foreach_mapped_loop(Mesh *mesh, void *userData, MeshForeachFlag flag) { + /* We can't use dm->getLoopDataLayout(dm) here, * we want to always access dm->loopData, EditDerivedBMesh would * return loop data from bmesh itself. */ - const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? - CustomData_get_layer(&mesh->ldata, CD_NORMAL) : - NULL; + if (mesh->edit_mesh != NULL) { + BMEditMesh *em = mesh->edit_mesh; + BMesh *bm = em->bm; + BMIter iter; + BMFace *efa; - const MVert *mv = mesh->mvert; - const MLoop *ml = mesh->mloop; - const MPoly *mp = mesh->mpoly; - const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); - const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX); - int p_idx, i; - - if (v_index || f_index) { - for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) { - for (i = 0; i < mp->totloop; i++, ml++) { - const int v_idx = v_index ? v_index[ml->v] : ml->v; - const int f_idx = f_index ? f_index[p_idx] : p_idx; + const float(*vertexCos)[3] = mesh->runtime.edit_data->vertexCos; + + /* XXX: investigate using EditMesh data. */ + const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? + CustomData_get_layer(&mesh->ldata, CD_NORMAL) : + NULL; + + int f_idx; + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, f_idx) { + BMLoop *l_iter, *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const BMVert *eve = l_iter->v; + const int v_idx = BM_elem_index_get(eve); const float *no = lnors ? *lnors++ : NULL; - if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) { - continue; - } - func(userData, v_idx, f_idx, mv[ml->v].co, no); - } + func(userData, v_idx, f_idx, vertexCos ? vertexCos[v_idx] : eve->co, no); + } while ((l_iter = l_iter->next) != l_first); } } else { - for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) { - for (i = 0; i < mp->totloop; i++, ml++) { - const int v_idx = ml->v; - const int f_idx = p_idx; - const float *no = lnors ? *lnors++ : NULL; - func(userData, v_idx, f_idx, mv[ml->v].co, no); + const float(*lnors)[3] = (flag & MESH_FOREACH_USE_NORMAL) ? + CustomData_get_layer(&mesh->ldata, CD_NORMAL) : + NULL; + + const MVert *mv = mesh->mvert; + const MLoop *ml = mesh->mloop; + const MPoly *mp = mesh->mpoly; + const int *v_index = CustomData_get_layer(&mesh->vdata, CD_ORIGINDEX); + const int *f_index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX); + int p_idx, i; + + if (v_index || f_index) { + for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) { + for (i = 0; i < mp->totloop; i++, ml++) { + const int v_idx = v_index ? v_index[ml->v] : ml->v; + const int f_idx = f_index ? f_index[p_idx] : p_idx; + const float *no = lnors ? *lnors++ : NULL; + if (ELEM(ORIGINDEX_NONE, v_idx, f_idx)) { + continue; + } + func(userData, v_idx, f_idx, mv[ml->v].co, no); + } + } + } + else { + for (p_idx = 0; p_idx < mesh->totpoly; p_idx++, mp++) { + for (i = 0; i < mp->totloop; i++, ml++) { + const int v_idx = ml->v; + const int f_idx = p_idx; + const float *no = lnors ? *lnors++ : NULL; + func(userData, v_idx, f_idx, mv[ml->v].co, no); + } } } } @@ -145,37 +234,72 @@ void BKE_mesh_foreach_mapped_face_center( void *userData, MeshForeachFlag flag) { - const MVert *mvert = mesh->mvert; - const MPoly *mp = mesh->mpoly; - const MLoop *ml; - float _no_buf[3]; - float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL; - const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX); + if (mesh->edit_mesh != NULL) { + BMEditMesh *em = mesh->edit_mesh; + BMesh *bm = em->bm; + const float(*polyCos)[3]; + const float(*polyNos)[3]; + BMFace *efa; + BMIter iter; + int i; - if (index) { - for (int i = 0; i < mesh->totpoly; i++, mp++) { - const int orig = *index++; - if (orig == ORIGINDEX_NONE) { - continue; + BKE_editmesh_cache_ensure_poly_centers(em, mesh->runtime.edit_data); + polyCos = mesh->runtime.edit_data->polyCos; /* always set */ + + if (flag & MESH_FOREACH_USE_NORMAL) { + BKE_editmesh_cache_ensure_poly_normals(em, mesh->runtime.edit_data); + polyNos = mesh->runtime.edit_data->polyNos; /* maybe NULL */ + } + else { + polyNos = NULL; + } + + if (polyNos) { + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { + const float *no = polyNos[i]; + func(userData, i, polyCos[i], no); } - float cent[3]; - ml = &mesh->mloop[mp->loopstart]; - BKE_mesh_calc_poly_center(mp, ml, mvert, cent); - if (flag & MESH_FOREACH_USE_NORMAL) { - BKE_mesh_calc_poly_normal(mp, ml, mvert, no); + } + else { + BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) { + const float *no = (flag & MESH_FOREACH_USE_NORMAL) ? efa->no : NULL; + func(userData, i, polyCos[i], no); } - func(userData, orig, cent, no); } } else { - for (int i = 0; i < mesh->totpoly; i++, mp++) { - float cent[3]; - ml = &mesh->mloop[mp->loopstart]; - BKE_mesh_calc_poly_center(mp, ml, mvert, cent); - if (flag & MESH_FOREACH_USE_NORMAL) { - BKE_mesh_calc_poly_normal(mp, ml, mvert, no); + const MVert *mvert = mesh->mvert; + const MPoly *mp = mesh->mpoly; + const MLoop *ml; + float _no_buf[3]; + float *no = (flag & MESH_FOREACH_USE_NORMAL) ? _no_buf : NULL; + const int *index = CustomData_get_layer(&mesh->pdata, CD_ORIGINDEX); + + if (index) { + for (int i = 0; i < mesh->totpoly; i++, mp++) { + const int orig = *index++; + if (orig == ORIGINDEX_NONE) { + continue; + } + float cent[3]; + ml = &mesh->mloop[mp->loopstart]; + BKE_mesh_calc_poly_center(mp, ml, mvert, cent); + if (flag & MESH_FOREACH_USE_NORMAL) { + BKE_mesh_calc_poly_normal(mp, ml, mvert, no); + } + func(userData, orig, cent, no); + } + } + else { + for (int i = 0; i < mesh->totpoly; i++, mp++) { + float cent[3]; + ml = &mesh->mloop[mp->loopstart]; + BKE_mesh_calc_poly_center(mp, ml, mvert, cent); + if (flag & MESH_FOREACH_USE_NORMAL) { + BKE_mesh_calc_poly_normal(mp, ml, mvert, no); + } + func(userData, i, cent, no); } - func(userData, i, cent, no); } } } diff --git a/source/blender/blenkernel/intern/mesh_wrapper.c b/source/blender/blenkernel/intern/mesh_wrapper.c new file mode 100644 index 00000000000..fc65be1dd56 --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_wrapper.c @@ -0,0 +1,165 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** \file + * \ingroup bke + * + * The primary purpose of this API is to avoid unnecessary mesh conversion for the final + * output of a modified mesh. + * + * This API handles the case when the modifier stack outputs a mesh which does not have + * #Mesh data (#MPoly, #MLoop, #MEdge, #MVert). + * Currently this is used so the resulting mesh can have #BMEditMesh data, + * postponing the converting until it's needed or avoiding conversion entirely + * which can be an expensive operation. + * Once converted, the meshes type changes to #ME_WRAPPER_TYPE_MDATA, + * although the edit mesh is not cleared. + * + * This API exposes functions that abstract over the different kinds of internal data, + * as well as supporting converting the mesh into regular mesh. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_defaults.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" + +#include "BLI_bitmap.h" +#include "BLI_edgehash.h" +#include "BLI_ghash.h" +#include "BLI_hash.h" +#include "BLI_linklist.h" +#include "BLI_math.h" +#include "BLI_memarena.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_animsys.h" +#include "BKE_editmesh.h" +#include "BKE_editmesh_cache.h" +#include "BKE_global.h" +#include "BKE_idtype.h" +#include "BKE_key.h" +#include "BKE_lib_id.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_object.h" + +#include "PIL_time.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +Mesh *BKE_mesh_wrapper_from_editmesh_with_coords(BMEditMesh *em, + const CustomData_MeshMasks *cd_mask_extra, + float (*vertexCos)[3], + const Mesh *me_settings) +{ + Mesh *me = BKE_id_new_nomain(ID_ME, NULL); + BKE_mesh_copy_settings(me, me_settings); + BKE_mesh_runtime_ensure_edit_data(me); + + me->runtime.wrapper_type = ME_WRAPPER_TYPE_BMESH; + if (cd_mask_extra) { + me->runtime.cd_mask_extra = *cd_mask_extra; + } + + /* Use edit-mesh directly where possible. */ + me->runtime.is_original = true; + me->edit_mesh = MEM_dupallocN(em); + +/* Make sure, we crash if these are ever used. */ +#ifdef DEBUG + me->totvert = INT_MAX; + me->totedge = INT_MAX; + me->totpoly = INT_MAX; + me->totloop = INT_MAX; +#else + me->totvert = 0; + me->totedge = 0; + me->totpoly = 0; + me->totloop = 0; +#endif + + EditMeshData *edit_data = me->runtime.edit_data; + edit_data->vertexCos = vertexCos; + return me; +} + +Mesh *BKE_mesh_wrapper_from_editmesh(BMEditMesh *em, + const CustomData_MeshMasks *cd_mask_extra, + const Mesh *me_settings) +{ + return BKE_mesh_wrapper_from_editmesh_with_coords(em, cd_mask_extra, NULL, me_settings); +} + +void BKE_mesh_wrapper_ensure_mdata(Mesh *me) +{ + if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) { + return; + } + const eMeshWrapperType geom_type_orig = me->runtime.wrapper_type; + me->runtime.wrapper_type = ME_WRAPPER_TYPE_MDATA; + + switch (geom_type_orig) { + case ME_WRAPPER_TYPE_MDATA: { + break; /* Quiet warning. */ + } + case ME_WRAPPER_TYPE_BMESH: { + me->totvert = 0; + me->totedge = 0; + me->totpoly = 0; + me->totloop = 0; + + BLI_assert(me->edit_mesh != NULL); + BLI_assert(me->runtime.edit_data != NULL); + + BMEditMesh *em = me->edit_mesh; + BM_mesh_bm_to_me_for_eval(em->bm, me, &me->runtime.cd_mask_extra); + + EditMeshData *edit_data = me->runtime.edit_data; + if (edit_data->vertexCos) { + BKE_mesh_vert_coords_apply(me, edit_data->vertexCos); + me->runtime.is_original = false; + } + break; + } + } + + if (me->runtime.wrapper_type_finalize) { + BKE_mesh_wrapper_deferred_finalize(me, &me->runtime.cd_mask_extra); + } +} + +bool BKE_mesh_wrapper_minmax(const Mesh *me, float min[3], float max[3]) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_BMESH: + return BKE_editmesh_cache_calc_minmax(me->edit_mesh, me->runtime.edit_data, min, max); + case ME_WRAPPER_TYPE_MDATA: + return BKE_mesh_minmax(me, min, max); + } + BLI_assert(0); +} diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 305acf3a377..6b54a530034 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -50,6 +50,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_appdir.h" #include "BKE_editmesh.h" +#include "BKE_editmesh_cache.h" #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_key.h" @@ -934,6 +935,30 @@ void BKE_modifier_path_init(char *path, int path_maxlen, const char *name) BLI_join_dirfile(path, path_maxlen, G.relbase_valid ? "//" : BKE_tempdir_session(), name); } +/** + * Call when #ModifierTypeInfo.dependsOnNormals callback requests normals. + */ +static void modwrap_dependsOnNormals(Mesh *me) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_BMESH: { + EditMeshData *edit_data = me->runtime.edit_data; + if (edit_data->vertexCos) { + /* Note that 'ensure' is acceptable here since these values aren't modified in-place. + * If that changes we'll need to recalculate. */ + BKE_editmesh_cache_ensure_vert_normals(me->edit_mesh, edit_data); + } + else { + BM_mesh_normals_update(me->edit_mesh->bm); + } + break; + } + case ME_WRAPPER_TYPE_MDATA: + BKE_mesh_calc_normals(me); + break; + } +} + /* wrapper around ModifierTypeInfo.modifyMesh that ensures valid normals */ struct Mesh *BKE_modifier_modify_mesh(ModifierData *md, @@ -943,8 +968,14 @@ struct Mesh *BKE_modifier_modify_mesh(ModifierData *md, const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); BLI_assert(CustomData_has_layer(&me->pdata, CD_NORMAL) == false); + if (me->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { + if ((mti->flags & eModifierTypeFlag_AcceptsBMesh) == 0) { + BKE_mesh_wrapper_ensure_mdata(me); + } + } + if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { - BKE_mesh_calc_normals(me); + modwrap_dependsOnNormals(me); } return mti->modifyMesh(md, ctx, me); } @@ -959,7 +990,7 @@ void BKE_modifier_deform_verts(ModifierData *md, BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false); if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) { - BKE_mesh_calc_normals(me); + modwrap_dependsOnNormals(me); } mti->deformVerts(md, ctx, me, vertexCos, numVerts); } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index d17575195e3..3e2629f8272 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -81,6 +81,7 @@ #include "BKE_displist.h" #include "BKE_duplilist.h" #include "BKE_editmesh.h" +#include "BKE_editmesh_cache.h" #include "BKE_effect.h" #include "BKE_fcurve.h" #include "BKE_fcurve_driver.h" @@ -3089,7 +3090,7 @@ void BKE_object_boundbox_calc_from_mesh(struct Object *ob, struct Mesh *me_eval) INIT_MINMAX(min, max); - if (!BKE_mesh_minmax(me_eval, min, max)) { + if (!BKE_mesh_wrapper_minmax(me_eval, min, max)) { zero_v3(min); zero_v3(max); } diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c index 64950411fed..e000b253000 100644 --- a/source/blender/bmesh/intern/bmesh_query.c +++ b/source/blender/bmesh/intern/bmesh_query.c @@ -1567,6 +1567,41 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq, } } +/** + * A version of BM_loop_calc_face_normal_safe_ex which takes vertex coordinates. + */ +float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l, + const float normal_fallback[3], + float const (*vertexCos)[3], + const float epsilon_sq, + float r_normal[3]) +{ + const int i_prev = BM_elem_index_get(l->prev->v); + const int i_next = BM_elem_index_get(l->next->v); + const int i = BM_elem_index_get(l->v); + + float v1[3], v2[3], v_tmp[3]; + sub_v3_v3v3(v1, vertexCos[i_prev], vertexCos[i]); + sub_v3_v3v3(v2, vertexCos[i_next], vertexCos[i]); + + const float fac = ((v2[0] == 0.0f) ? + ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : + v1[1] / v2[1]) : + v1[0] / v2[0]); + + mul_v3_v3fl(v_tmp, v2, fac); + sub_v3_v3(v_tmp, v1); + if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) { + /* Not co-linear, we can compute cross-product and normalize it into normal. */ + cross_v3_v3v3(r_normal, v1, v2); + return normalize_v3(r_normal); + } + else { + copy_v3_v3(r_normal, normal_fallback); + return 0.0f; + } +} + /** * #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon. * @@ -1577,6 +1612,15 @@ float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal); } +float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l, + const float normal_fallback[3], + float const (*vertexCos)[3], + float r_normal[3]) + +{ + return BM_loop_calc_face_normal_safe_vcos_ex(l, normal_fallback, vertexCos, 1e-5f, r_normal); +} + /** * \brief BM_loop_calc_face_normal * diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h index aaf8191c5db..7e07059d4d8 100644 --- a/source/blender/bmesh/intern/bmesh_query.h +++ b/source/blender/bmesh/intern/bmesh_query.h @@ -142,6 +142,16 @@ float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL( float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL(); float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe_vcos_ex(const BMLoop *l, + const float normal_fallback[3], + float const (*vertexCos)[3], + const float epsilon_sq, + float r_normal[3]) ATTR_NONNULL(); +float BM_loop_calc_face_normal_safe_vcos(const BMLoop *l, + const float normal_fallback[3], + float const (*vertexCos)[3], + float r_normal[3]) ATTR_NONNULL(); + void BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]); void BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 401f5c76a02..cbb5f5f06ff 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -105,6 +105,14 @@ typedef struct MeshRenderData { BMEditMesh *edit_bmesh; BMesh *bm; EditMeshData *edit_data; + + /* For deformed edit-mesh data. */ + /* Use for #ME_WRAPPER_TYPE_BMESH. */ + const float (*bm_vert_coords)[3]; + const float (*bm_vert_normals)[3]; + const float (*bm_poly_normals)[3]; + const float (*bm_poly_centers)[3]; + int *v_origindex, *e_origindex, *p_origindex; int crease_ofs; int bweight_ofs; @@ -151,9 +159,24 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final); mr->bm = me->edit_mesh->bm; mr->edit_bmesh = me->edit_mesh; - mr->edit_data = me->runtime.edit_data; mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage; - bool use_mapped = !do_uvedit && mr->me && !mr->me->runtime.is_original; + mr->edit_data = mr->me->runtime.edit_data; + + if (mr->edit_data) { + EditMeshData *emd = mr->edit_data; + if (emd->vertexCos) { + BKE_editmesh_cache_ensure_vert_normals(mr->edit_bmesh, emd); + BKE_editmesh_cache_ensure_poly_normals(mr->edit_bmesh, emd); + } + + mr->bm_vert_coords = mr->edit_data->vertexCos; + mr->bm_vert_normals = mr->edit_data->vertexNos; + mr->bm_poly_normals = mr->edit_data->polyNos; + mr->bm_poly_centers = mr->edit_data->polyCos; + } + + bool has_mdata = (mr->me->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA); + bool use_mapped = has_mdata && !do_uvedit && mr->me && !mr->me->runtime.is_original; int bm_ensure_types = BM_VERT | BM_EDGE | BM_LOOP | BM_FACE; @@ -184,7 +207,7 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, /* Seems like the mesh_eval_final do not have the right origin indices. * Force not mapped in this case. */ - if (do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) { + if (has_mdata && do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) { // mr->edit_bmesh = NULL; mr->extract_type = MR_EXTRACT_MESH; } @@ -311,12 +334,23 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, /* Use bmface->no instead. */ } if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) { + + const float(*vert_coords)[3] = NULL; + const float(*vert_normals)[3] = NULL; + const float(*poly_normals)[3] = NULL; + + if (mr->edit_data && mr->edit_data->vertexCos) { + vert_coords = mr->bm_vert_coords; + vert_normals = mr->bm_vert_normals; + poly_normals = mr->bm_poly_normals; + } + mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__); int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL); BM_loops_calc_normal_vcos(mr->bm, - NULL, - NULL, - NULL, + vert_coords, + vert_normals, + poly_normals, is_auto_smooth, split_angle, mr->loop_normals, @@ -396,6 +430,42 @@ BLI_INLINE BMVert *bm_original_vert_get(const MeshRenderData *mr, int idx) NULL; } +BLI_INLINE const float *bm_vert_co_get(const MeshRenderData *mr, const BMVert *eve) +{ + const float(*vert_coords)[3] = mr->bm_vert_coords; + if (vert_coords != NULL) { + return vert_coords[BM_elem_index_get(eve)]; + } + else { + UNUSED_VARS(mr); + return eve->co; + } +} + +BLI_INLINE const float *bm_vert_no_get(const MeshRenderData *mr, const BMVert *eve) +{ + const float(*vert_normals)[3] = mr->bm_vert_normals; + if (vert_normals != NULL) { + return vert_normals[BM_elem_index_get(eve)]; + } + else { + UNUSED_VARS(mr); + return eve->co; + } +} + +BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *efa) +{ + const float(*poly_normals)[3] = mr->bm_poly_normals; + if (poly_normals != NULL) { + return poly_normals[BM_elem_index_get(efa)]; + } + else { + UNUSED_VARS(mr); + return efa->no; + } +} + /** \} */ /* ---------------------------------------------------------------------- */ @@ -1480,7 +1550,7 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf) BMVert *eve; int v; BM_ITER_MESH_INDEX (eve, &iter, mr->bm, BM_VERTS_OF_MESH, v) { - data->packed_nor[v] = GPU_normal_convert_i10_v3(eve->no); + data->packed_nor[v] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, eve)); } } else { @@ -1492,14 +1562,11 @@ static void *extract_pos_nor_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_pos_nor_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *_data) +static void extract_pos_nor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data) { MeshExtract_PosNor_Data *data = _data; PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert->pos, loop->v->co); + copy_v3_v3(vert->pos, bm_vert_co_get(mr, loop->v)); vert->nor = data->packed_nor[BM_elem_index_get(loop->v)]; BMFace *efa = loop->f; vert->nor.w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; @@ -1536,8 +1603,8 @@ static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge int l = mr->loop_len + e * 2; MeshExtract_PosNor_Data *data = _data; PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert[0].pos, eed->v1->co); - copy_v3_v3(vert[1].pos, eed->v2->co); + copy_v3_v3(vert[0].pos, bm_vert_co_get(mr, eed->v1)); + copy_v3_v3(vert[1].pos, bm_vert_co_get(mr, eed->v2)); vert[0].nor = data->packed_nor[BM_elem_index_get(eed->v1)]; vert[1].nor = data->packed_nor[BM_elem_index_get(eed->v2)]; } @@ -1561,7 +1628,7 @@ static void extract_pos_nor_lvert_bmesh(const MeshRenderData *mr, int v, BMVert int l = mr->loop_len + mr->edge_loose_len * 2 + v; MeshExtract_PosNor_Data *data = _data; PosNorLoop *vert = data->vbo_data + l; - copy_v3_v3(vert->pos, eve->co); + copy_v3_v3(vert->pos, bm_vert_co_get(mr, eve)); vert->nor = data->packed_nor[BM_elem_index_get(eve)]; } @@ -1627,10 +1694,10 @@ static void extract_lnor_hq_loop_bmesh(const MeshRenderData *mr, int l, BMLoop * normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, mr->loop_normals[l]); } else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) { - normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->v->no); + normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_vert_no_get(mr, loop->v)); } else { - normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, loop->f->no); + normal_float_to_short_v3(&((gpuHQNor *)data)[l].x, bm_face_no_get(mr, loop->f)); } } @@ -1704,10 +1771,10 @@ static void extract_lnor_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loo ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->loop_normals[l]); } else if (BM_elem_flag_test(loop->f, BM_ELEM_SMOOTH)) { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(loop->v->no); + ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_vert_no_get(mr, loop->v)); } else { - ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(loop->f->no); + ((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, loop->f)); } BMFace *efa = loop->f; ((GPUPackedNormal *)data)[l].w = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) ? -1 : 0; @@ -1915,7 +1982,10 @@ static void extract_tan_ex(const MeshRenderData *mr, GPUVertBuf *vbo, const bool if (mr->extract_type == MR_EXTRACT_BMESH) { BMesh *bm = mr->bm; for (int v = 0; v < mr->vert_len; v++) { - copy_v3_v3(orco[v], BM_vert_at_index(bm, v)->co); + const BMVert *eve = BM_vert_at_index(bm, v); + /* Exceptional case where #bm_vert_co_get can be avoided, as we want the original coords. + * not the distorted ones. */ + copy_v3_v3(orco[v], eve->co); } } else { @@ -2301,14 +2371,14 @@ static void *extract_edge_fac_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_edge_fac_loop_bmesh(const MeshRenderData *UNUSED(mr), - int l, - BMLoop *loop, - void *_data) +static void extract_edge_fac_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data) { MeshExtract_EdgeFac_Data *data = (MeshExtract_EdgeFac_Data *)_data; if (BM_edge_is_manifold(loop->e)) { - float ratio = loop_edge_factor_get(loop->f->no, loop->v->co, loop->v->no, loop->next->v->co); + float ratio = loop_edge_factor_get(bm_face_no_get(mr, loop->f), + bm_vert_co_get(mr, loop->v), + bm_vert_no_get(mr, loop->v), + bm_vert_co_get(mr, loop->next->v)); data->vbo_data[l] = ratio * 253 + 1; } else { @@ -3133,7 +3203,7 @@ static void *extract_stretch_angle_init(const MeshRenderData *mr, void *buf) return data; } -static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr), +static void extract_stretch_angle_loop_bmesh(const MeshRenderData *mr, int l, BMLoop *loop, void *_data) @@ -3150,8 +3220,12 @@ static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr), BMLoop *l_next_tmp = loop; luv = BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs); luv_next = BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs); - compute_normalize_edge_vectors( - auv, av, luv->uv, luv_next->uv, l_tmp->v->co, l_next_tmp->v->co); + compute_normalize_edge_vectors(auv, + av, + luv->uv, + luv_next->uv, + bm_vert_co_get(mr, l_tmp->v), + bm_vert_co_get(mr, l_next_tmp->v)); /* Save last edge. */ copy_v2_v2(last_auv, auv[1]); copy_v3_v3(last_av, av[1]); @@ -3167,7 +3241,12 @@ static void extract_stretch_angle_loop_bmesh(const MeshRenderData *UNUSED(mr), else { luv = BM_ELEM_CD_GET_VOID_P(loop, data->cd_ofs); luv_next = BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs); - compute_normalize_edge_vectors(auv, av, luv->uv, luv_next->uv, loop->v->co, l_next->v->co); + compute_normalize_edge_vectors(auv, + av, + luv->uv, + luv_next->uv, + bm_vert_co_get(mr, loop->v), + bm_vert_co_get(mr, l_next->v)); } edituv_get_stretch_angle(auv, av, data->vbo_data + l); } @@ -3307,7 +3386,7 @@ static void statvis_calc_overhang(const MeshRenderData *mr, float *r_overhang) if (mr->extract_type == MR_EXTRACT_BMESH) { int l = 0; BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - float fac = angle_normalized_v3v3(f->no, dir) / (float)M_PI; + float fac = angle_normalized_v3v3(bm_face_no_get(mr, f), dir) / (float)M_PI; fac = overhang_remap(fac, min, max, minmax_irange); for (int i = 0; i < f->len; i++, l++) { r_overhang[l] = fac; @@ -3385,7 +3464,11 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) for (int i = 0; i < mr->tri_len; i++) { BMLoop **ltri = looptris[i]; const int index = BM_elem_index_get(ltri[0]->f); - const float *cos[3] = {ltri[0]->v->co, ltri[1]->v->co, ltri[2]->v->co}; + const float *cos[3] = { + bm_vert_co_get(mr, ltri[0]->v), + bm_vert_co_get(mr, ltri[1]->v), + bm_vert_co_get(mr, ltri[2]->v), + }; float ray_co[3]; float ray_no[3]; @@ -3398,7 +3481,8 @@ static void statvis_calc_thickness(const MeshRenderData *mr, float *r_thickness) BMFace *f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, &dist, NULL, NULL); if (f_hit && dist < face_dists[index]) { - float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); + float angle_fac = fabsf( + dot_v3v3(bm_face_no_get(mr, ltri[0]->f), bm_face_no_get(mr, f_hit))); angle_fac = 1.0f - angle_fac; angle_fac = angle_fac * angle_fac * angle_fac; angle_fac = 1.0f - angle_fac; @@ -3603,8 +3687,17 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) BMesh *bm = em->bm; BMFace *f; + if (mr->bm_vert_coords != NULL) { + BKE_editmesh_cache_ensure_poly_normals(em, mr->edit_data); + + /* Most likely this is already valid, ensure just in case. + * Needed for #BM_loop_calc_face_normal_safe_vcos. */ + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + } + int l = 0; - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + int p = 0; + BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, p) { float fac = -1.0f; if (f->len > 3) { @@ -3613,13 +3706,23 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort) fac = 0.0f; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { + const float *no_face; float no_corner[3]; - BM_loop_calc_face_normal_safe(l_iter, no_corner); + if (mr->bm_vert_coords != NULL) { + no_face = mr->bm_poly_normals[p]; + BM_loop_calc_face_normal_safe_vcos(l_iter, no_face, mr->bm_vert_coords, no_corner); + } + else { + no_face = f->no; + BM_loop_calc_face_normal_safe(l_iter, no_corner); + } + /* simple way to detect (what is most likely) concave */ - if (dot_v3v3(f->no, no_corner) < 0.0f) { + if (dot_v3v3(no_face, no_corner) < 0.0f) { negate_v3(no_corner); } - fac = max_ff(fac, angle_normalized_v3v3(f->no, no_corner)); + fac = max_ff(fac, angle_normalized_v3v3(no_face, no_corner)); + } while ((l_iter = l_iter->next) != l_first); fac *= 2.0f; } @@ -3842,14 +3945,14 @@ static void *extract_fdots_pos_init(const MeshRenderData *mr, void *buf) return vbo->data; } -static void extract_fdots_pos_loop_bmesh(const MeshRenderData *UNUSED(mr), +static void extract_fdots_pos_loop_bmesh(const MeshRenderData *mr, int UNUSED(l), BMLoop *loop, void *data) { float(*center)[3] = (float(*)[3])data; float w = 1.0f / (float)loop->f->len; - madd_v3_v3fl(center[BM_elem_index_get(loop->f)], loop->v->co, w); + madd_v3_v3fl(center[BM_elem_index_get(loop->f)], bm_vert_co_get(mr, loop->v), w); } static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr, @@ -3928,7 +4031,7 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void * nor[f].w = NOR_AND_FLAG_HIDDEN; } else { - nor[f] = GPU_normal_convert_i10_v3(efa->no); + nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa)); /* Select / Active Flag. */ nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : @@ -3946,7 +4049,7 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void * nor[f].w = NOR_AND_FLAG_HIDDEN; } else { - nor[f] = GPU_normal_convert_i10_v3(efa->no); + nor[f] = GPU_normal_convert_i10_v3(bm_face_no_get(mr, efa)); /* Select / Active Flag. */ nor[f].w = (BM_elem_flag_test(efa, BM_ELEM_SELECT) ? ((efa == mr->efa_act) ? NOR_AND_FLAG_ACTIVE : NOR_AND_FLAG_SELECT) : @@ -4171,7 +4274,7 @@ static void *extract_skin_roots_init(const MeshRenderData *mr, void *buf) const MVertSkin *vs = BM_ELEM_CD_GET_VOID_P(eve, cd_ofs); if (vs->flag & MVERT_SKIN_ROOT) { vbo_data->size = (vs->radius[0] + vs->radius[1]) * 0.5f; - copy_v3_v3(vbo_data->local_pos, eve->co); + copy_v3_v3(vbo_data->local_pos, bm_vert_co_get(mr, eve)); vbo_data++; root_len++; } diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 649bcd7bbaa..4488a044187 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -96,11 +96,25 @@ static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *c cd_used->edit_uv = 1; } +BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_MDATA: + return &me->ldata; + break; + case ME_WRAPPER_TYPE_BMESH: + return &me->edit_mesh->bm->ldata; + break; + } + + BLI_assert(0); + return &me->ldata; +} + static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; - const CustomData *cd_ldata = &me_final->ldata; - + const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV); if (layer != -1) { cd_used->uv |= (1 << layer); @@ -110,8 +124,7 @@ static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; - const CustomData *cd_ldata = &me_final->ldata; - + const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV); if (layer != -1) { cd_used->uv |= (1 << layer); @@ -121,8 +134,7 @@ static void mesh_cd_calc_active_mask_uv_layer(const Mesh *me, DRW_MeshCDMask *cd static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used) { const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; - const CustomData *cd_ldata = &me_final->ldata; - + const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL); if (layer != -1) { cd_used->vcol |= (1 << layer); @@ -134,7 +146,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, int gpumat_array_len) { const Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; - const CustomData *cd_ldata = &me_final->ldata; + const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); /* See: DM_vertex_attributes_from_gpu for similar logic */ DRW_MeshCDMask cd_used; diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c index 8ee52756f27..9d6f95552b9 100644 --- a/source/blender/editors/space_view3d/view3d_walk.c +++ b/source/blender/editors/space_view3d/view3d_walk.c @@ -374,16 +374,19 @@ static bool walk_floor_distance_get(RegionView3D *rv3d, mul_v3_v3fl(dvec_tmp, dvec, walk->grid); add_v3_v3(ray_start, dvec_tmp); - ret = ED_transform_snap_object_project_ray(walk->snap_context, - walk->depsgraph, - &(const struct SnapObjectParams){ - .snap_select = SNAP_ALL, - }, - ray_start, - ray_normal, - r_distance, - r_location, - r_normal_dummy); + ret = ED_transform_snap_object_project_ray( + walk->snap_context, + walk->depsgraph, + &(const struct SnapObjectParams){ + .snap_select = SNAP_ALL, + /* Avoid having to convert the edit-mesh to a regular mesh. */ + .use_object_edit_cage = true, + }, + ray_start, + ray_normal, + r_distance, + r_location, + r_normal_dummy); /* artificially scale the distance to the scene size */ *r_distance /= walk->grid; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index dc1a2b5ff1d..029352f3d85 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -112,7 +112,20 @@ typedef struct Mesh_Runtime { * In the future we may leave the mesh-data empty * since its not needed if we can use edit-mesh data. */ char is_original; - char _pad[6]; + + /** #eMeshWrapperType and others. */ + char wrapper_type; + /** + * A type mask from wrapper_type, + * in case there are differences in finalizing logic between types. + */ + char wrapper_type_finalize; + + char _pad[4]; + + /** Needed in case we need to lazily initialize the mesh. */ + CustomData_MeshMasks cd_mask_extra; + } Mesh_Runtime; typedef struct Mesh { @@ -228,6 +241,15 @@ typedef struct TFace { /* **************** MESH ********************* */ +/** #Mesh_Runtime.wrapper_type */ +typedef enum eMeshWrapperType { + /** Use mesh data (#Mesh.mvert,#Mesh.medge, #Mesh.mloop, #Mesh.mpoly). */ + ME_WRAPPER_TYPE_MDATA = 0, + /** Use edit-mesh data (#Mesh.#edit_mesh, #Mesh_Runtime.edit_data). */ + ME_WRAPPER_TYPE_BMESH = 1, + /* ME_WRAPPER_TYPE_SUBD = 2, */ /* TODO */ +} eMeshWrapperType; + /* texflag */ enum { ME_AUTOSPACE = 1, diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 29d456e5126..99ce447236b 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -162,6 +162,11 @@ static void deformVertsEM(ModifierData *md, ArmatureModifierData *amd = (ArmatureModifierData *)md; Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + MOD_previous_vcos_store(md, vertexCos); /* if next modifier needs original vertices */ armature_deform_verts(amd->object, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index 5f2043d8c09..ef8530557d7 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -502,10 +502,15 @@ static void deformVertsEM(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); } - if (mesh_src) { + if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) { BLI_assert(mesh_src->totvert == numVerts); } + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + if (cmd->type == MOD_CAST_TYPE_CUBOID) { cuboid_do(cmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 6224cf6b1fc..3b2268ea14d 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -756,6 +756,11 @@ static void deformVertsEM(ModifierData *md, Mesh *mesh_src = MOD_deform_mesh_eval_get( ctx->object, editData, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + correctivesmooth_modifier_do( md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (uint)numVerts, editData); diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index 238c8223799..eec87a918ec 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -142,6 +142,11 @@ static void deformVertsEM(ModifierData *md, { Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + deformVerts(md, ctx, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 514ea185ede..0cb882d0532 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -407,6 +407,11 @@ static void deformVertsEM(ModifierData *md, Mesh *mesh_src = MOD_deform_mesh_eval_get( ctx->object, editData, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + displaceModifier_do((DisplaceModifierData *)md, ctx, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index 095ca95594b..0ca8bc55fb8 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -35,6 +35,7 @@ #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_lib_id.h" +#include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_runtime.h" #include "BKE_particle.h" @@ -783,6 +784,11 @@ static void deformVertsEM(ModifierData *md, Mesh *mesh_src = MOD_deform_mesh_eval_get( ctx->object, editData, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + LaplacianDeformModifier_do( (LaplacianDeformModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts); diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 2fefca68bad..643afc5b5fc 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -559,6 +559,11 @@ static void deformVertsEM(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + laplaciansmoothModifier_do( (LaplacianSmoothModifierData *)md, ctx->object, mesh_src, vertexCos, numVerts); diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 8dd507d51a4..0a7aa006fcc 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -125,6 +125,11 @@ static void deformVertsEM(ModifierData *md, struct Mesh *mesh_src = MOD_deform_mesh_eval_get( ctx->object, em, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + deformVerts(md, ctx, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index c5ed6363415..57b5f3891b2 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -479,6 +479,11 @@ static void deformVertsEM(ModifierData *md, Mesh *mesh_src = MOD_deform_mesh_eval_get( ctx->object, editData, mesh, NULL, numVerts, false, false); + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + meshdeformModifier_do(md, ctx, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index bb8519b01ea..11dc0a92769 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -142,6 +142,11 @@ static void deformVertsEM(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); } + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + struct MDeformVert *dvert = NULL; int defgrp_index = -1; if (swmd->vgroup_name[0] != '\0') { diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 0bd16a318ae..a81b42905e3 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -440,6 +440,11 @@ static void deformVertsEM(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); } + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + SimpleDeformModifier_do(sdmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 5b13bee7dac..7ac6690e3a7 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -216,6 +216,9 @@ static void deformVertsEM(ModifierData *md, /* mesh_src is needed for vgroups, and taking edges into account. */ mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); + /* TODO(campbell): use edit-mode data only (remove this line). */ + BKE_mesh_wrapper_ensure_mdata(mesh_src); + smoothModifier_do(smd, ctx->object, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index bd453c24a31..4999c77c355 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -196,7 +196,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, } else if (ob->type == OB_MESH) { if (em) { - mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL, ob->data); + mesh = BKE_mesh_wrapper_from_editmesh_with_coords(em, NULL, vertexCos, ob->data); } else { /* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether @@ -209,9 +209,12 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, mesh->runtime.deformed_only = 1; } + if (em != NULL) { + /* pass */ + } /* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether * we really need vertexCos here. */ - if (vertexCos) { + else if (vertexCos) { BKE_mesh_vert_coords_apply(mesh, vertexCos); mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL; } @@ -241,7 +244,9 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob, } } - BLI_assert(mesh == NULL || mesh->totvert == num_verts); + if (mesh && mesh->runtime.wrapper_type == ME_WRAPPER_TYPE_MDATA) { + BLI_assert(mesh->totvert == num_verts); + } return mesh; } diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 458e2d0caea..692f0ca18f0 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -381,6 +381,11 @@ static void deformVertsEM(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, em, mesh, NULL, numVerts, false, false); } + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + warpModifier_do(wmd, ctx, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index fc4b65a7e5c..90d9f451f75 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -353,6 +353,11 @@ static void deformVertsEM(ModifierData *md, mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); } + /* TODO(Campbell): use edit-mode data only (remove this line). */ + if (mesh_src != NULL) { + BKE_mesh_wrapper_ensure_mdata(mesh_src); + } + waveModifier_do(wmd, ctx, ctx->object, mesh_src, vertexCos, numVerts); if (!ELEM(mesh_src, NULL, mesh)) { -- cgit v1.2.3