Fix #113377: Pass edit mesh pointer through modifiers

Currently replacing the Mesh during evaluation with the object info node
can cause us to use invalid original indices when the source object is
in edit mode. This is really a more fundamental problem though: we have
no way to tell whether an evaluated mesh actually corresponds to the
object's original mesh.

This commit changes to explicitly propagating the edit mesh pointer
through copied and changed meshes during modifier and nodes evaluation,
instead of just blindly copying the edit mode pointer from the original
mesh to the evaluated mesh. A benefit of not writing to the evaluated
mesh means it can be shared, potentially offering a future performance
improvement for uses of the object info node.

When we detect an invalid correspondence between the evaluated/original
meshes, we skip extracting the cage mesh's data and skip extracting edit
mesh data from the evaluated object.

This commit also moves the source of "object is in edit mode" truth in
the draw module from whether the evaluated mesh has an edit mode pointer
to the object's mode flag. That's a simplification that's also helpful
to reduce the strong linking between BMesh and edit mode.

Pull Request: https://projects.blender.org/blender/blender/pulls/120999
This commit is contained in:
Hans Goudey
2024-11-21 16:42:00 +01:00
committed by Hans Goudey
parent 1dcd435a87
commit 839108f623
15 changed files with 255 additions and 115 deletions

View File

@@ -95,6 +95,14 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em);
* don't add NULL data check here. caller must do that
*/
BMEditMesh *BKE_editmesh_from_object(Object *ob);
/**
* Return whether the evaluated mesh is a "descendent" of the original mesh: whether it is a
* version of the original mesh propagated during evaluation. This will be false if the mesh was
* taken from from an different object during evaluation, with the object info node for example.
*/
bool BKE_editmesh_eval_orig_map_available(const Mesh &mesh_eval, const Mesh *mesh_orig);
/**
* \note Does not free the #BMEditMesh itself.
*/

View File

@@ -94,8 +94,6 @@ void BKE_mesh_clear_geometry_and_metadata(Mesh *mesh);
Mesh *BKE_mesh_add(Main *bmain, const char *name);
void BKE_mesh_free_editmesh(Mesh *mesh);
/**
* A version of #BKE_mesh_copy_parameters that is intended for evaluated output
* (the modifier stack for example).

View File

@@ -66,6 +66,20 @@ BMEditMesh *BKE_editmesh_from_object(Object *ob)
return ((Mesh *)ob->data)->runtime->edit_mesh.get();
}
bool BKE_editmesh_eval_orig_map_available(const Mesh &mesh_eval, const Mesh *mesh_orig)
{
if (!mesh_orig) {
return false;
}
if (&mesh_eval == mesh_orig) {
return true;
}
if (mesh_eval.runtime->edit_mesh) {
return mesh_eval.runtime->edit_mesh == mesh_orig->runtime->edit_mesh;
}
return false;
}
void BKE_editmesh_looptris_calc_ex(BMEditMesh *em, const BMeshCalcTessellation_Params *params)
{
BMesh *bm = em->bm;

View File

@@ -166,6 +166,13 @@ static void mesh_copy_data(Main *bmain,
if (mesh_src->id.tag & ID_TAG_NO_MAIN) {
/* For copies in depsgraph, keep data like #CD_ORIGINDEX and #CD_ORCO. */
CustomData_MeshMasks_update(&mask, &CD_MASK_DERIVEDMESH);
/* Meshes copied during evaluation pass the edit mesh pointer to determine whether a mapping
* from the evaluated to the original state is possible. */
mesh_dst->runtime->edit_mesh = mesh_src->runtime->edit_mesh;
if (const blender::bke::EditMeshData *edit_data = mesh_src->runtime->edit_data.get()) {
mesh_dst->runtime->edit_data = std::make_unique<blender::bke::EditMeshData>(*edit_data);
}
}
mesh_dst->mat = (Material **)MEM_dupallocN(mesh_src->mat);
@@ -208,17 +215,10 @@ static void mesh_copy_data(Main *bmain,
}
}
void BKE_mesh_free_editmesh(Mesh *mesh)
{
mesh->runtime->edit_mesh.reset();
}
static void mesh_free_data(ID *id)
{
Mesh *mesh = reinterpret_cast<Mesh *>(id);
BKE_mesh_free_editmesh(mesh);
BKE_mesh_clear_geometry_and_metadata(mesh);
MEM_SAFE_FREE(mesh->mat);
@@ -804,6 +804,8 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
}
me_dst->mat = (Material **)MEM_dupallocN(me_src->mat);
me_dst->totcol = me_src->totcol;
me_dst->runtime->edit_mesh = me_src->runtime->edit_mesh;
}
Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,

