Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey@blender.org>2022-01-11 17:42:07 +0300
committerSergey Sharybin <sergey@blender.org>2022-01-25 16:32:23 +0300
commit0f89bcdbebf5094bd816318774b67c677790ea99 (patch)
treeda29273e8c26da441924aa46c2d4948f1990fff8 /source/blender/blenkernel
parentc5980ada4fd564add37e878e372d1249715636b1 (diff)
Fix depsgraphs sharing IDs via evaluated edit mesh
The evaluated mesh is a result of evaluated modifiers, and referencing other evaluated IDs such as materials. It can not be stored in the EditMesh structure which is intended to be re-used by many areas. Such sharing was causing ownership errors causing bugs like T93855: Cycles crash with edit mode and simultaneous viewport and final render The proposed solution is to store the evaluated edit mesh and its cage in the object's runtime field. The motivation goes as following: - It allows to avoid ownership problems like the ones in the linked report. - Object level is chosen over mesh level is because the evaluated mesh is affected by modifiers, which are on the object level. This patch allows to have modifier stack of an object which shares mesh with an object which is in edit mode to be properly taken into account (before the change the modifier stack from the active object will be used for all objects which share the mesh). There is a change in the way how copy-on-write is handled in the edit mode to allow proper state update when changing active scene (or having two windows with different scenes). Previously, the copt-on-write would have been ignored by skipping tagging CoW component. Now it is ignored from within the CoW operation callback. This allows to update edit pointers for objects which are not from the current depsgraph and where the edit_mesh was never assigned in the case when the depsgraph was evaluated prior the active depsgraph. There is no user level changes changes expected with the CoW handling changes: should not affect on neither performance, nor memory consumption. Tested scenarios: - Various modifiers configurations of objects sharing mesh and be part of the same scene. - Steps from the reports: T93855, T82952, T77359 This also fixes T76609, T72733 and perhaps other reports. Differential Revision: https://developer.blender.org/D13824
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h1
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h11
-rw-r--r--source/blender/blenkernel/BKE_mesh.h3
-rw-r--r--source/blender/blenkernel/BKE_object.h3
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc87
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c2
-rw-r--r--source/blender/blenkernel/intern/editmesh.c39
-rw-r--r--source/blender/blenkernel/intern/material.c5
-rw-r--r--source/blender/blenkernel/intern/mesh.cc21
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc7
-rw-r--r--source/blender/blenkernel/intern/modifier.c7
-rw-r--r--source/blender/blenkernel/intern/object.cc38
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc2
-rw-r--r--source/blender/blenkernel/intern/object_update.c13
14 files changed, 144 insertions, 95 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: