diff options
35 files changed, 365 insertions, 276 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 269d90b868e..1801c1ee1c9 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -399,7 +399,6 @@ bool editbmesh_modifier_is_enabled(struct Scene *scene, void makeDerivedMesh(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, - struct BMEditMesh *em, const struct CustomData_MeshMasks *dataMask); void DM_calc_loop_tangents(DerivedMesh *dm, diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 5be06dcc5c3..1da7ae3da8a 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -62,14 +62,6 @@ typedef struct BMEditMesh { struct BMLoop *(*looptris)[3]; int tottri; - struct Mesh *mesh_eval_final, *mesh_eval_cage; - - /** Cached cage bounding box of `mesh_eval_cage` for selection. */ - struct BoundBox *bb_cage; - - /** Evaluated mesh data-mask. */ - CustomData_MeshMasks lastDataMask; - /** Selection mode (#SCE_SELECT_VERTEX, #SCE_SELECT_EDGE & #SCE_SELECT_FACE). */ short selectmode; /** The active material (assigned to newly created faces). */ @@ -121,7 +113,6 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em); * don't add NULL data check here. caller must do that */ BMEditMesh *BKE_editmesh_from_object(struct Object *ob); -void BKE_editmesh_free_derived_caches(BMEditMesh *em); /** * \note Does not free the #BMEditMesh struct itself. */ @@ -145,7 +136,7 @@ void BKE_editmesh_lnorspace_update(BMEditMesh *em, struct Mesh *me); * If auto-smooth not already set, set it. */ void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, struct Mesh *me); -struct BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em); +struct BoundBox *BKE_editmesh_cage_boundbox_get(struct Object *object, BMEditMesh *em); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 6554a9c72aa..e1c706a82dc 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -119,6 +119,9 @@ void BKE_mesh_looptri_get_real_edges(const struct Mesh *mesh, void BKE_mesh_free_data_for_undo(struct Mesh *me); void BKE_mesh_clear_geometry(struct Mesh *me); struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name); + +void BKE_mesh_free_editmesh(struct Mesh *mesh); + /** * A version of #BKE_mesh_copy_parameters that is intended for evaluated output * (the modifier stack for example). diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index da8dba0c86b..99758f4ad78 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -530,6 +530,9 @@ struct Mesh *BKE_object_get_pre_modified_mesh(const struct Object *object); */ struct Mesh *BKE_object_get_original_mesh(const struct Object *object); +struct Mesh *BKE_object_get_editmesh_eval_final(const struct Object *object); +struct Mesh *BKE_object_get_editmesh_eval_cage(const struct Object *object); + /* Lattice accessors. * These functions return either the regular lattice, or the edit-mode lattice, * whichever is currently in use. */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 13131c24eda..d0d19ff199d 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -1769,17 +1769,6 @@ static void mesh_build_data(struct Depsgraph *depsgraph, const CustomData_MeshMasks *dataMask, const bool need_mapping) { - BLI_assert(ob->type == OB_MESH); - - /* Evaluated meshes aren't supposed to be created on original instances. If you do, - * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ - BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); - - BKE_object_free_derived_caches(ob); - if (DEG_is_active(depsgraph)) { - BKE_sculpt_update_object_before_eval(ob); - } - #if 0 /* XXX This is already taken care of in mesh_calc_modifiers()... */ if (need_mapping) { /* Also add the flag so that it is recorded in lastDataMask. */ @@ -1846,15 +1835,7 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph, BMEditMesh *em, CustomData_MeshMasks *dataMask) { - BLI_assert(obedit->id.tag & LIB_TAG_COPIED_ON_WRITE); - - BKE_object_free_derived_caches(obedit); - if (DEG_is_active(depsgraph)) { - BKE_sculpt_update_object_before_eval(obedit); - } - - BKE_editmesh_free_derived_caches(em); - + Mesh *mesh = static_cast<Mesh *>(obedit->data); Mesh *me_cage; Mesh *me_final; GeometrySet *non_mesh_components; @@ -1862,13 +1843,33 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph, editbmesh_calc_modifiers( depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final, &non_mesh_components); - em->mesh_eval_final = me_final; - em->mesh_eval_cage = me_cage; + /* The modifier stack result is expected to share edit mesh pointer with the input. + * This is similar `mesh_calc_finalize()`. */ + BKE_mesh_free_editmesh(me_final); + BKE_mesh_free_editmesh(me_cage); + me_final->edit_mesh = me_cage->edit_mesh = em; + + /* Object has edit_mesh but is not in edit mode (object shares mesh datablock with another object + * with is in edit mode). + * Convert edit mesh to mesh until the draw manager can draw mesh wrapper which is not in the + * edit mode. */ + if (!(obedit->mode & OB_MODE_EDIT)) { + BKE_mesh_wrapper_ensure_mdata(me_final); + if (me_final != me_cage) { + BKE_mesh_wrapper_ensure_mdata(me_cage); + } + } + + const bool is_mesh_eval_owned = (me_final != mesh->runtime.mesh_eval); + BKE_object_eval_assign_data(obedit, &me_final->id, is_mesh_eval_owned); + + obedit->runtime.editmesh_eval_cage = me_cage; + obedit->runtime.geometry_set_eval = non_mesh_components; - BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final); + BKE_object_boundbox_calc_from_mesh(obedit, me_final); - em->lastDataMask = *dataMask; + obedit->runtime.last_data_mask = *dataMask; } static void object_get_datamask(const Depsgraph *depsgraph, @@ -1924,9 +1925,25 @@ static void object_get_datamask(const Depsgraph *depsgraph, void makeDerivedMesh(struct Depsgraph *depsgraph, Scene *scene, Object *ob, - BMEditMesh *em, const CustomData_MeshMasks *dataMask) { + BLI_assert(ob->type == OB_MESH); + + /* Evaluated meshes aren't supposed to be created on original instances. If you do, + * they aren't cleaned up properly on mode switch, causing crashes, e.g T58150. */ + BLI_assert(ob->id.tag & LIB_TAG_COPIED_ON_WRITE); + + BKE_object_free_derived_caches(ob); + if (DEG_is_active(depsgraph)) { + BKE_sculpt_update_object_before_eval(ob); + } + + /* NOTE: Access the `edit_mesh` after freeing the derived caches, so that `ob->data` is restored + * to the pre-evaluated state. This is because the evaluated state is not necessarily sharing the + * `edit_mesh` pointer with the input. For example, if the object is first evaluated in the + * object mode, and then user in another scene moves object to edit mode. */ + BMEditMesh *em = ((Mesh *)ob->data)->edit_mesh; + bool need_mapping; CustomData_MeshMasks cddata_masks = *dataMask; object_get_datamask(depsgraph, ob, &cddata_masks, &need_mapping); @@ -1965,8 +1982,9 @@ Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph, !CustomData_MeshMasks_are_matching(&(ob->runtime.last_data_mask), &cddata_masks) || (need_mapping && !ob->runtime.last_need_mapping)) { CustomData_MeshMasks_update(&cddata_masks, &ob->runtime.last_data_mask); - mesh_build_data( - depsgraph, scene, ob, &cddata_masks, need_mapping || ob->runtime.last_need_mapping); + + makeDerivedMesh(depsgraph, scene, ob, dataMask); + mesh_eval = BKE_object_get_evaluated_mesh(ob); } @@ -1981,6 +1999,15 @@ Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph, Object *ob, const CustomData_MeshMasks *dataMask) { + BMEditMesh *em = ((Mesh *)ob->data)->edit_mesh; + if (em != nullptr) { + /* There is no such a concept as deformed mesh in edit mode. + * Explicitly disallow this request so that the evaluated result is not modified with evaluated + * result from the wrong mode. */ + BLI_assert_msg(0, "Request of derformed mesh of object which is in edit mode"); + return nullptr; + } + /* This function isn't thread-safe and can't be used during evaluation. */ BLI_assert(DEG_is_evaluating(depsgraph) == false); @@ -2055,12 +2082,12 @@ Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph, */ object_get_datamask(depsgraph, obedit, &cddata_masks, nullptr); - if (!em->mesh_eval_cage || - !CustomData_MeshMasks_are_matching(&(em->lastDataMask), &cddata_masks)) { + if (!obedit->runtime.editmesh_eval_cage || + !CustomData_MeshMasks_are_matching(&(obedit->runtime.last_data_mask), &cddata_masks)) { editbmesh_build_data(depsgraph, scene, obedit, em, &cddata_masks); } - return em->mesh_eval_cage; + return obedit->runtime.editmesh_eval_cage; } Mesh *editbmesh_get_eval_cage_from_orig(struct Depsgraph *depsgraph, diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 6bbb9957b03..9408b9190ae 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -109,7 +109,7 @@ float (*BKE_crazyspace_get_mapped_editverts(struct Depsgraph *depsgraph, Object /* disable subsurf temporal, get mapped cos, and enable it */ if (modifiers_disable_subsurf_temporary(scene_eval, obedit_eval)) { /* need to make new derivemesh */ - makeDerivedMesh(depsgraph, scene_eval, obedit_eval, editmesh_eval, &CD_MASK_BAREMESH); + makeDerivedMesh(depsgraph, scene_eval, obedit_eval, &CD_MASK_BAREMESH); } /* now get the cage */ diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 6ef811c46c7..0774a1a3d88 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -39,6 +39,8 @@ #include "BKE_mesh_wrapper.h" #include "BKE_object.h" +#include "DEG_depsgraph_query.h" + BMEditMesh *BKE_editmesh_create(BMesh *bm) { BMEditMesh *em = MEM_callocN(sizeof(BMEditMesh), __func__); @@ -51,9 +53,6 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em) BMEditMesh *em_copy = MEM_callocN(sizeof(BMEditMesh), __func__); *em_copy = *em; - em_copy->mesh_eval_cage = em_copy->mesh_eval_final = NULL; - em_copy->bb_cage = NULL; - em_copy->bm = BM_mesh_copy(em->bm); /* The tessellation is NOT calculated on the copy here, @@ -194,22 +193,8 @@ void BKE_editmesh_looptri_and_normals_calc_with_partial(BMEditMesh *em, }); } -void BKE_editmesh_free_derived_caches(BMEditMesh *em) -{ - if (em->mesh_eval_cage) { - BKE_id_free(NULL, em->mesh_eval_cage); - } - if (em->mesh_eval_final && em->mesh_eval_final != em->mesh_eval_cage) { - BKE_id_free(NULL, em->mesh_eval_final); - } - em->mesh_eval_cage = em->mesh_eval_final = NULL; - - MEM_SAFE_FREE(em->bb_cage); -} - void BKE_editmesh_free_data(BMEditMesh *em) { - BKE_editmesh_free_derived_caches(em); if (em->looptris) { MEM_freeN(em->looptris); @@ -283,13 +268,15 @@ const float (*BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph *r_is_alloc = false; Mesh *me = ob->data; + Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object_eval); if ((me->runtime.edit_data != NULL) && (me->runtime.edit_data->vertexCos != NULL)) { /* Deformed, and we have deformed coords already. */ coords = me->runtime.edit_data->vertexCos; } - else if ((em->mesh_eval_final != NULL) && - (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) { + else if ((editmesh_eval_final != NULL) && + (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) { /* If this is an edit-mesh type, leave NULL as we can use the vertex coords. */ } else { @@ -334,18 +321,18 @@ void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, Mesh *me) } } -BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em) +BoundBox *BKE_editmesh_cage_boundbox_get(struct Object *object, BMEditMesh *UNUSED(em)) { - if (em->bb_cage == NULL) { + if (object->runtime.editmesh_bb_cage == NULL) { float min[3], max[3]; INIT_MINMAX(min, max); - if (em->mesh_eval_cage) { - BKE_mesh_wrapper_minmax(em->mesh_eval_cage, min, max); + if (object->runtime.editmesh_eval_cage) { + BKE_mesh_wrapper_minmax(object->runtime.editmesh_eval_cage, min, max); } - em->bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage"); - BKE_boundbox_init_from_minmax(em->bb_cage, min, max); + object->runtime.editmesh_bb_cage = MEM_callocN(sizeof(BoundBox), "BMEditMesh.bb_cage"); + BKE_boundbox_init_from_minmax(object->runtime.editmesh_bb_cage, min, max); } - return em->bb_cage; + return object->runtime.editmesh_bb_cage; } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index d6035887790..15469f910b4 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -720,8 +720,9 @@ static ID *get_evaluated_object_data_with_materials(Object *ob) /* Meshes in edit mode need special handling. */ if (ob->type == OB_MESH && ob->mode == OB_MODE_EDIT) { Mesh *mesh = ob->data; - if (mesh->edit_mesh && mesh->edit_mesh->mesh_eval_final) { - data = &mesh->edit_mesh->mesh_eval_final->id; + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob); + if (mesh->edit_mesh && editmesh_eval_final) { + data = &editmesh_eval_final->id; } } return data; diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 9b0cf17a424..73fe279552d 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -173,19 +173,26 @@ static void mesh_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int BKE_mesh_assert_normals_dirty_or_calculated(mesh_dst); } +void BKE_mesh_free_editmesh(struct Mesh *mesh) +{ + if (mesh->edit_mesh == nullptr) { + return; + } + + if (mesh->edit_mesh->is_shallow_copy == false) { + BKE_editmesh_free_data(mesh->edit_mesh); + } + MEM_freeN(mesh->edit_mesh); + mesh->edit_mesh = nullptr; +} + static void mesh_free_data(ID *id) { Mesh *mesh = (Mesh *)id; BLI_freelistN(&mesh->vertex_group_names); - if (mesh->edit_mesh) { - if (mesh->edit_mesh->is_shallow_copy == false) { - BKE_editmesh_free_data(mesh->edit_mesh); - } - MEM_freeN(mesh->edit_mesh); - mesh->edit_mesh = nullptr; - } + BKE_mesh_free_editmesh(mesh); BKE_mesh_runtime_free_data(mesh); mesh_clear_geometry(mesh); diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index cbc772d93a6..7d5f156040d 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -1102,8 +1102,11 @@ static Mesh *mesh_new_from_mesh_object(Depsgraph *depsgraph, Mesh *mesh_input = (Mesh *)object->data; /* If we are in edit mode, use evaluated mesh from edit structure, matching to what * viewport is using for visualization. */ - if (mesh_input->edit_mesh != nullptr && mesh_input->edit_mesh->mesh_eval_final) { - mesh_input = mesh_input->edit_mesh->mesh_eval_final; + if (mesh_input->edit_mesh != nullptr) { + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object); + if (editmesh_eval_final != nullptr) { + mesh_input = editmesh_eval_final; + } } return mesh_new_from_mesh(object, mesh_input); } diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 3f9faa415cb..e1fd8ff45d1 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -1036,8 +1036,11 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval, BMEditMesh *em = BKE_editmesh_from_object(ob_eval); /* 'em' might not exist yet in some cases, just after loading a .blend file, see T57878. */ if (em != NULL) { - me = (get_cage_mesh && em->mesh_eval_cage != NULL) ? em->mesh_eval_cage : - em->mesh_eval_final; + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval); + Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval); + + me = (get_cage_mesh && editmesh_eval_cage != NULL) ? editmesh_eval_cage : + editmesh_eval_final; } } if (me == NULL) { diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc index d510c9b06dc..3fa380d2519 100644 --- a/source/blender/blenkernel/intern/object.cc +++ b/source/blender/blenkernel/intern/object.cc @@ -1846,6 +1846,12 @@ void BKE_object_free_derived_caches(Object *ob) object_update_from_subsurf_ccg(ob); + if (ob->runtime.editmesh_eval_cage && + ob->runtime.editmesh_eval_cage != reinterpret_cast<Mesh *>(ob->runtime.data_eval)) { + BKE_mesh_eval_delete(ob->runtime.editmesh_eval_cage); + } + ob->runtime.editmesh_eval_cage = nullptr; + if (ob->runtime.data_eval != nullptr) { if (ob->runtime.is_data_eval_owned) { ID *data_eval = ob->runtime.data_eval; @@ -1885,6 +1891,8 @@ void BKE_object_free_derived_caches(Object *ob) BKE_geometry_set_free(ob->runtime.geometry_set_eval); ob->runtime.geometry_set_eval = nullptr; } + + MEM_SAFE_FREE(ob->runtime.editmesh_bb_cage); } void BKE_object_free_caches(Object *object) @@ -3390,7 +3398,8 @@ static void give_parvert(Object *par, int nr, float vec[3]) if (par->type == OB_MESH) { Mesh *me = (Mesh *)par->data; BMEditMesh *em = me->edit_mesh; - Mesh *me_eval = (em) ? em->mesh_eval_final : BKE_object_get_evaluated_mesh(par); + Mesh *me_eval = (em) ? BKE_object_get_editmesh_eval_final(par) : + BKE_object_get_evaluated_mesh(par); if (me_eval) { int count = 0; @@ -4553,6 +4562,33 @@ Mesh *BKE_object_get_original_mesh(const Object *object) return result; } +Mesh *BKE_object_get_editmesh_eval_final(const Object *object) +{ + BLI_assert(!DEG_is_original_id(&object->id)); + BLI_assert(object->type == OB_MESH); + + const Mesh *mesh = static_cast<const Mesh *>(object->data); + if (mesh->edit_mesh == nullptr) { + /* Heppens when requesting material of evaluated 3d font obejct: the evaluated object get + * converted to mesh, and it does not have edit mesh. */ + return nullptr; + } + + return reinterpret_cast<Mesh *>(object->runtime.data_eval); +} + +Mesh *BKE_object_get_editmesh_eval_cage(const Object *object) +{ + BLI_assert(!DEG_is_original_id(&object->id)); + BLI_assert(object->type == OB_MESH); + + const Mesh *mesh = static_cast<const Mesh *>(object->data); + BLI_assert(mesh->edit_mesh != nullptr); + UNUSED_VARS_NDEBUG(mesh); + + return object->runtime.editmesh_eval_cage; +} + Lattice *BKE_object_get_lattice(const Object *object) { ID *data = (ID *)object->data; diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index 5dcb753abf4..3082d6f25f3 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -371,7 +371,7 @@ static const Mesh *mesh_data_from_duplicator_object(Object *ob, if (em != nullptr) { /* Note that this will only show deformation if #eModifierMode_OnCage is enabled. * We could change this but it matches 2.7x behavior. */ - me_eval = em->mesh_eval_cage; + me_eval = BKE_object_get_editmesh_eval_cage(ob); if ((me_eval == nullptr) || (me_eval->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) { EditMeshData *emd = me_eval ? me_eval->runtime.edit_data : nullptr; diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 904fe9be51f..1a208355870 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -160,12 +160,6 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o /* includes all keys and modifiers */ switch (ob->type) { case OB_MESH: { -#if 0 - BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL; -#else - BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? ((Mesh *)ob->data)->edit_mesh : NULL; -#endif - CustomData_MeshMasks cddata_masks = scene->customdata_mask; CustomData_MeshMasks_update(&cddata_masks, &CD_MASK_BAREMESH); /* Custom attributes should not be removed automatically. They might be used by the render @@ -192,12 +186,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o cddata_masks.lmask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; cddata_masks.vmask |= CD_MASK_ORCO | CD_MASK_PROP_COLOR; } - if (em) { - makeDerivedMesh(depsgraph, scene, ob, em, &cddata_masks); /* was CD_MASK_BAREMESH */ - } - else { - makeDerivedMesh(depsgraph, scene, ob, NULL, &cddata_masks); - } + makeDerivedMesh(depsgraph, scene, ob, &cddata_masks); /* was CD_MASK_BAREMESH */ break; } case OB_ARMATURE: diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index b1204c9366c..851d0bcf000 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -898,6 +898,29 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode if (!deg_copy_on_write_is_needed(id_orig)) { return id_cow; } + + /* When updating object data in edit-mode, don't request COW update since this will duplicate + * all object data which is unnecessary when the edit-mode data is used for calculating + * modifiers. + * + * TODO: Investigate modes besides edit-mode. */ + if (check_datablock_expanded(id_cow)) { + const ID_Type id_type = GS(id_orig->name); + if (OB_DATA_SUPPORT_EDITMODE(id_type) && BKE_object_data_is_in_editmode(id_orig)) { + /* Make sure pointers in the edit mode data are updated in the copy. + * This allows depsgraph to pick up changes made in another context after it has been + * evaluated. Consider the following scenario: + * + * - ObjectA in SceneA is using Mesh. + * - ObjectB in SceneB is using Mesh (same exact datablock). + * - Depsgraph of SceneA is evaluated. + * - Depsgraph of SceneB is evaluated. + * - User enters edit mode of ObjectA in SceneA. */ + update_edit_mode_pointers(depsgraph, id_orig, id_cow); + return id_cow; + } + } + RuntimeBackup backup(depsgraph); backup.init_from_id(id_cow); deg_free_copy_on_write_datablock(id_cow); diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index 8fd28dfc497..f7acd8c72c3 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -163,23 +163,6 @@ struct ComponentNode : public Node { DEG_COMPONENT_NODE_DECLARE; \ } -/* When updating object data in edit-mode, don't request COW update since this will duplicate - * all object data which is unnecessary when the edit-mode data is used for calculating modifiers. - * - * TODO: Investigate modes besides edit-mode. */ -#define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_OBDATA_IN_EDIT_MODE(name) \ - struct name##ComponentNode : public ComponentNode { \ - DEG_COMPONENT_NODE_DECLARE; \ - virtual bool need_tag_cow_before_update() override \ - { \ - if (OB_DATA_SUPPORT_EDITMODE(owner->id_type) && \ - BKE_object_data_is_in_editmode(owner->id_orig)) { \ - return false; \ - } \ - return true; \ - } \ - } - #define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(name) \ struct name##ComponentNode : public ComponentNode { \ DEG_COMPONENT_NODE_DECLARE; \ @@ -202,7 +185,7 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(Animation); DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(BatchCache); DEG_COMPONENT_NODE_DECLARE_GENERIC(Cache); DEG_COMPONENT_NODE_DECLARE_GENERIC(CopyOnWrite); -DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_OBDATA_IN_EDIT_MODE(Geometry); +DEG_COMPONENT_NODE_DECLARE_GENERIC(Geometry); DEG_COMPONENT_NODE_DECLARE_GENERIC(ImageAnimation); DEG_COMPONENT_NODE_DECLARE_GENERIC(LayerCollections); DEG_COMPONENT_NODE_DECLARE_GENERIC(Particles); diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index 668a1255843..4029f1237e8 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -667,7 +667,7 @@ static void drw_shgroup_bone_custom_solid(ArmatureDrawContext *ctx, /* TODO(fclem): arg... less than ideal but we never iter on this object * to assure batch cache is valid. */ - DRW_mesh_batch_cache_validate(mesh); + DRW_mesh_batch_cache_validate(custom, mesh); struct GPUBatch *surf = DRW_mesh_batch_cache_get_surface(mesh); struct GPUBatch *edges = DRW_mesh_batch_cache_get_edge_detection(mesh, NULL); @@ -715,7 +715,7 @@ static void drw_shgroup_bone_custom_wire(ArmatureDrawContext *ctx, } /* TODO(fclem): arg... less than ideal but we never iter on this object * to assure batch cache is valid. */ - DRW_mesh_batch_cache_validate(mesh); + DRW_mesh_batch_cache_validate(custom, mesh); struct GPUBatch *geom = DRW_mesh_batch_cache_get_all_edges(mesh); if (geom) { diff --git a/source/blender/draw/engines/overlay/overlay_edit_mesh.c b/source/blender/draw/engines/overlay/overlay_edit_mesh.c index 3a2871249a2..ad929cc0835 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_mesh.c +++ b/source/blender/draw/engines/overlay/overlay_edit_mesh.c @@ -28,6 +28,7 @@ #include "BKE_customdata.h" #include "BKE_editmesh.h" +#include "BKE_object.h" #include "draw_cache_impl.h" #include "draw_manager_text.h" @@ -229,7 +230,10 @@ static void overlay_edit_mesh_add_ob_to_pass(OVERLAY_PrivateData *pd, Object *ob Mesh *me = (Mesh *)ob->data; BMEditMesh *embm = me->edit_mesh; if (embm) { - has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final); + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob); + Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob); + + has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final); has_skin_roots = CustomData_get_offset(&embm->bm->vdata, CD_MVERT_SKIN) != -1; } diff --git a/source/blender/draw/engines/overlay/overlay_edit_uv.c b/source/blender/draw/engines/overlay/overlay_edit_uv.c index 983df1ceac8..f51df908fbf 100644 --- a/source/blender/draw/engines/overlay/overlay_edit_uv.c +++ b/source/blender/draw/engines/overlay/overlay_edit_uv.c @@ -412,7 +412,7 @@ void OVERLAY_edit_uv_cache_init(OVERLAY_Data *vedata) draw_ctx->view_layer, NULL, &objects_len, draw_ctx->object_mode); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { Object *object_eval = DEG_get_evaluated_object(draw_ctx->depsgraph, objects[ob_index]); - DRW_mesh_batch_cache_validate((Mesh *)object_eval->data); + DRW_mesh_batch_cache_validate(object_eval, (Mesh *)object_eval->data); overlay_edit_uv_cache_populate(vedata, object_eval); } MEM_freeN(objects); @@ -441,22 +441,22 @@ static void overlay_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob) if (has_active_edit_uvmap) { if (pd->edit_uv.do_uv_overlay) { - geom = DRW_mesh_batch_cache_get_edituv_edges(ob->data); + geom = DRW_mesh_batch_cache_get_edituv_edges(ob, ob->data); if (geom) { DRW_shgroup_call_obmat(pd->edit_uv_edges_grp, geom, NULL); } - geom = DRW_mesh_batch_cache_get_edituv_verts(ob->data); + geom = DRW_mesh_batch_cache_get_edituv_verts(ob, ob->data); if (geom) { DRW_shgroup_call_obmat(pd->edit_uv_verts_grp, geom, NULL); } if (pd->edit_uv.do_faces) { - geom = DRW_mesh_batch_cache_get_edituv_faces(ob->data); + geom = DRW_mesh_batch_cache_get_edituv_faces(ob, ob->data); if (geom) { DRW_shgroup_call_obmat(pd->edit_uv_faces_grp, geom, NULL); } } if (pd->edit_uv.do_face_dots) { - geom = DRW_mesh_batch_cache_get_edituv_facedots(ob->data); + geom = DRW_mesh_batch_cache_get_edituv_facedots(ob, ob->data); if (geom) { DRW_shgroup_call_obmat(pd->edit_uv_face_dots_grp, geom, NULL); } @@ -465,14 +465,14 @@ static void overlay_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob) if (pd->edit_uv.do_uv_stretching_overlay) { if (pd->edit_uv.draw_type == SI_UVDT_STRETCH_ANGLE) { - geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(me); + geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(ob, me); } else /* SI_UVDT_STRETCH_AREA */ { OVERLAY_StretchingAreaTotals *totals = MEM_mallocN(sizeof(OVERLAY_StretchingAreaTotals), __func__); BLI_addtail(&pd->edit_uv.totals, totals); geom = DRW_mesh_batch_cache_get_edituv_faces_stretch_area( - me, &totals->total_area, &totals->total_area_uv); + ob, me, &totals->total_area, &totals->total_area_uv); } if (geom) { DRW_shgroup_call_obmat(pd->edit_uv_stretching_grp, geom, NULL); @@ -482,7 +482,7 @@ static void overlay_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob) if (draw_shadows && (has_active_object_uvmap || has_active_edit_uvmap)) { if (pd->edit_uv.do_uv_shadow_overlay) { - geom = DRW_mesh_batch_cache_get_uv_edges(ob->data); + geom = DRW_mesh_batch_cache_get_uv_edges(ob, ob->data); if (geom) { DRW_shgroup_call_obmat(pd->edit_uv_shadow_edges_grp, geom, NULL); } diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c index 449130c4c5b..1eb8fc981cf 100644 --- a/source/blender/draw/engines/overlay/overlay_wireframe.c +++ b/source/blender/draw/engines/overlay/overlay_wireframe.c @@ -185,10 +185,11 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata, Mesh *me = ob->data; if (is_edit_mode) { BLI_assert(me->edit_mesh); - BMEditMesh *embm = me->edit_mesh; - has_edit_mesh_cage = embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final); - if (embm->mesh_eval_final) { - me = embm->mesh_eval_final; + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob); + Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob); + has_edit_mesh_cage = editmesh_eval_cage && (editmesh_eval_cage != editmesh_eval_final); + if (editmesh_eval_final) { + me = editmesh_eval_final; } } is_mesh_verts_only = me->totedge == 0 && me->totvert > 0; diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c index e9930dbdb30..2801f2d7720 100644 --- a/source/blender/draw/engines/select/select_draw_utils.c +++ b/source/blender/draw/engines/select/select_draw_utils.c @@ -49,7 +49,7 @@ void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3]) BoundBox *bb; BMEditMesh *em = BKE_editmesh_from_object(obj); if (em) { - bb = BKE_editmesh_cage_boundbox_get(em); + bb = BKE_editmesh_cage_boundbox_get(obj, em); } else { bb = BKE_object_boundbox_get(obj); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 1110658e3b2..a4564ce2668 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -960,7 +960,7 @@ int DRW_cache_object_material_count_get(struct Object *ob) switch (type) { case OB_MESH: - return DRW_mesh_material_count_get((me != NULL) ? me : ob->data); + return DRW_mesh_material_count_get(ob, (me != NULL) ? me : ob->data); case OB_CURVE: case OB_SURF: case OB_FONT: @@ -2875,7 +2875,7 @@ GPUBatch *DRW_cache_mesh_surface_get(Object *ob) GPUBatch *DRW_cache_mesh_surface_edges_get(Object *ob) { BLI_assert(ob->type == OB_MESH); - return DRW_mesh_batch_cache_get_surface_edges(ob->data); + return DRW_mesh_batch_cache_get_surface_edges(ob, ob->data); } GPUBatch **DRW_cache_mesh_surface_shaded_get(Object *ob, @@ -2883,31 +2883,31 @@ GPUBatch **DRW_cache_mesh_surface_shaded_get(Object *ob, uint gpumat_array_len) { BLI_assert(ob->type == OB_MESH); - return DRW_mesh_batch_cache_get_surface_shaded(ob->data, gpumat_array, gpumat_array_len); + return DRW_mesh_batch_cache_get_surface_shaded(ob, ob->data, gpumat_array, gpumat_array_len); } GPUBatch **DRW_cache_mesh_surface_texpaint_get(Object *ob) { BLI_assert(ob->type == OB_MESH); - return DRW_mesh_batch_cache_get_surface_texpaint(ob->data); + return DRW_mesh_batch_cache_get_surface_texpaint(ob, ob->data); } GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob) { BLI_assert(ob->type == OB_MESH); - return DRW_mesh_batch_cache_get_surface_texpaint_single(ob->data); + return DRW_mesh_batch_cache_get_surface_texpaint_single(ob, ob->data); } GPUBatch *DRW_cache_mesh_surface_vertpaint_get(Object *ob) { BLI_assert(ob->type == OB_MESH); - return DRW_mesh_batch_cache_get_surface_vertpaint(ob->data); + return DRW_mesh_batch_cache_get_surface_vertpaint(ob, ob->data); } GPUBatch *DRW_cache_mesh_surface_sculptcolors_get(Object *ob) { BLI_assert(ob->type == OB_MESH); - return DRW_mesh_batch_cache_get_surface_sculpt(ob->data); + return DRW_mesh_batch_cache_get_surface_sculpt(ob, ob->data); } GPUBatch *DRW_cache_mesh_surface_weights_get(Object *ob) @@ -3091,7 +3091,7 @@ GPUBatch **DRW_cache_surf_surface_shaded_get(Object *ob, struct Curve *cu = ob->data; struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob); if (mesh_eval != NULL) { - return DRW_mesh_batch_cache_get_surface_shaded(mesh_eval, gpumat_array, gpumat_array_len); + return DRW_mesh_batch_cache_get_surface_shaded(ob, mesh_eval, gpumat_array, gpumat_array_len); } return DRW_curve_batch_cache_get_surface_shaded(cu, gpumat_array, gpumat_array_len); @@ -3385,7 +3385,7 @@ void drw_batch_cache_validate(Object *ob) struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh_no_subsurf(ob); switch (ob->type) { case OB_MESH: - DRW_mesh_batch_cache_validate((Mesh *)ob->data); + DRW_mesh_batch_cache_validate(ob, (Mesh *)ob->data); break; case OB_CURVE: case OB_FONT: @@ -3393,7 +3393,7 @@ void drw_batch_cache_validate(Object *ob) break; case OB_SURF: if (mesh_eval != NULL) { - DRW_mesh_batch_cache_validate(mesh_eval); + DRW_mesh_batch_cache_validate(ob, mesh_eval); } DRW_curve_batch_cache_validate((Curve *)ob->data); break; diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h index bd4edaf09fb..e7f66ebacd0 100644 --- a/source/blender/draw/intern/draw_cache_extract.h +++ b/source/blender/draw/intern/draw_cache_extract.h @@ -28,6 +28,7 @@ struct TaskGraph; #include "DNA_customdata_types.h" #include "BKE_attribute.h" +#include "BKE_object.h" #include "GPU_batch.h" #include "GPU_index_buffer.h" @@ -107,11 +108,13 @@ ENUM_OPERATORS(eMRDataType, MR_DATA_POLYS_SORTED) extern "C" { #endif -BLI_INLINE int mesh_render_mat_len_get(const Mesh *me) +BLI_INLINE int mesh_render_mat_len_get(const Object *object, const Mesh *me) { - /* In edit mode, the displayed mesh is stored in the edit-mesh. */ - if (me->edit_mesh && me->edit_mesh->mesh_eval_final) { - return MAX2(1, me->edit_mesh->mesh_eval_final->totcol); + if (me->edit_mesh != NULL) { + const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object); + if (editmesh_eval_final != NULL) { + return MAX2(1, editmesh_eval_final->totcol); + } } return MAX2(1, me->totcol); } @@ -328,6 +331,7 @@ typedef struct MeshBatchCache { void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, MeshBatchCache *cache, MeshBufferCache *mbc, + Object *object, Mesh *me, bool is_editmode, bool is_paint_mode, diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index fe55778527b..987ddf3a938 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -570,6 +570,7 @@ static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *t static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, MeshBatchCache *cache, MeshBufferCache *mbc, + Object *object, Mesh *me, const bool is_editmode, @@ -615,7 +616,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, */ const bool do_hq_normals = (scene->r.perf_flag & SCE_PERF_HQ_NORMALS) != 0 || GPU_use_hq_normals_workaround(); - const bool override_single_mat = mesh_render_mat_len_get(me) <= 1; + const bool override_single_mat = mesh_render_mat_len_get(object, me) <= 1; /* Create an array containing all the extractors that needs to be executed. */ ExtractorRunDatas extractors; @@ -700,7 +701,7 @@ static void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, #endif MeshRenderData *mr = mesh_render_data_create( - me, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts); + object, me, is_editmode, is_paint_mode, is_mode_active, obmat, do_final, do_uvedit, ts); mr->use_hide = use_hide; mr->use_subsurf_fdots = use_subsurf_fdots; mr->use_final_mesh = do_final; @@ -902,6 +903,7 @@ extern "C" { void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, MeshBatchCache *cache, MeshBufferCache *mbc, + Object *object, Mesh *me, const bool is_editmode, @@ -918,6 +920,7 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, blender::draw::mesh_buffer_cache_create_requested(task_graph, cache, mbc, + object, me, is_editmode, is_paint_mode, diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c index 29430c46d93..a47a124bd24 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.c @@ -438,7 +438,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ } } -MeshRenderData *mesh_render_data_create(Mesh *me, +MeshRenderData *mesh_render_data_create(Object *object, + Mesh *me, const bool is_editmode, const bool is_paint_mode, const bool is_mode_active, @@ -449,15 +450,18 @@ MeshRenderData *mesh_render_data_create(Mesh *me, { MeshRenderData *mr = MEM_callocN(sizeof(*mr), __func__); mr->toolsettings = ts; - mr->mat_len = mesh_render_mat_len_get(me); + mr->mat_len = mesh_render_mat_len_get(object, me); copy_m4_m4(mr->obmat, obmat); if (is_editmode) { - BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final); + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object); + Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(object); + + BLI_assert(editmesh_eval_cage && editmesh_eval_final); mr->bm = me->edit_mesh->bm; mr->edit_bmesh = me->edit_mesh; - mr->me = (do_final) ? me->edit_mesh->mesh_eval_final : me->edit_mesh->mesh_eval_cage; + mr->me = (do_final) ? editmesh_eval_final : editmesh_eval_cage; mr->edit_data = is_mode_active ? mr->me->runtime.edit_data : NULL; if (mr->edit_data) { @@ -507,7 +511,7 @@ 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 (has_mdata && do_final && me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage) { + if (has_mdata && do_final && editmesh_eval_final != editmesh_eval_cage) { // mr->edit_bmesh = NULL; mr->extract_type = MR_EXTRACT_MESH; } diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 77b507bc2b6..6a2f4b91ad1 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -60,7 +60,7 @@ void DRW_curve_batch_cache_validate(struct Curve *cu); void DRW_curve_batch_cache_free(struct Curve *cu); void DRW_mesh_batch_cache_dirty_tag(struct Mesh *me, eMeshBatchDirtyMode mode); -void DRW_mesh_batch_cache_validate(struct Mesh *me); +void DRW_mesh_batch_cache_validate(struct Object *object, struct Mesh *me); void DRW_mesh_batch_cache_free(struct Mesh *me); void DRW_lattice_batch_cache_dirty_tag(struct Lattice *lt, int mode); @@ -236,14 +236,18 @@ struct GPUBatch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_loose_edges(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edge_detection(struct Mesh *me, bool *r_is_manifold); struct GPUBatch *DRW_mesh_batch_cache_get_surface(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_surface_edges(struct Mesh *me); -struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(struct Mesh *me, +struct GPUBatch *DRW_mesh_batch_cache_get_surface_edges(struct Object *object, struct Mesh *me); +struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(struct Object *object, + struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len); -struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(struct Mesh *me); +struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Object *object, + struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Object *object, + struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(struct Object *object, + struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(struct Object *object, struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_surface_weights(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_sculpt_overlays(struct Mesh *me); @@ -293,14 +297,16 @@ struct GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(struct Mesh *me); * The `cache->tot_area` and cache->tot_uv_area` update are calculation are * only valid after calling `DRW_mesh_batch_cache_create_requested`. */ -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(struct Mesh *me, +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(struct Object *object, + struct Mesh *me, float **tot_area, float **tot_uv_area); -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(struct Mesh *me); -struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(struct Object *object, + struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(struct Object *object, struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(struct Object *object, struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(struct Object *object, struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Object *object, struct Mesh *me); /** \} */ @@ -308,7 +314,7 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(struct Mesh *me); /** \name For Image UV Editor * \{ */ -struct GPUBatch *DRW_mesh_batch_cache_get_uv_edges(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_uv_edges(struct Object *object, struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(struct Mesh *me); /** \} */ @@ -321,7 +327,7 @@ struct GPUVertBuf *DRW_mesh_batch_cache_pos_vertbuf_get(struct Mesh *me); struct GPUVertBuf *DRW_curve_batch_cache_pos_vertbuf_get(struct Curve *cu); struct GPUVertBuf *DRW_mball_batch_cache_pos_vertbuf_get(struct Object *ob); -int DRW_mesh_material_count_get(const struct Mesh *me); +int DRW_mesh_material_count_get(const struct Object *object, const struct Mesh *me); /* See 'common_globals_lib.glsl' for duplicate defines. */ diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 1e5ffc14911..f57921d058c 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -280,9 +280,16 @@ BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a) *((uint32_t *)a) = 0; } -BLI_INLINE const Mesh *editmesh_final_or_this(const Mesh *me) +BLI_INLINE const Mesh *editmesh_final_or_this(const Object *object, const Mesh *me) { - return (me->edit_mesh && me->edit_mesh->mesh_eval_final) ? me->edit_mesh->mesh_eval_final : me; + if (me->edit_mesh != NULL) { + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object); + if (editmesh_eval_final != NULL) { + return editmesh_eval_final; + } + } + + return me; } static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *cd_used) @@ -443,9 +450,11 @@ BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me) return &me->vdata; } -static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used) +static void mesh_cd_calc_active_uv_layer(const Object *object, + const Mesh *me, + DRW_MeshCDMask *cd_used) { - const Mesh *me_final = editmesh_final_or_this(me); + const Mesh *me_final = editmesh_final_or_this(object, me); 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) { @@ -453,9 +462,11 @@ 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) +static void mesh_cd_calc_active_mask_uv_layer(const Object *object, + const Mesh *me, + DRW_MeshCDMask *cd_used) { - const Mesh *me_final = editmesh_final_or_this(me); + const Mesh *me_final = editmesh_final_or_this(object, me); 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) { @@ -463,9 +474,11 @@ 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_MeshAttributes *attrs_used) +static void mesh_cd_calc_active_vcol_layer(const Object *object, + const Mesh *me, + DRW_MeshAttributes *attrs_used) { - const Mesh *me_final = editmesh_final_or_this(me); + const Mesh *me_final = editmesh_final_or_this(object, me); const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); int layer = CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR); @@ -474,9 +487,11 @@ static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshAttributes *a } } -static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used) +static void mesh_cd_calc_active_mloopcol_layer(const Object *object, + const Mesh *me, + DRW_MeshCDMask *cd_used) { - const Mesh *me_final = editmesh_final_or_this(me); + const Mesh *me_final = editmesh_final_or_this(object, me); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL); @@ -514,12 +529,13 @@ static bool custom_data_match_attribute(const CustomData *custom_data, return false; } -static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Mesh *me, +static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, + const Mesh *me, struct GPUMaterial **gpumat_array, int gpumat_array_len, DRW_MeshAttributes *attributes) { - const Mesh *me_final = editmesh_final_or_this(me); + const Mesh *me_final = editmesh_final_or_this(object, me); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); const CustomData *cd_pdata = mesh_cd_pdata_get_from_mesh(me_final); const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); @@ -793,7 +809,7 @@ BLI_INLINE void mesh_batch_cache_add_request(MeshBatchCache *cache, DRWBatchFlag /* GPUBatch cache management. */ -static bool mesh_batch_cache_valid(Mesh *me) +static bool mesh_batch_cache_valid(Object *object, Mesh *me) { MeshBatchCache *cache = me->runtime.batch_cache; @@ -809,14 +825,14 @@ static bool mesh_batch_cache_valid(Mesh *me) return false; } - if (cache->mat_len != mesh_render_mat_len_get(me)) { + if (cache->mat_len != mesh_render_mat_len_get(object, me)) { return false; } return true; } -static void mesh_batch_cache_init(Mesh *me) +static void mesh_batch_cache_init(Object *object, Mesh *me) { MeshBatchCache *cache = me->runtime.batch_cache; @@ -836,7 +852,7 @@ static void mesh_batch_cache_init(Mesh *me) // cache->vert_len = mesh_render_verts_len_get(me); } - cache->mat_len = mesh_render_mat_len_get(me); + cache->mat_len = mesh_render_mat_len_get(object, me); cache->surface_per_mat = MEM_callocN(sizeof(*cache->surface_per_mat) * cache->mat_len, __func__); cache->tris_per_mat = MEM_callocN(sizeof(*cache->tris_per_mat) * cache->mat_len, __func__); @@ -847,11 +863,11 @@ static void mesh_batch_cache_init(Mesh *me) drw_mesh_weight_state_clear(&cache->weight_state); } -void DRW_mesh_batch_cache_validate(Mesh *me) +void DRW_mesh_batch_cache_validate(Object *object, Mesh *me) { - if (!mesh_batch_cache_valid(me)) { + if (!mesh_batch_cache_valid(object, me)) { mesh_batch_cache_clear(me); - mesh_batch_cache_init(me); + mesh_batch_cache_init(object, me); } } @@ -1095,24 +1111,24 @@ void DRW_mesh_batch_cache_free(Mesh *me) /** \name Public API * \{ */ -static void texpaint_request_active_uv(MeshBatchCache *cache, Mesh *me) +static void texpaint_request_active_uv(MeshBatchCache *cache, Object *object, Mesh *me) { DRW_MeshCDMask cd_needed; mesh_cd_layers_type_clear(&cd_needed); - mesh_cd_calc_active_uv_layer(me, &cd_needed); + mesh_cd_calc_active_uv_layer(object, me, &cd_needed); BLI_assert(cd_needed.uv != 0 && "No uv layer available in texpaint, but batches requested anyway!"); - mesh_cd_calc_active_mask_uv_layer(me, &cd_needed); + mesh_cd_calc_active_mask_uv_layer(object, me, &cd_needed); mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); } -static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me) +static void texpaint_request_active_vcol(MeshBatchCache *cache, Object *object, Mesh *me) { DRW_MeshCDMask cd_needed; mesh_cd_layers_type_clear(&cd_needed); - mesh_cd_calc_active_mloopcol_layer(me, &cd_needed); + mesh_cd_calc_active_mloopcol_layer(object, me, &cd_needed); BLI_assert(cd_needed.vcol != 0 && "No MLOOPCOL layer available in vertpaint, but batches requested anyway!"); @@ -1120,11 +1136,11 @@ static void texpaint_request_active_vcol(MeshBatchCache *cache, Mesh *me) mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); } -static void sculpt_request_active_vcol(MeshBatchCache *cache, Mesh *me) +static void sculpt_request_active_vcol(MeshBatchCache *cache, Object *object, Mesh *me) { DRW_MeshAttributes attrs_needed; drw_mesh_attributes_clear(&attrs_needed); - mesh_cd_calc_active_vcol_layer(me, &attrs_needed); + mesh_cd_calc_active_vcol_layer(object, me, &attrs_needed); BLI_assert(attrs_needed.num_requests != 0 && "No MPropCol layer available in Sculpt, but batches requested anyway!"); @@ -1197,7 +1213,8 @@ GPUBatch *DRW_mesh_batch_cache_get_edit_mesh_analysis(Mesh *me) return DRW_batch_request(&cache->batch.edit_mesh_analysis); } -GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, +GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Object *object, + Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len) { @@ -1205,7 +1222,7 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, DRW_MeshAttributes attrs_needed; drw_mesh_attributes_clear(&attrs_needed); DRW_MeshCDMask cd_needed = mesh_cd_calc_used_gpu_layers( - me, gpumat_array, gpumat_array_len, &attrs_needed); + object, me, gpumat_array, gpumat_array_len, &attrs_needed); BLI_assert(gpumat_array_len == cache->mat_len); @@ -1216,41 +1233,41 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me, return cache->surface_per_mat; } -GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me) +GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - texpaint_request_active_uv(cache, me); + texpaint_request_active_uv(cache, object, me); mesh_batch_cache_request_surface_batches(cache); return cache->surface_per_mat; } -GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - texpaint_request_active_uv(cache, me); + texpaint_request_active_uv(cache, object, me); mesh_batch_cache_request_surface_batches(cache); return cache->batch.surface; } -GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - texpaint_request_active_vcol(cache, me); + texpaint_request_active_vcol(cache, object, me); mesh_batch_cache_request_surface_batches(cache); return cache->batch.surface; } -GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - sculpt_request_active_vcol(cache, me); + sculpt_request_active_vcol(cache, object, me); mesh_batch_cache_request_surface_batches(cache); return cache->batch.surface; } -int DRW_mesh_material_count_get(const Mesh *me) +int DRW_mesh_material_count_get(const Object *object, const Mesh *me) { - return mesh_render_mat_len_get(me); + return mesh_render_mat_len_get(object, me); } GPUBatch *DRW_mesh_batch_cache_get_sculpt_overlays(Mesh *me) @@ -1375,26 +1392,27 @@ GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me) /** \name UV Image editor API * \{ */ -static void edituv_request_active_uv(MeshBatchCache *cache, Mesh *me) +static void edituv_request_active_uv(MeshBatchCache *cache, Object *object, Mesh *me) { DRW_MeshCDMask cd_needed; mesh_cd_layers_type_clear(&cd_needed); - mesh_cd_calc_active_uv_layer(me, &cd_needed); + mesh_cd_calc_active_uv_layer(object, me, &cd_needed); mesh_cd_calc_edit_uv_layer(me, &cd_needed); BLI_assert(cd_needed.edit_uv != 0 && "No uv layer available in edituv, but batches requested anyway!"); - mesh_cd_calc_active_mask_uv_layer(me, &cd_needed); + mesh_cd_calc_active_mask_uv_layer(object, me, &cd_needed); mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); } -GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Mesh *me, +GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Object *object, + Mesh *me, float **tot_area, float **tot_uv_area) { MeshBatchCache *cache = mesh_batch_cache_get(me); - edituv_request_active_uv(cache, me); + edituv_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_AREA); if (tot_area != NULL) { @@ -1406,58 +1424,58 @@ GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_area(Mesh *me, return DRW_batch_request(&cache->batch.edituv_faces_stretch_area); } -GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_edituv_faces_stretch_angle(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - edituv_request_active_uv(cache, me); + edituv_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES_STRETCH_ANGLE); return DRW_batch_request(&cache->batch.edituv_faces_stretch_angle); } -GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_edituv_faces(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - edituv_request_active_uv(cache, me); + edituv_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_EDITUV_FACES); return DRW_batch_request(&cache->batch.edituv_faces); } -GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_edituv_edges(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - edituv_request_active_uv(cache, me); + edituv_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_EDITUV_EDGES); return DRW_batch_request(&cache->batch.edituv_edges); } -GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_edituv_verts(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - edituv_request_active_uv(cache, me); + edituv_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_EDITUV_VERTS); return DRW_batch_request(&cache->batch.edituv_verts); } -GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_edituv_facedots(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - edituv_request_active_uv(cache, me); + edituv_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_EDITUV_FACEDOTS); return DRW_batch_request(&cache->batch.edituv_fdots); } -GPUBatch *DRW_mesh_batch_cache_get_uv_edges(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_uv_edges(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - edituv_request_active_uv(cache, me); + edituv_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS_UVS); return DRW_batch_request(&cache->batch.wire_loops_uvs); } -GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Mesh *me) +GPUBatch *DRW_mesh_batch_cache_get_surface_edges(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - texpaint_request_active_uv(cache, me); + texpaint_request_active_uv(cache, object, me); mesh_batch_cache_add_request(cache, MBC_WIRE_LOOPS); return DRW_batch_request(&cache->batch.wire_loops); } @@ -1560,20 +1578,12 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, /* Sanity check. */ if ((me->edit_mesh != NULL) && (ob->mode & OB_MODE_EDIT)) { - BLI_assert(me->edit_mesh->mesh_eval_final != NULL); + BLI_assert(BKE_object_get_editmesh_eval_final(ob) != NULL); } - /* Don't check `DRW_object_is_in_edit_mode(ob)` here because it means the same mesh - * may draw with edit-mesh data and regular mesh data. - * In this case the custom-data layers used won't always match in `me->runtime.batch_cache`. - * If we want to display regular mesh data, we should have a separate cache for the edit-mesh. - * See T77359. */ const bool is_editmode = (me->edit_mesh != NULL) && - /* In rare cases we have the edit-mode data but not the generated cache. - * This can happen when switching an objects data to a mesh which - * happens to be in edit-mode in another scene, see: T82952. */ - (me->edit_mesh->mesh_eval_final != - NULL) /* && DRW_object_is_in_edit_mode(ob) */; + (BKE_object_get_editmesh_eval_final(ob) != NULL) && + DRW_object_is_in_edit_mode(ob); /* This could be set for paint mode too, currently it's only used for edit-mode. */ const bool is_mode_active = is_editmode && DRW_object_is_in_edit_mode(ob); @@ -1599,7 +1609,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, /* Modifiers will only generate an orco layer if the mesh is deformed. */ if (cache->cd_needed.orco != 0) { /* Orco is always extracted from final mesh. */ - Mesh *me_final = (me->edit_mesh) ? me->edit_mesh->mesh_eval_final : me; + Mesh *me_final = (me->edit_mesh) ? BKE_object_get_editmesh_eval_final(ob) : me; if (CustomData_get_layer(&me_final->vdata, CD_ORCO) == NULL) { /* Skip orco calculation */ cache->cd_needed.orco = 0; @@ -1705,10 +1715,14 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, cache->batch_ready |= batch_requested; - const bool do_cage = (is_editmode && - (me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage)); + bool do_cage = false, do_uvcage = false; + if (is_editmode) { + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob); + Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob); - const bool do_uvcage = is_editmode && !me->edit_mesh->mesh_eval_final->runtime.is_original; + do_cage = editmesh_eval_final != editmesh_eval_cage; + do_uvcage = !editmesh_eval_final->runtime.is_original; + } const int required_mode = BKE_subsurf_modifier_eval_required_mode(DRW_state_is_scene_render(), is_editmode); @@ -2029,6 +2043,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, mesh_buffer_cache_create_requested(task_graph, cache, &cache->uv_cage, + ob, me, is_editmode, is_paint_mode, @@ -2046,6 +2061,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, mesh_buffer_cache_create_requested(task_graph, cache, &cache->cage, + ob, me, is_editmode, is_paint_mode, @@ -2071,6 +2087,7 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, mesh_buffer_cache_create_requested(task_graph, cache, &cache->final, + ob, me, is_editmode, is_paint_mode, diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 2f0c5cca3d6..a24a3a5a3a7 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -1828,7 +1828,7 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene, Mesh *mesh_eval = mesh; BMesh *bm = nullptr; if (mesh->edit_mesh) { - mesh_eval = mesh->edit_mesh->mesh_eval_final; + mesh_eval = BKE_object_get_editmesh_eval_final(ob); bm = mesh->edit_mesh->bm; } diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 276a8cc3a13..45e4c2a575e 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -212,21 +212,7 @@ bool DRW_object_is_in_edit_mode(const Object *ob) if (BKE_object_is_in_editmode(ob)) { if (ob->type == OB_MESH) { if ((ob->mode & OB_MODE_EDIT) == 0) { - Mesh *me = (Mesh *)ob->data; - BMEditMesh *embm = me->edit_mesh; - /* Sanity check when rendering in multiple windows. */ - if (embm && embm->mesh_eval_final == NULL) { - return false; - } - /* Do not draw ob with edit overlay when edit data is present and is modified. */ - if (embm && embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final)) { - return false; - } - /* Check if the object that we are drawing is modified. */ - if (!DEG_is_original_id(&me->id)) { - return false; - } - return true; + return false; } } return true; diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.h b/source/blender/draw/intern/mesh_extractors/extract_mesh.h index bb55d0c5b2c..37eb4f80442 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.h +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.h @@ -281,7 +281,8 @@ typedef struct MeshExtract { * \param is_mode_active: When true, use the modifiers from the edit-data, * otherwise don't use modifiers as they are not from this object. */ -MeshRenderData *mesh_render_data_create(Mesh *me, +MeshRenderData *mesh_render_data_create(Object *object, + Mesh *me, bool is_editmode, bool is_paint_mode, bool is_mode_active, diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 013d5e5a661..f3db8f1f0d2 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -334,9 +334,6 @@ void EDBM_mesh_clear(BMEditMesh *em) /* clear bmesh */ BM_mesh_clear(em->bm); - /* Free evaluated meshes & cache. */ - BKE_editmesh_free_derived_caches(em); - /* free tessellation data */ em->tottri = 0; MEM_SAFE_FREE(em->looptris); @@ -1404,8 +1401,6 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params) BM_lnorspace_invalidate(em->bm, false); em->bm->spacearr_dirty &= ~BM_SPACEARR_BMO_SET; } - /* Don't keep stale evaluated mesh data around, see: T38872. */ - BKE_editmesh_free_derived_caches(em); #ifdef DEBUG { diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index e96c43e0d02..9dc8b6cf69d 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -153,19 +153,21 @@ static Mesh *mesh_for_snap(Object *ob_eval, eSnapEditType edit_mode_type, bool * return NULL; } - BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval); - if ((edit_mode_type == SNAP_GEOM_FINAL) && em_eval->mesh_eval_final) { - if (em_eval->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval); + Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval); + + if ((edit_mode_type == SNAP_GEOM_FINAL) && editmesh_eval_final) { + if (editmesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { return NULL; } - me_eval = em_eval->mesh_eval_final; + me_eval = editmesh_eval_final; use_hide = true; } - else if ((edit_mode_type == SNAP_GEOM_CAGE) && em_eval->mesh_eval_cage) { - if (em_eval->mesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { + else if ((edit_mode_type == SNAP_GEOM_CAGE) && editmesh_eval_cage) { + if (editmesh_eval_cage->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH) { return NULL; } - me_eval = em_eval->mesh_eval_cage; + me_eval = editmesh_eval_cage; use_hide = true; } } @@ -345,12 +347,14 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob_eval) { - BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval); - if (em_eval->mesh_eval_final) { - return &em_eval->mesh_eval_final->runtime; + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob_eval); + if (editmesh_eval_final) { + return &editmesh_eval_final->runtime; } - if (em_eval->mesh_eval_cage) { - return &em_eval->mesh_eval_cage->runtime; + + Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob_eval); + if (editmesh_eval_cage) { + return &editmesh_eval_cage->runtime; } return &((Mesh *)ob_eval->data)->runtime; diff --git a/source/blender/editors/util/ed_transverts.c b/source/blender/editors/util/ed_transverts.c index 705dfff7260..b8efbad1ad9 100644 --- a/source/blender/editors/util/ed_transverts.c +++ b/source/blender/editors/util/ed_transverts.c @@ -41,6 +41,7 @@ #include "BKE_editmesh.h" #include "BKE_lattice.h" #include "BKE_mesh_iterators.h" +#include "BKE_object.h" #include "DEG_depsgraph.h" @@ -311,9 +312,10 @@ void ED_transverts_create_from_obedit(TransVertStore *tvs, Object *obedit, const userdata[1] = tvs->transverts; } - if (tvs->transverts && em->mesh_eval_cage) { + struct Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(obedit); + if (tvs->transverts && editmesh_eval_cage) { BM_mesh_elem_table_ensure(bm, BM_VERT); - BKE_mesh_foreach_mapped_vert(em->mesh_eval_cage, set_mapped_co, userdata, MESH_FOREACH_NOP); + BKE_mesh_foreach_mapped_vert(editmesh_eval_cage, set_mapped_co, userdata, MESH_FOREACH_NOP); } } else if (obedit->type == OB_ARMATURE) { diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 5cce7ec5f67..f9ef4ba0000 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -181,6 +181,12 @@ typedef struct Object_Runtime { */ struct Mesh *mesh_deform_eval; + /* Evaluated mesh cage in edit mode. */ + struct Mesh *editmesh_eval_cage; + + /** Cached cage bounding box of `editmesh_eval_cage` for selection. */ + struct BoundBox *editmesh_bb_cage; + /** * Original grease pencil bGPdata pointer, before object->data was changed to point * to gpd_eval. diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index b77f6b7e3e2..a8c6687193b 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -245,9 +245,10 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * if ((ctx->flag & MOD_APPLY_TO_BASE_MESH) == 0) { Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); const bool is_render_mode = (ctx->flag & MOD_APPLY_RENDER) != 0; - /* Same check as in `DRW_mesh_batch_cache_create_requested` to keep both code coherent. */ - const bool is_editmode = (mesh->edit_mesh != NULL) && - (mesh->edit_mesh->mesh_eval_final != NULL); + /* Same check as in `DRW_mesh_batch_cache_create_requested` to keep both code coherent. The + * difference is that here we do not check for the final edit mesh pointer as it is not yet + * assigned at this stage of modifier stack evaluation. */ + const bool is_editmode = (mesh->edit_mesh != NULL); const int required_mode = BKE_subsurf_modifier_eval_required_mode(is_render_mode, is_editmode); if (BKE_subsurf_modifier_can_do_gpu_subdiv_ex(scene, ctx->object, smd, required_mode, false)) { subdiv_cache_cpu_evaluation_settings(ctx, mesh, smd); |