View File

@@ -857,7 +857,6 @@ static void editbmesh_calc_modifiers(Depsgraph &depsgraph,
* cage mesh isn't modified anymore. */
mesh = BKE_mesh_copy_for_eval(*mesh);
if (mesh_cage->runtime->edit_mesh) {
mesh->runtime->edit_mesh = mesh_cage->runtime->edit_mesh;
mesh->runtime->is_original_bmesh = true;
mesh->runtime->deformed_only = mesh_cage->runtime->deformed_only;
if (mesh_cage->runtime->edit_data) {
@@ -1054,12 +1053,6 @@ static void editbmesh_build_data(Depsgraph &depsgraph,
editbmesh_calc_modifiers(
depsgraph, scene, obedit, dataMask, &me_cage, &me_final, &non_mesh_components);
/* 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->runtime->edit_mesh = me_cage->runtime->edit_mesh = mesh->runtime->edit_mesh;
/* 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

View File

@@ -4189,10 +4189,6 @@ const 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->runtime->edit_mesh != nullptr);
UNUSED_VARS_NDEBUG(mesh);
return object->runtime->editmesh_eval_cage;
}

View File

@@ -441,13 +441,14 @@ static void overlay_edit_uv_cache_populate(OVERLAY_Data *vedata, Object &ob)
blender::gpu::Batch *geom;
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_edit_object = DRW_object_is_in_edit_mode(&ob);
const bool is_edit_object = ob.mode == OB_MODE_EDIT;
Mesh &mesh = *(Mesh *)ob.data;
const bool has_active_object_uvmap = CustomData_get_active_layer(&mesh.corner_data,
CD_PROP_FLOAT2) != -1;
const bool has_active_edit_uvmap = is_edit_object && (CustomData_get_active_layer(
&mesh.runtime->edit_mesh->bm->ldata,
CD_PROP_FLOAT2) != -1);
/* Currently we only support extracting UV data for an original edit #BMesh mesh. */
const bool has_active_edit_uvmap =
is_edit_object && mesh.runtime->edit_mesh &&
(CustomData_get_active_layer(&mesh.runtime->edit_mesh->bm->ldata, CD_PROP_FLOAT2) != -1);
const bool draw_shadows = (draw_ctx->object_mode != OB_MODE_OBJECT) &&
(ob.mode == draw_ctx->object_mode);

View File

@@ -331,7 +331,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
const bool is_preview = dupli_object != nullptr &&
dupli_object->preview_base_geometry != nullptr;
const bool in_pose_mode = ob->type == OB_ARMATURE && OVERLAY_armature_is_pose_mode(ob, draw_ctx);
const bool in_edit_mode = overlay_object_is_edit_mode(pd, ob);
const bool in_edit_mode = ob->mode == OB_MODE_EDIT;
const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI);
const bool instance_parent_in_edit_mode = is_instance ?
overlay_object_is_edit_mode(

View File

@@ -160,7 +160,7 @@ void Instance::begin_sync()
void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
{
const bool in_edit_mode = object_is_edit_mode(ob_ref.object);
const bool in_edit_mode = ob_ref.object->mode == OB_MODE_EDIT;
const bool in_paint_mode = object_is_paint_mode(ob_ref.object);
const bool in_sculpt_mode = object_is_sculpt_mode(ob_ref);
const bool in_particle_edit_mode = object_is_particle_edit_mode(ob_ref);

View File

@@ -171,13 +171,13 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES) != 0;
const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0;
const bool is_mesh = ob->type == OB_MESH;
const bool is_edit_mode = DRW_object_is_in_edit_mode(ob);
const bool is_edit_mode = ob->mode == OB_MODE_EDIT;
bool has_edit_mesh_cage = false;
bool is_mesh_verts_only = false;
if (is_mesh) {
/* TODO: Should be its own function. */
const Mesh *mesh = static_cast<const Mesh *>(ob->data);
if (is_edit_mode) {
if (is_edit_mode && mesh->runtime->edit_mesh) {
BLI_assert(mesh->runtime->edit_mesh.get());
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(ob);
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(ob);
@@ -289,9 +289,10 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->rv3d) &&
!DRW_state_is_image_render();
const bool is_instance = (ob->base_flag & BASE_FROM_DUPLI);
const bool instance_parent_in_edit_mode = is_instance ? DRW_object_is_in_edit_mode(
DRW_object_get_dupli_parent(ob)) :
false;
const bool instance_parent_in_edit_mode = is_instance ?
DRW_object_get_dupli_parent(ob)->mode ==
OB_MODE_EDIT :
false;
const bool use_coloring = (use_wire && !is_edit_mode && !is_sculpt_mode &&
!has_edit_mesh_cage && !instance_parent_in_edit_mode);
geom = DRW_cache_object_face_wireframe_get(draw_ctx->scene, ob);

View File

@@ -197,8 +197,9 @@ void select_id_draw_object(void *vedata,
BLI_assert(initial_offset > 0);
switch (ob->type) {
case OB_MESH:
if (ob->mode & OB_MODE_EDIT) {
case OB_MESH: {
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
if (mesh.runtime->edit_mesh) {
bool draw_facedot = check_ob_drawface_dot(select_mode, v3d, eDrawType(ob->dt));
draw_select_id_edit_mesh(stl,
ob,
@@ -214,6 +215,7 @@ void select_id_draw_object(void *vedata,
stl, ob, select_mode, initial_offset, r_vert_offset, r_edge_offset, r_face_offset);
}
break;
}
case OB_CURVES_LEGACY:
case OB_SURF:
break;

View File

@@ -3361,7 +3361,7 @@ void drw_batch_cache_generate_requested(Object *ob)
const bool use_hide = ((ob->type == OB_MESH) &&
((is_paint_mode && (ob == draw_ctx->obact) &&
DRW_object_use_hide_faces(ob)) ||
((mode == CTX_MODE_EDIT_MESH) && DRW_object_is_in_edit_mode(ob))));
((mode == CTX_MODE_EDIT_MESH) && (ob->mode == OB_MODE_EDIT))));
switch (ob->type) {
case OB_MESH:
@@ -3400,7 +3400,7 @@ void drw_batch_cache_generate_requested_evaluated_mesh_or_curve(Object *ob)
const bool use_hide = ((ob->type == OB_MESH) &&
((is_paint_mode && (ob == draw_ctx->obact) &&
DRW_object_use_hide_faces(ob)) ||
((mode == CTX_MODE_EDIT_MESH) && DRW_object_is_in_edit_mode(ob))));
((mode == CTX_MODE_EDIT_MESH) && (ob->mode == OB_MODE_EDIT))));
Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf_unchecked(ob);
/* Try getting the mesh first and if that fails, try getting the curve data.

View File

@@ -545,17 +545,16 @@ std::unique_ptr<MeshRenderData> mesh_render_data_create(Object &object,
mr->use_hide = use_hide;
if (is_editmode) {
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(&object);
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(&object);
const Mesh *editmesh_orig = BKE_object_get_pre_modified_mesh(&object);
const Mesh *eval_cage = BKE_object_get_editmesh_eval_cage(&object);
BLI_assert(editmesh_eval_cage && editmesh_eval_final);
mr->bm = mesh.runtime->edit_mesh->bm;
mr->edit_bmesh = mesh.runtime->edit_mesh.get();
mr->mesh = (do_final) ? editmesh_eval_final : editmesh_eval_cage;
mr->bm = editmesh_orig->runtime->edit_mesh->bm;
mr->edit_bmesh = editmesh_orig->runtime->edit_mesh.get();
mr->mesh = (do_final) ? &mesh : eval_cage;
mr->edit_data = is_editmode ? mr->mesh->runtime->edit_data.get() : nullptr;
/* If there is no distinct cage, hide unmapped edges that can't be selected. */
mr->hide_unmapped_edges = !do_final || editmesh_eval_final == editmesh_eval_cage;
mr->hide_unmapped_edges = !do_final || &mesh == eval_cage;
if (bke::EditMeshData *emd = mr->edit_data) {
if (!emd->vert_positions.is_empty()) {

View File

@@ -8,6 +8,7 @@
* \brief Mesh API for render engines
*/
#include <memory>
#include <optional>
#include "MEM_guardedalloc.h"
@@ -1327,6 +1328,18 @@ static void drw_mesh_batch_cache_check_available(TaskGraph &task_graph, Mesh &me
}
#endif
static void init_empty_dummy_batch(gpu::Batch &batch)
{
/* The dummy batch is only used in cases with invalid edit mode mapping, so the overhead of
* creating a vertex buffer shouldn't matter. */
GPUVertFormat format{};
GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
blender::gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*vbo, 1);
GPU_batch_vertbuf_add(&batch, vbo, true);
}
void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
Object &ob,
Mesh &mesh,
@@ -1370,9 +1383,7 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
BLI_assert(BKE_object_get_editmesh_eval_final(&ob) != nullptr);
}
const bool is_editmode = (mesh.runtime->edit_mesh != nullptr) &&
(BKE_object_get_editmesh_eval_final(&ob) != nullptr) &&
DRW_object_is_in_edit_mode(&ob);
const bool is_editmode = ob.mode == OB_MODE_EDIT;
DRWBatchFlag batch_requested = cache.batch_requested;
cache.batch_requested = (DRWBatchFlag)0;
@@ -1499,14 +1510,32 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
cache.batch_ready |= batch_requested;
bool do_cage = false, do_uvcage = false;
if (is_editmode) {
const Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(&ob);
const Mesh *editmesh_eval_cage = BKE_object_get_editmesh_eval_cage(&ob);
/* This is the mesh before modifier evaluation, used to test how the mesh changed during
* evaluation to decide which data is valid to extract. */
const Mesh *orig_edit_mesh = is_editmode ? BKE_object_get_pre_modified_mesh(&ob) : nullptr;
do_cage = editmesh_eval_final != editmesh_eval_cage;
do_uvcage = !(editmesh_eval_final->runtime->is_original_bmesh &&
editmesh_eval_final->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH);
bool do_cage = false;
const Mesh *edit_data_mesh = nullptr;
if (is_editmode) {
const Mesh *eval_cage = BKE_object_get_editmesh_eval_cage(&ob);
if (eval_cage && eval_cage != &mesh) {
/* Extract "cage" data separately when it exists and it's not just the same mesh as the
* regular evaluated mesh. Otherwise edit data will be extracted from the final evaluated
* mesh. */
do_cage = true;
edit_data_mesh = eval_cage;
}
else {
edit_data_mesh = &mesh;
}
}
bool do_uvcage = false;
if (is_editmode) {
/* Currently we don't extract UV data from the evaluated mesh unless it's the same mesh as the
* original edit mesh. */
do_uvcage = !(mesh.runtime->is_original_bmesh &&
mesh.runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH);
}
const bool do_subdivision = BKE_subsurf_modifier_has_gpu_subdiv(&mesh);
@@ -1650,96 +1679,158 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
mbuflist = (do_cage) ? &cache.cage.buff : &cache.final.buff;
/* When the msh doesn't correspond to the object's original mesh (i.e. the mesh was replaced by
* another with the object info node during evaluation), don't extract edit mode data for it.
* That data can be invalid because any original indices (#CD_ORIGINDEX) on the evaluated mesh
* won't correspond to the correct mesh. */
const bool edit_mapping_valid = is_editmode && BKE_editmesh_eval_orig_map_available(
*edit_data_mesh, orig_edit_mesh);
/* Edit Mesh */
assert_deps_valid(MBC_EDIT_TRIANGLES,
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edit_data)});
if (DRW_batch_requested(cache.batch.edit_triangles, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache.batch.edit_triangles, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.edit_triangles, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_triangles, &mbuflist->vbo.edit_data);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_triangles, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.edit_triangles, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_triangles, &mbuflist->vbo.edit_data);
}
else {
init_empty_dummy_batch(*cache.batch.edit_triangles);
}
}
assert_deps_valid(
MBC_EDIT_VERTICES,
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edit_data)});
if (DRW_batch_requested(cache.batch.edit_vertices, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edit_vertices, &mbuflist->ibo.points);
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.edit_data);
if (!do_subdivision || do_cage) {
/* For GPU subdivision, vertex normals are included in the `pos` VBO. */
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.vnor);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_vertices, &mbuflist->ibo.points);
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.edit_data);
if (!do_subdivision || do_cage) {
/* For GPU subdivision, vertex normals are included in the `pos` VBO. */
DRW_vbo_request(cache.batch.edit_vertices, &mbuflist->vbo.vnor);
}
}
else {
init_empty_dummy_batch(*cache.batch.edit_vertices);
}
}
assert_deps_valid(MBC_EDIT_EDGES,
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edit_data)});
if (DRW_batch_requested(cache.batch.edit_edges, GPU_PRIM_LINES)) {
DRW_ibo_request(cache.batch.edit_edges, &mbuflist->ibo.lines);
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.edit_data);
if (!do_subdivision || do_cage) {
/* For GPU subdivision, vertex normals are included in the `pos` VBO. */
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.vnor);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_edges, &mbuflist->ibo.lines);
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.edit_data);
if (!do_subdivision || do_cage) {
/* For GPU subdivision, vertex normals are included in the `pos` VBO. */
DRW_vbo_request(cache.batch.edit_edges, &mbuflist->vbo.vnor);
}
}
else {
init_empty_dummy_batch(*cache.batch.edit_edges);
}
}
assert_deps_valid(MBC_EDIT_VNOR,
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.vnor)});
if (DRW_batch_requested(cache.batch.edit_vnor, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edit_vnor, &mbuflist->ibo.points);
DRW_vbo_request(cache.batch.edit_vnor, &mbuflist->vbo.pos);
if (!do_subdivision) {
/* For GPU subdivision, vertex normals are included in the `pos` VBO. */
DRW_vbo_request(cache.batch.edit_vnor, &mbuflist->vbo.vnor);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_vnor, &mbuflist->ibo.points);
DRW_vbo_request(cache.batch.edit_vnor, &mbuflist->vbo.pos);
if (!do_subdivision) {
/* For GPU subdivision, vertex normals are included in the `pos` VBO. */
DRW_vbo_request(cache.batch.edit_vnor, &mbuflist->vbo.vnor);
}
}
else {
init_empty_dummy_batch(*cache.batch.edit_vnor);
}
}
assert_deps_valid(MBC_EDIT_LNOR,
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.nor)});
if (DRW_batch_requested(cache.batch.edit_lnor, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edit_lnor, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.nor);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_lnor, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_lnor, &mbuflist->vbo.nor);
}
else {
init_empty_dummy_batch(*cache.batch.edit_lnor);
}
}
assert_deps_valid(
MBC_EDIT_FACEDOTS,
{BUFFER_INDEX(ibo.fdots), BUFFER_INDEX(vbo.fdots_pos), BUFFER_INDEX(vbo.fdots_nor)});
if (DRW_batch_requested(cache.batch.edit_fdots, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edit_fdots, &mbuflist->ibo.fdots);
DRW_vbo_request(cache.batch.edit_fdots, &mbuflist->vbo.fdots_pos);
DRW_vbo_request(cache.batch.edit_fdots, &mbuflist->vbo.fdots_nor);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_fdots, &mbuflist->ibo.fdots);
DRW_vbo_request(cache.batch.edit_fdots, &mbuflist->vbo.fdots_pos);
DRW_vbo_request(cache.batch.edit_fdots, &mbuflist->vbo.fdots_nor);
}
else {
init_empty_dummy_batch(*cache.batch.edit_fdots);
}
}
assert_deps_valid(MBC_SKIN_ROOTS, {BUFFER_INDEX(vbo.skin_roots)});
if (DRW_batch_requested(cache.batch.edit_skin_roots, GPU_PRIM_POINTS)) {
DRW_vbo_request(cache.batch.edit_skin_roots, &mbuflist->vbo.skin_roots);
if (edit_mapping_valid) {
DRW_vbo_request(cache.batch.edit_skin_roots, &mbuflist->vbo.skin_roots);
}
else {
init_empty_dummy_batch(*cache.batch.edit_skin_roots);
}
}
/* Selection */
assert_deps_valid(MBC_EDIT_SELECTION_VERTS,
{BUFFER_INDEX(ibo.points), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.vert_idx)});
if (DRW_batch_requested(cache.batch.edit_selection_verts, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edit_selection_verts, &mbuflist->ibo.points);
DRW_vbo_request(cache.batch.edit_selection_verts, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_selection_verts, &mbuflist->vbo.vert_idx);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_selection_verts, &mbuflist->ibo.points);
DRW_vbo_request(cache.batch.edit_selection_verts, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_selection_verts, &mbuflist->vbo.vert_idx);
}
else {
init_empty_dummy_batch(*cache.batch.edit_selection_verts);
}
}
assert_deps_valid(MBC_EDIT_SELECTION_EDGES,
{BUFFER_INDEX(ibo.lines), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.edge_idx)});
if (DRW_batch_requested(cache.batch.edit_selection_edges, GPU_PRIM_LINES)) {
DRW_ibo_request(cache.batch.edit_selection_edges, &mbuflist->ibo.lines);
DRW_vbo_request(cache.batch.edit_selection_edges, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_selection_edges, &mbuflist->vbo.edge_idx);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_selection_edges, &mbuflist->ibo.lines);
DRW_vbo_request(cache.batch.edit_selection_edges, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_selection_edges, &mbuflist->vbo.edge_idx);
}
else {
init_empty_dummy_batch(*cache.batch.edit_selection_edges);
}
}
assert_deps_valid(MBC_EDIT_SELECTION_FACES,
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.face_idx)});
if (DRW_batch_requested(cache.batch.edit_selection_faces, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache.batch.edit_selection_faces, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.edit_selection_faces, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_selection_faces, &mbuflist->vbo.face_idx);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_selection_faces, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.edit_selection_faces, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.edit_selection_faces, &mbuflist->vbo.face_idx);
}
else {
init_empty_dummy_batch(*cache.batch.edit_selection_faces);
}
}
assert_deps_valid(
MBC_EDIT_SELECTION_FACEDOTS,
{BUFFER_INDEX(ibo.fdots), BUFFER_INDEX(vbo.fdots_pos), BUFFER_INDEX(vbo.fdot_idx)});
if (DRW_batch_requested(cache.batch.edit_selection_fdots, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edit_selection_fdots, &mbuflist->ibo.fdots);
DRW_vbo_request(cache.batch.edit_selection_fdots, &mbuflist->vbo.fdots_pos);
DRW_vbo_request(cache.batch.edit_selection_fdots, &mbuflist->vbo.fdot_idx);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edit_selection_fdots, &mbuflist->ibo.fdots);
DRW_vbo_request(cache.batch.edit_selection_fdots, &mbuflist->vbo.fdots_pos);
DRW_vbo_request(cache.batch.edit_selection_fdots, &mbuflist->vbo.fdot_idx);
}
else {
init_empty_dummy_batch(*cache.batch.edit_selection_fdots);
}
}
/**
@@ -1754,9 +1845,14 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
MBC_EDITUV_FACES,
{BUFFER_INDEX(ibo.edituv_tris), BUFFER_INDEX(vbo.uv), BUFFER_INDEX(vbo.edituv_data)});
if (DRW_batch_requested(cache.batch.edituv_faces, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache.batch.edituv_faces, &mbuflist->ibo.edituv_tris);
DRW_vbo_request(cache.batch.edituv_faces, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_faces, &mbuflist->vbo.edituv_data);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edituv_faces, &mbuflist->ibo.edituv_tris);
DRW_vbo_request(cache.batch.edituv_faces, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_faces, &mbuflist->vbo.edituv_data);
}
else {
init_empty_dummy_batch(*cache.batch.edituv_faces);
}
}
assert_deps_valid(MBC_EDITUV_FACES_STRETCH_AREA,
{BUFFER_INDEX(ibo.edituv_tris),
@@ -1764,10 +1860,15 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
BUFFER_INDEX(vbo.edituv_data),
BUFFER_INDEX(vbo.edituv_stretch_area)});
if (DRW_batch_requested(cache.batch.edituv_faces_stretch_area, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->ibo.edituv_tris);
DRW_vbo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->vbo.edituv_data);
DRW_vbo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->vbo.edituv_stretch_area);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->ibo.edituv_tris);
DRW_vbo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->vbo.edituv_data);
DRW_vbo_request(cache.batch.edituv_faces_stretch_area, &mbuflist->vbo.edituv_stretch_area);
}
else {
init_empty_dummy_batch(*cache.batch.edituv_faces_stretch_area);
}
}
assert_deps_valid(MBC_EDITUV_FACES_STRETCH_ANGLE,
{BUFFER_INDEX(ibo.edituv_tris),
@@ -1775,43 +1876,68 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph &task_graph,
BUFFER_INDEX(vbo.edituv_data),
BUFFER_INDEX(vbo.edituv_stretch_angle)});
if (DRW_batch_requested(cache.batch.edituv_faces_stretch_angle, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->ibo.edituv_tris);
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_data);
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_stretch_angle);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->ibo.edituv_tris);
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_data);
DRW_vbo_request(cache.batch.edituv_faces_stretch_angle, &mbuflist->vbo.edituv_stretch_angle);
}
else {
init_empty_dummy_batch(*cache.batch.edituv_faces_stretch_angle);
}
}
assert_deps_valid(
MBC_EDITUV_EDGES,
{BUFFER_INDEX(ibo.edituv_lines), BUFFER_INDEX(vbo.uv), BUFFER_INDEX(vbo.edituv_data)});
if (DRW_batch_requested(cache.batch.edituv_edges, GPU_PRIM_LINES)) {
DRW_ibo_request(cache.batch.edituv_edges, &mbuflist->ibo.edituv_lines);
DRW_vbo_request(cache.batch.edituv_edges, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_edges, &mbuflist->vbo.edituv_data);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edituv_edges, &mbuflist->ibo.edituv_lines);
DRW_vbo_request(cache.batch.edituv_edges, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_edges, &mbuflist->vbo.edituv_data);
}
else {
init_empty_dummy_batch(*cache.batch.edituv_edges);
}
}
assert_deps_valid(
MBC_EDITUV_VERTS,
{BUFFER_INDEX(ibo.edituv_points), BUFFER_INDEX(vbo.uv), BUFFER_INDEX(vbo.edituv_data)});
if (DRW_batch_requested(cache.batch.edituv_verts, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edituv_verts, &mbuflist->ibo.edituv_points);
DRW_vbo_request(cache.batch.edituv_verts, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_verts, &mbuflist->vbo.edituv_data);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edituv_verts, &mbuflist->ibo.edituv_points);
DRW_vbo_request(cache.batch.edituv_verts, &mbuflist->vbo.uv);
DRW_vbo_request(cache.batch.edituv_verts, &mbuflist->vbo.edituv_data);
}
else {
init_empty_dummy_batch(*cache.batch.edituv_verts);
}
}
assert_deps_valid(MBC_EDITUV_FACEDOTS,
{BUFFER_INDEX(ibo.edituv_fdots),
BUFFER_INDEX(vbo.fdots_uv),
BUFFER_INDEX(vbo.fdots_edituv_data)});
if (DRW_batch_requested(cache.batch.edituv_fdots, GPU_PRIM_POINTS)) {
DRW_ibo_request(cache.batch.edituv_fdots, &mbuflist->ibo.edituv_fdots);
DRW_vbo_request(cache.batch.edituv_fdots, &mbuflist->vbo.fdots_uv);
DRW_vbo_request(cache.batch.edituv_fdots, &mbuflist->vbo.fdots_edituv_data);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.edituv_fdots, &mbuflist->ibo.edituv_fdots);
DRW_vbo_request(cache.batch.edituv_fdots, &mbuflist->vbo.fdots_uv);
DRW_vbo_request(cache.batch.edituv_fdots, &mbuflist->vbo.fdots_edituv_data);
}
else {
init_empty_dummy_batch(*cache.batch.edituv_fdots);
}
}
assert_deps_valid(
MBC_VIEWER_ATTRIBUTE_OVERLAY,
{BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.pos), BUFFER_INDEX(vbo.attr_viewer)});
if (DRW_batch_requested(cache.batch.surface_viewer_attribute, GPU_PRIM_TRIS)) {
DRW_ibo_request(cache.batch.surface_viewer_attribute, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.surface_viewer_attribute, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.surface_viewer_attribute, &mbuflist->vbo.attr_viewer);
if (edit_mapping_valid) {
DRW_ibo_request(cache.batch.surface_viewer_attribute, &mbuflist->ibo.tris);
DRW_vbo_request(cache.batch.surface_viewer_attribute, &mbuflist->vbo.pos);
DRW_vbo_request(cache.batch.surface_viewer_attribute, &mbuflist->vbo.attr_viewer);
}
else {
init_empty_dummy_batch(*cache.batch.surface_viewer_attribute);
}
}
#ifndef NDEBUG

View File

@@ -189,7 +189,7 @@ bool DRW_object_is_renderable(const Object *ob)
BLI_assert((ob->base_flag & BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT) != 0);
if (ob->type == OB_MESH) {
if ((ob == DST.draw_ctx.object_edit) || DRW_object_is_in_edit_mode(ob)) {
if ((ob == DST.draw_ctx.object_edit) || ob->mode == OB_MODE_EDIT) {
View3D *v3d = DST.draw_ctx.v3d;
if (v3d && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) && RETOPOLOGY_ENABLED(v3d)) {
return false;