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
This commit is contained in:
Sergey Sharybin 2022-01-11 15:42:07 +01:00
parent c5980ada4f
commit 0f89bcdbeb
Notes: blender-bot 2023-02-14 05:16:25 +01:00
Referenced by commit 2c0c431399, Fix T102221: Entering editmode invalidates the driver associated with that mesh
Referenced by commit 6bbf63f251, Fix T96054: Switching vertex group does not update display
Referenced by commit 6f9828289f, Fix T95356: Crash in armature edit mode and certain condition
Referenced by commit 974981a637, Fix T95222: Crash selecting vertices with modifier applied on cage
Referenced by issue #102221, Regression: Entering editmode will invalidate the driver associated with that mesh
Referenced by issue #96054, newly selected vertex group with lattices don't display weights in edit mode.
Referenced by issue #95997, [3.1] Crash when entering edit mode
Referenced by issue #95571, Crashes in edit mode
Referenced by issue #95467, Textures disappear when going to Edit Mesh on Solid Texture mode.
Referenced by issue #95356, Blender crashes when renaming bone in Edit Mode, Saving, and than selecting/deselecting.
Referenced by issue #95356, Blender crashes when renaming bone in Edit Mode, Saving, and than selecting/deselecting.
Referenced by issue #95288, Shrinkwrap selection broken in edit mode.
Referenced by issue #95165, Regression: Custom Normals tools dont update immediately (when started with Auto Smooth OFF)
Referenced by issue #94230, Crash rendering with EEVEE in mesh edit-mode
Referenced by issue #93963, Inconsistent displaying object data in a Viewport between scenes
Referenced by issue #93855, Cycles crash with edit mode and simultaneous viewport and final render
Referenced by issue #76609, Multi-object editing is broken with linked objects with modifiers.
Referenced by issue #72733, Issue with shared meshes overwriting modifiers
35 changed files with 365 additions and 276 deletions

View File

@ -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,

View File

@ -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
}

View File

@ -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).

View File

@ -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. */

View File

@ -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,

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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:

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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. */

View File

@ -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,

View File

@ -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;
}

View File

@ -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;

View File

@ -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,

View File

@ -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
{

View File

@ -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;

View File

@ -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) {

View File

@ -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.

View File

@ -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);