Refactor: Select Engine: Draw actual indices instead of 'Original Indices' #119977

Merged
Germano Cavalcante merged 6 commits from mano-wii/blender:draw_select_id_cleanup into main 2024-04-16 14:58:12 +02:00
5 changed files with 73 additions and 71 deletions

View File

@ -68,7 +68,8 @@ struct SELECTID_Context {
/* `draw_select_buffer.cc` */
bool DRW_select_buffer_elem_get(uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type);
bool DRW_select_buffer_elem_get(
uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type, bool use_orig_index);
mano-wii marked this conversation as resolved Outdated

const bool -> bool

`const bool` -> `bool`
uint DRW_select_buffer_context_offset_for_object_elem(Depsgraph *depsgraph,
Object *object,
char elem_type);

View File

@ -93,7 +93,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
blender::gpu::Batch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(mesh);
DRW_shgroup_call_no_cull(face_shgrp, geom_facedots, ob);
}
*r_face_offset = initial_offset + em->bm->totface;
*r_face_offset = initial_offset + mesh->faces_num;
Review

Seems this change is unrelated? Or it's a bug fix that could be applied separately?

Seems this change is unrelated? Or it's a bug fix that could be applied separately?

This change is related, since this offset indicates the number of indexes of the object.
Before we only had the original indices, now we have the real indices that can be greater or less than the original indices.
em->bm->totface: number of original indices
mesh->faces_num: number real of indices

This change is related, since this offset indicates the number of indexes of the object. Before we only had the original indices, now we have the real indices that can be greater or less than the original indices. `em->bm->totface`: number of original indices `mesh->faces_num`: number real of indices
}
else {
if (ob->dt >= OB_SOLID) {
@ -114,7 +114,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge);
DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset);
DRW_shgroup_call_no_cull(edge_shgrp, geom_edges, ob);
*r_edge_offset = *r_face_offset + em->bm->totedge;
*r_edge_offset = *r_face_offset + mesh->edges_num;
}
else {
/* Note that `r_vert_offset` is calculated from `r_edge_offset`.
@ -128,7 +128,7 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert);
DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *(int *)r_edge_offset);
DRW_shgroup_call_no_cull(vert_shgrp, geom_verts, ob);
*r_vert_offset = *r_edge_offset + em->bm->totvert;
*r_vert_offset = *r_edge_offset + mesh->verts_num;
}
else {
*r_vert_offset = *r_edge_offset;

View File

@ -17,6 +17,10 @@
#include "DNA_screen_types.h"
#include "BKE_customdata.hh"
#include "BKE_mesh.hh"
#include "BKE_object.hh"
#include "GPU_select.hh"
#include "DEG_depsgraph.hh"
@ -389,10 +393,41 @@ uint DRW_select_buffer_find_nearest_to_point(Depsgraph *depsgraph,
/** \name Object Utils
* \{ */
bool DRW_select_buffer_elem_get(const uint sel_id,
uint *r_elem,
uint *r_base_index,
char *r_elem_type)
static const CustomData *mesh_customdata_of_type(const Mesh *mesh_eval, char elem_type)
{
switch (elem_type) {
case SCE_SELECT_FACE:
return &mesh_eval->face_data;
case SCE_SELECT_EDGE:
return &mesh_eval->edge_data;
case SCE_SELECT_VERTEX:
return &mesh_eval->vert_data;
mano-wii marked this conversation as resolved
Review

I don't think there should be a default case here. Better to add BLI_assert_unreachable(); and return nullptr outside of the switch.

I don't think there should be a default case here. Better to add `BLI_assert_unreachable();` and `return nullptr` outside of the switch.
}
BLI_assert_unreachable();
return nullptr;
}
static const int *orig_index_from_object_get(const Object *object_eval, char elem_type)
{
if (object_eval->type != OB_MESH) {
return nullptr;
}
/* Keep in sync with the mesh used in #MeshRenderData::mesh. */
const Mesh *mesh_eval = static_cast<const Mesh *>(object_eval->data);
const bool is_editmode = (mesh_eval->runtime->edit_mesh != nullptr) &&
(BKE_object_get_editmesh_eval_final(object_eval) != nullptr) &&
DRW_object_is_in_edit_mode(object_eval);
if (is_editmode) {
mesh_eval = BKE_object_get_editmesh_eval_cage(object_eval);
}
const CustomData *data = mesh_customdata_of_type(mesh_eval, elem_type);
return static_cast<const int *>(CustomData_get_layer(data, CD_ORIGINDEX));
}
bool DRW_select_buffer_elem_get(
const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type, bool use_orig_index)
{
SELECTID_Context *select_ctx = DRW_select_engine_context_get();
@ -424,8 +459,6 @@ bool DRW_select_buffer_elem_get(const uint sel_id,
return false;
}
*r_elem = elem_id;
if (r_base_index) {
*r_base_index = base_index;
}
@ -434,6 +467,16 @@ bool DRW_select_buffer_elem_get(const uint sel_id,
*r_elem_type = elem_type;
}
if (use_orig_index) {
const Object *object_eval = select_ctx->objects[base_index];
const int *orig_index = orig_index_from_object_get(object_eval, elem_type);
if (orig_index) {
elem_id = orig_index[elem_id];
}
}
*r_elem = elem_id;
return true;
}

View File

@ -38,11 +38,6 @@ static void extract_select_idx_init(const MeshRenderData &mr,
extract_select_idx_init_impl(mr, mr.corners_num + mr.loose_indices_num, buf, tls_data);
}
/* TODO: Use #glVertexID to get loop index and use the data structure on the CPU to retrieve the
* select element associated with this loop ID. This would remove the need for this separate
* index VBO's. We could upload the p/e/v_origindex as a buffer texture and sample it inside the
* shader to output original index. */
static void extract_face_idx_iter_face_bm(const MeshRenderData & /*mr*/,
const BMFace *f,
const int f_index,
@ -115,7 +110,7 @@ static void extract_face_idx_iter_face_mesh(const MeshRenderData &mr,
void *data)
{
for (const int corner : mr.faces[face_index]) {
(*(int32_t **)data)[corner] = (mr.p_origindex) ? mr.p_origindex[face_index] : face_index;
(*(int32_t **)data)[corner] = face_index;
}
}
@ -125,7 +120,7 @@ static void extract_edge_idx_iter_face_mesh(const MeshRenderData &mr,
{
for (const int corner : mr.faces[face_index]) {
const int edge = mr.corner_edges[corner];
(*(int32_t **)data)[corner] = (mr.e_origindex) ? mr.e_origindex[edge] : edge;
(*(int32_t **)data)[corner] = edge;
}
}
@ -135,7 +130,7 @@ static void extract_vert_idx_iter_face_mesh(const MeshRenderData &mr,
{
for (const int corner : mr.faces[face_index]) {
const int vert = mr.corner_verts[corner];
(*(int32_t **)data)[corner] = (mr.v_origindex) ? mr.v_origindex[vert] : vert;
(*(int32_t **)data)[corner] = vert;
}
}
@ -145,9 +140,8 @@ static void extract_edge_idx_iter_loose_edge_mesh(const MeshRenderData &mr,
void *data)
{
const int e_index = mr.loose_edges[loose_edge_i];
const int e_orig = (mr.e_origindex) ? mr.e_origindex[e_index] : e_index;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 0] = e_orig;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 1] = e_orig;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 0] = e_index;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 1] = e_index;
}
static void extract_vert_idx_iter_loose_edge_mesh(const MeshRenderData &mr,
@ -155,8 +149,8 @@ static void extract_vert_idx_iter_loose_edge_mesh(const MeshRenderData &mr,
const int loose_edge_i,
void *data)
{
int v1_orig = (mr.v_origindex) ? mr.v_origindex[edge[0]] : edge[0];
int v2_orig = (mr.v_origindex) ? mr.v_origindex[edge[1]] : edge[1];
int v1_orig = edge[0];
int v2_orig = edge[1];
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 0] = v1_orig;
(*(int32_t **)data)[mr.corners_num + loose_edge_i * 2 + 1] = v2_orig;
}
@ -168,12 +162,11 @@ static void extract_vert_idx_iter_loose_vert_mesh(const MeshRenderData &mr,
const int offset = mr.corners_num + (mr.loose_edges_num * 2);
const int v_index = mr.loose_verts[loose_vert_i];
const int v_orig = (mr.v_origindex) ? mr.v_origindex[v_index] : v_index;
(*(int32_t **)data)[offset + loose_vert_i] = v_orig;
(*(int32_t **)data)[offset + loose_vert_i] = v_index;
}
static void extract_vert_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
const MeshRenderData & /*mr*/,
MeshBatchCache & /*cache*/,
void *buf,
void * /*data*/)
@ -185,24 +178,10 @@ static void extract_vert_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
(int32_t *)GPU_vertbuf_get_data(subdiv_cache.verts_orig_index),
subdiv_cache.num_subdiv_loops,
loose_geom.loop_len);
if (!mr.v_origindex) {
return;
}
/* Remap the vertex indices to those pointed by the origin indices layer. At this point, the
* VBO data is a copy of #verts_orig_index which contains the coarse vertices indices, so
* the memory can both be accessed for lookup and immediately overwritten. */
int32_t *vbo_data = static_cast<int32_t *>(GPU_vertbuf_get_data(vbo));
for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
if (vbo_data[i] == -1) {
continue;
}
vbo_data[i] = mr.v_origindex[vbo_data[i]];
}
}
static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
const MeshRenderData & /*mr*/,
void *buffer,
void * /*data*/)
{
@ -222,13 +201,11 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cach
const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index];
if (v1.coarse_vertex_index != -1u) {
vert_idx_data[offset] = mr.v_origindex ? mr.v_origindex[v1.coarse_vertex_index] :
v1.coarse_vertex_index;
vert_idx_data[offset] = v1.coarse_vertex_index;
}
if (v2.coarse_vertex_index != -1u) {
vert_idx_data[offset + 1] = mr.v_origindex ? mr.v_origindex[v2.coarse_vertex_index] :
v2.coarse_vertex_index;
vert_idx_data[offset + 1] = v2.coarse_vertex_index;
}
offset += 2;
@ -237,8 +214,7 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cach
Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts(subdiv_cache);
for (const DRWSubdivLooseVertex &loose_vert : loose_verts) {
vert_idx_data[offset] = mr.v_origindex ? mr.v_origindex[loose_vert.coarse_vertex_index] :
loose_vert.coarse_vertex_index;
vert_idx_data[offset] = loose_vert.coarse_vertex_index;
offset += 1;
}
}
@ -259,7 +235,7 @@ static void extract_edge_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
}
static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
const MeshRenderData & /*mr*/,
void *buffer,
void * /*data*/)
{
@ -274,8 +250,7 @@ static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cach
Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache);
for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
const int coarse_edge_index = mr.e_origindex ? mr.e_origindex[loose_edge.coarse_edge_index] :
loose_edge.coarse_edge_index;
const int coarse_edge_index = loose_edge.coarse_edge_index;
vert_idx_data[offset] = coarse_edge_index;
vert_idx_data[offset + 1] = coarse_edge_index;
offset += 2;
@ -283,7 +258,7 @@ static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache &subdiv_cach
}
static void extract_face_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
const MeshRenderData &mr,
const MeshRenderData & /*mr*/,
MeshBatchCache & /*cache*/,
void *buf,
void * /*data*/)
@ -291,18 +266,6 @@ static void extract_face_idx_init_subdiv(const DRWSubdivCache &subdiv_cache,
gpu::VertBuf *vbo = static_cast<gpu::VertBuf *>(buf);
draw_subdiv_init_origindex_buffer(
vbo, subdiv_cache.subdiv_loop_face_index, subdiv_cache.num_subdiv_loops, 0);
if (!mr.p_origindex) {
return;
}
/* Remap the face indices to those pointed by the origin indices layer. At this point, the
* VBO data is a copy of #subdiv_loop_face_index which contains the coarse face indices, so
* the memory can both be accessed for lookup and immediately overwritten. */
int32_t *vbo_data = static_cast<int32_t *>(GPU_vertbuf_get_data(vbo));
for (int i = 0; i < subdiv_cache.num_subdiv_loops; i++) {
vbo_data[i] = mr.p_origindex[vbo_data[i]];
}
}
constexpr MeshExtract create_extractor_face_idx()
@ -371,16 +334,11 @@ static void extract_fdot_idx_iter_face_bm(const MeshRenderData & /*mr*/,
(*(int32_t **)data)[f_index] = f_index;
}
static void extract_fdot_idx_iter_face_mesh(const MeshRenderData &mr,
static void extract_fdot_idx_iter_face_mesh(const MeshRenderData & /*mr*/,
const int face_index,
void *data)
{
if (mr.p_origindex != nullptr) {
(*(int32_t **)data)[face_index] = mr.p_origindex[face_index];
}
else {
(*(int32_t **)data)[face_index] = face_index;
}
(*(int32_t **)data)[face_index] = face_index;
}
constexpr MeshExtract create_extractor_fdot_idx()

View File

@ -182,7 +182,7 @@ static BMElem *edbm_select_id_bm_elem_get(const Span<Base *> bases,
{
uint elem_id;
char elem_type = 0;
bool success = DRW_select_buffer_elem_get(sel_id, &elem_id, r_base_index, &elem_type);
bool success = DRW_select_buffer_elem_get(sel_id, &elem_id, r_base_index, &elem_type, true);
if (success) {
Object *obedit = bases[*r_base_index]->object;