Mesh: Draw: Replace extractor abstraction for UV edit index buffers
Part of #116901. This file contains the creation of four different UV edit index buffers: triangles, lines, points, and face dots. The main changes are about making it clearer when faces are skipped. Other than that, changes are faily extensive but straightfoward. In a few places some parts of existing loops have been split out and parallelized, but the bulk of the work for each IBO remains largely single threaded.
This commit is contained in:
@@ -649,11 +649,6 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
}
|
||||
EXTRACT_ADD_REQUESTED(vbo, attr_viewer);
|
||||
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_tris);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_lines);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_points);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_fdots);
|
||||
|
||||
#undef EXTRACT_ADD_REQUESTED
|
||||
|
||||
if (extractors.is_empty() && !DRW_ibo_requested(buffers.ibo.lines) &&
|
||||
@@ -669,7 +664,10 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
!DRW_vbo_requested(buffers.vbo.fdots_edituv_data) && !DRW_vbo_requested(buffers.vbo.uv) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_stretch_area) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_stretch_angle) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_data) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_data) && !DRW_ibo_requested(buffers.ibo.edituv_tris) &&
|
||||
!DRW_ibo_requested(buffers.ibo.edituv_lines) &&
|
||||
!DRW_ibo_requested(buffers.ibo.edituv_points) &&
|
||||
!DRW_ibo_requested(buffers.ibo.edituv_fdots) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_paint_mask) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_adjacency) &&
|
||||
!DRW_vbo_requested(buffers.vbo.skin_roots) && !DRW_vbo_requested(buffers.vbo.sculpt_data) &&
|
||||
@@ -1039,6 +1037,66 @@ void mesh_buffer_cache_create_requested(TaskGraph &task_graph,
|
||||
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
|
||||
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.edituv_tris)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
MeshBufferList &buffers;
|
||||
};
|
||||
TaskNode *task_node = BLI_task_graph_node_create(
|
||||
&task_graph,
|
||||
[](void *__restrict task_data) {
|
||||
const TaskData &data = *static_cast<TaskData *>(task_data);
|
||||
extract_edituv_tris(data.mr, *data.buffers.ibo.edituv_tris);
|
||||
},
|
||||
new TaskData{*mr, buffers},
|
||||
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
|
||||
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.edituv_lines)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
MeshBufferList &buffers;
|
||||
};
|
||||
TaskNode *task_node = BLI_task_graph_node_create(
|
||||
&task_graph,
|
||||
[](void *__restrict task_data) {
|
||||
const TaskData &data = *static_cast<TaskData *>(task_data);
|
||||
extract_edituv_lines(data.mr, *data.buffers.ibo.edituv_lines);
|
||||
},
|
||||
new TaskData{*mr, buffers},
|
||||
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
|
||||
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.edituv_points)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
MeshBufferList &buffers;
|
||||
};
|
||||
TaskNode *task_node = BLI_task_graph_node_create(
|
||||
&task_graph,
|
||||
[](void *__restrict task_data) {
|
||||
const TaskData &data = *static_cast<TaskData *>(task_data);
|
||||
extract_edituv_points(data.mr, *data.buffers.ibo.edituv_points);
|
||||
},
|
||||
new TaskData{*mr, buffers},
|
||||
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
|
||||
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.edituv_fdots)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
MeshBufferList &buffers;
|
||||
};
|
||||
TaskNode *task_node = BLI_task_graph_node_create(
|
||||
&task_graph,
|
||||
[](void *__restrict task_data) {
|
||||
const TaskData &data = *static_cast<TaskData *>(task_data);
|
||||
extract_edituv_face_dots(data.mr, *data.buffers.ibo.edituv_fdots);
|
||||
},
|
||||
new TaskData{*mr, buffers},
|
||||
[](void *task_data) { delete static_cast<TaskData *>(task_data); });
|
||||
BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.lines_paint_mask)) {
|
||||
struct TaskData {
|
||||
MeshRenderData &mr;
|
||||
@@ -1224,10 +1282,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
EXTRACT_ADD_REQUESTED(vbo, attr[i]);
|
||||
}
|
||||
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_points);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_tris);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_lines);
|
||||
|
||||
#undef EXTRACT_ADD_REQUESTED
|
||||
|
||||
if (extractors.is_empty() && !DRW_ibo_requested(buffers.ibo.lines) &&
|
||||
@@ -1241,7 +1295,9 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
!DRW_vbo_requested(buffers.vbo.fdots_pos) && !DRW_ibo_requested(buffers.ibo.fdots) &&
|
||||
!DRW_vbo_requested(buffers.vbo.uv) && !DRW_vbo_requested(buffers.vbo.edituv_stretch_area) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_stretch_angle) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_data) &&
|
||||
!DRW_vbo_requested(buffers.vbo.edituv_data) && !DRW_ibo_requested(buffers.ibo.edituv_tris) &&
|
||||
!DRW_ibo_requested(buffers.ibo.edituv_lines) &&
|
||||
!DRW_ibo_requested(buffers.ibo.edituv_points) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_paint_mask) &&
|
||||
!DRW_ibo_requested(buffers.ibo.lines_adjacency) &&
|
||||
!DRW_vbo_requested(buffers.vbo.sculpt_data))
|
||||
@@ -1322,6 +1378,15 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache &cache,
|
||||
if (DRW_vbo_requested(buffers.vbo.edituv_data)) {
|
||||
extract_edituv_data_subdiv(mr, subdiv_cache, *buffers.vbo.edituv_data);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.edituv_tris)) {
|
||||
extract_edituv_tris_subdiv(mr, subdiv_cache, *buffers.ibo.edituv_tris);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.edituv_lines)) {
|
||||
extract_edituv_lines_subdiv(mr, subdiv_cache, *buffers.ibo.edituv_lines);
|
||||
}
|
||||
if (DRW_ibo_requested(buffers.ibo.edituv_points)) {
|
||||
extract_edituv_points_subdiv(mr, subdiv_cache, *buffers.ibo.edituv_points);
|
||||
}
|
||||
|
||||
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
|
||||
uint32_t data_offset = 0;
|
||||
|
||||
@@ -475,6 +475,19 @@ void extract_edituv_data(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
void extract_edituv_data_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::VertBuf &vbo);
|
||||
void extract_edituv_tris(const MeshRenderData &mr, gpu::IndexBuf &ibo);
|
||||
void extract_edituv_tris_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::IndexBuf &ibo);
|
||||
void extract_edituv_lines(const MeshRenderData &mr, gpu::IndexBuf &ibo);
|
||||
void extract_edituv_lines_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::IndexBuf &ibo);
|
||||
void extract_edituv_points(const MeshRenderData &mr, gpu::IndexBuf &ibo);
|
||||
void extract_edituv_points_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::IndexBuf &ibo);
|
||||
void extract_edituv_face_dots(const MeshRenderData &mr, gpu::IndexBuf &ibo);
|
||||
|
||||
void extract_skin_roots(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
|
||||
@@ -487,10 +500,6 @@ void extract_orco(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
|
||||
void extract_mesh_analysis(const MeshRenderData &mr, gpu::VertBuf &vbo);
|
||||
|
||||
extern const MeshExtract extract_edituv_tris;
|
||||
extern const MeshExtract extract_edituv_lines;
|
||||
extern const MeshExtract extract_edituv_points;
|
||||
extern const MeshExtract extract_edituv_fdots;
|
||||
extern const MeshExtract extract_attr[GPU_MAX_ATTR];
|
||||
extern const MeshExtract extract_attr_viewer;
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
* \ingroup draw
|
||||
*/
|
||||
|
||||
#include "BKE_editmesh.hh"
|
||||
|
||||
#include "extract_mesh.hh"
|
||||
|
||||
#include "GPU_index_buffer.hh"
|
||||
@@ -13,155 +15,135 @@
|
||||
#include "draw_subdivision.hh"
|
||||
|
||||
namespace blender::draw {
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Extract Edit UV Triangles Indices
|
||||
* \{ */
|
||||
|
||||
struct MeshExtract_EditUvElem_Data {
|
||||
GPUIndexBufBuilder elb;
|
||||
Span<int> corner_tri_faces;
|
||||
bool sync_selection;
|
||||
};
|
||||
|
||||
static void extract_edituv_tris_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*ibo*/,
|
||||
void *tls_data)
|
||||
inline bool skip_bm_face(const BMFace &face, const bool sync_selection)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
|
||||
GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, mr.corner_tris_num, mr.corners_num);
|
||||
if (mr.extract_type == MR_EXTRACT_MESH) {
|
||||
data->corner_tri_faces = mr.mesh->corner_tri_faces();
|
||||
if (BM_elem_flag_test(&face, BM_ELEM_HIDDEN)) {
|
||||
return true;
|
||||
}
|
||||
data->sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
if (!sync_selection) {
|
||||
if (!BM_elem_flag_test_bool(&face, BM_ELEM_SELECT)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
BLI_INLINE void edituv_tri_add(
|
||||
MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2, int v3)
|
||||
static void extract_edituv_tris_bm(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
if (!hidden && (data->sync_selection || selected)) {
|
||||
GPU_indexbuf_add_tri_verts(&data->elb, v1, v2, v3);
|
||||
const Span<std::array<BMLoop *, 3>> looptris = mr.edit_bmesh->looptris;
|
||||
for (const int i : looptris.index_range()) {
|
||||
const std::array<BMLoop *, 3> &tri = looptris[i];
|
||||
if (skip_bm_face(*tri[0]->f, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
GPU_indexbuf_add_tri_verts(
|
||||
&builder, BM_elem_index_get(tri[0]), BM_elem_index_get(tri[1]), BM_elem_index_get(tri[2]));
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_tris_iter_looptri_bm(const MeshRenderData & /*mr*/,
|
||||
BMLoop **elt,
|
||||
const int /*elt_index*/,
|
||||
void *_data)
|
||||
static void extract_edituv_tris_mesh(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
edituv_tri_add(data,
|
||||
BM_elem_flag_test(elt[0]->f, BM_ELEM_HIDDEN),
|
||||
BM_elem_flag_test(elt[0]->f, BM_ELEM_SELECT),
|
||||
BM_elem_index_get(elt[0]),
|
||||
BM_elem_index_get(elt[1]),
|
||||
BM_elem_index_get(elt[2]));
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<int3> corner_tris = mr.mesh->corner_tris();
|
||||
for (const int face : faces.index_range()) {
|
||||
const BMFace *face_orig = bm_original_face_get(mr, face);
|
||||
if (!face_orig) {
|
||||
continue;
|
||||
}
|
||||
if (skip_bm_face(*face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
const IndexRange tris = bke::mesh::face_triangles_range(faces, face);
|
||||
for (const int3 &tri : corner_tris.slice(tris)) {
|
||||
GPU_indexbuf_add_tri_verts(&builder, tri[0], tri[1], tri[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_tris_iter_corner_tri_mesh(const MeshRenderData &mr,
|
||||
const int3 &tri,
|
||||
const int elt_index,
|
||||
void *_data)
|
||||
void extract_edituv_tris(const MeshRenderData &mr, gpu::IndexBuf &ibo)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
const int face_i = data->corner_tri_faces[elt_index];
|
||||
const BMFace *efa = bm_original_face_get(mr, face_i);
|
||||
const bool mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
|
||||
const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
|
||||
const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
|
||||
edituv_tri_add(data, mp_hidden, mp_select, tri[0], tri[1], tri[2]);
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(&builder, GPU_PRIM_TRIS, mr.corner_tris_num, mr.corners_num);
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_tris_bm(mr, sync_selection, builder);
|
||||
}
|
||||
else {
|
||||
extract_edituv_tris_mesh(mr, sync_selection, builder);
|
||||
}
|
||||
|
||||
GPU_indexbuf_build_in_place(&builder, &ibo);
|
||||
}
|
||||
|
||||
static void extract_edituv_tris_finish(const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *_data)
|
||||
static void extract_edituv_tris_subdiv_bm(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPU_indexbuf_build_in_place(&data->elb, ibo);
|
||||
const BMesh &bm = *mr.bm;
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
for (const int subdiv_quad_index : IndexRange(subdiv_cache.num_subdiv_quads)) {
|
||||
const uint corner_start = subdiv_quad_index * 4;
|
||||
const int coarse_face = subdiv_loop_face_index[corner_start];
|
||||
const BMFace &face_orig = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
|
||||
if (skip_bm_face(face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
GPU_indexbuf_add_tri_verts(&builder, corner_start, corner_start + 1, corner_start + 2);
|
||||
GPU_indexbuf_add_tri_verts(&builder, corner_start, corner_start + 2, corner_start + 3);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_tris_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*buf*/,
|
||||
void *tls_data)
|
||||
static void extract_edituv_tris_subdiv_mesh(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
for (const int subdiv_quad_index : IndexRange(subdiv_cache.num_subdiv_quads)) {
|
||||
const uint corner_start = subdiv_quad_index * 4;
|
||||
const int coarse_face = subdiv_loop_face_index[corner_start];
|
||||
const BMFace *face_orig = bm_original_face_get(mr, coarse_face);
|
||||
if (!face_orig) {
|
||||
continue;
|
||||
}
|
||||
if (skip_bm_face(*face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
GPU_indexbuf_add_tri_verts(&builder, corner_start, corner_start + 1, corner_start + 2);
|
||||
GPU_indexbuf_add_tri_verts(&builder, corner_start, corner_start + 2, corner_start + 3);
|
||||
}
|
||||
}
|
||||
|
||||
void extract_edituv_tris_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::IndexBuf &ibo)
|
||||
{
|
||||
const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(
|
||||
&data->elb, GPU_PRIM_TRIS, subdiv_cache.num_subdiv_triangles, subdiv_cache.num_subdiv_loops);
|
||||
data->sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
}
|
||||
&builder, GPU_PRIM_TRIS, subdiv_cache.num_subdiv_triangles, subdiv_cache.num_subdiv_loops);
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_tris_subdiv_bm(mr, subdiv_cache, sync_selection, builder);
|
||||
}
|
||||
else {
|
||||
extract_edituv_tris_subdiv_mesh(mr, subdiv_cache, sync_selection, builder);
|
||||
}
|
||||
|
||||
static void extract_edituv_tris_iter_subdiv_bm(const DRWSubdivCache & /*subdiv_cache*/,
|
||||
const MeshRenderData & /*mr*/,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const BMFace *coarse_quad)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
const uint loop_idx = subdiv_quad_index * 4;
|
||||
|
||||
edituv_tri_add(data,
|
||||
BM_elem_flag_test(coarse_quad, BM_ELEM_HIDDEN) != 0,
|
||||
BM_elem_flag_test(coarse_quad, BM_ELEM_SELECT) != 0,
|
||||
loop_idx,
|
||||
loop_idx + 1,
|
||||
loop_idx + 2);
|
||||
|
||||
edituv_tri_add(data,
|
||||
BM_elem_flag_test(coarse_quad, BM_ELEM_HIDDEN) != 0,
|
||||
BM_elem_flag_test(coarse_quad, BM_ELEM_SELECT) != 0,
|
||||
loop_idx,
|
||||
loop_idx + 2,
|
||||
loop_idx + 3);
|
||||
}
|
||||
|
||||
static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache & /*subdiv_cache*/,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const int coarse_quad_index)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
const uint loop_idx = subdiv_quad_index * 4;
|
||||
|
||||
const BMFace *efa = bm_original_face_get(mr, coarse_quad_index);
|
||||
const bool mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
|
||||
const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
|
||||
|
||||
edituv_tri_add(data, mp_hidden, mp_select, loop_idx, loop_idx + 1, loop_idx + 2);
|
||||
edituv_tri_add(data, mp_hidden, mp_select, loop_idx, loop_idx + 2, loop_idx + 3);
|
||||
}
|
||||
|
||||
static void extract_edituv_tris_finish_subdiv(const DRWSubdivCache & /*subdiv_cache*/,
|
||||
const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPU_indexbuf_build_in_place(&data->elb, ibo);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_edituv_tris()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_edituv_tris_init;
|
||||
extractor.iter_looptri_bm = extract_edituv_tris_iter_looptri_bm;
|
||||
extractor.iter_corner_tri_mesh = extract_edituv_tris_iter_corner_tri_mesh;
|
||||
extractor.finish = extract_edituv_tris_finish;
|
||||
extractor.init_subdiv = extract_edituv_tris_init_subdiv;
|
||||
extractor.iter_subdiv_bm = extract_edituv_tris_iter_subdiv_bm;
|
||||
extractor.iter_subdiv_mesh = extract_edituv_tris_iter_subdiv_mesh;
|
||||
extractor.finish_subdiv = extract_edituv_tris_finish_subdiv;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
|
||||
extractor.use_threading = false;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_tris);
|
||||
return extractor;
|
||||
GPU_indexbuf_build_in_place(&builder, &ibo);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -170,181 +152,188 @@ constexpr MeshExtract create_extractor_edituv_tris()
|
||||
/** \name Extract Edit UV Line Indices around faces
|
||||
* \{ */
|
||||
|
||||
static void extract_edituv_lines_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*ibo*/,
|
||||
void *tls_data)
|
||||
static void extract_edituv_lines_bm(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
|
||||
GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES, mr.corners_num, mr.corners_num);
|
||||
data->sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
}
|
||||
|
||||
BLI_INLINE void edituv_edge_add(
|
||||
MeshExtract_EditUvElem_Data *data, bool hidden, bool selected, int v1, int v2)
|
||||
{
|
||||
if (!hidden && (data->sync_selection || selected)) {
|
||||
GPU_indexbuf_add_line_verts(&data->elb, v1, v2);
|
||||
const BMesh &bm = *mr.bm;
|
||||
const BMFace *face;
|
||||
BMIter f_iter;
|
||||
BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
|
||||
if (skip_bm_face(*face, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
|
||||
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
|
||||
GPU_indexbuf_add_line_verts(
|
||||
&builder, BM_elem_index_get(loop), BM_elem_index_get(loop->next));
|
||||
loop = loop->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_iter_face_bm(const MeshRenderData & /*mr*/,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *_data)
|
||||
static void extract_edituv_lines_mesh(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
const int l_index = BM_elem_index_get(l_iter);
|
||||
|
||||
edituv_edge_add(data,
|
||||
BM_elem_flag_test_bool(f, BM_ELEM_HIDDEN),
|
||||
BM_elem_flag_test_bool(f, BM_ELEM_SELECT),
|
||||
l_index,
|
||||
BM_elem_index_get(l_iter->next));
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
const IndexRange face = mr.faces[face_index];
|
||||
|
||||
bool mp_hidden, mp_select;
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<int> corner_edges = mr.corner_edges;
|
||||
const Span<int> orig_index_edge = mr.orig_index_edge ?
|
||||
Span<int>(mr.orig_index_edge, mr.edges_num) :
|
||||
Span<int>();
|
||||
if (mr.bm) {
|
||||
const BMFace *efa = bm_original_face_get(mr, face_index);
|
||||
mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
|
||||
mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const IndexRange face = faces[face_index];
|
||||
const BMFace *face_orig = bm_original_face_get(mr, face_index);
|
||||
if (!face_orig) {
|
||||
continue;
|
||||
}
|
||||
if (skip_bm_face(*face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
for (const int corner : face) {
|
||||
const int edge = corner_edges[corner];
|
||||
if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
const int corner_next = bke::mesh::face_corner_next(face, corner);
|
||||
GPU_indexbuf_add_line_verts(&builder, corner, corner_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
mp_hidden = mr.hide_poly.is_empty() ? false : mr.hide_poly[face_index];
|
||||
mp_select = !mr.select_poly.is_empty() && mr.select_poly[face_index];
|
||||
}
|
||||
|
||||
for (const int corner : face) {
|
||||
const int edge = mr.corner_edges[corner];
|
||||
const int corner_next = bke::mesh::face_corner_next(face, corner);
|
||||
|
||||
const bool real_edge = (mr.orig_index_edge == nullptr ||
|
||||
mr.orig_index_edge[edge] != ORIGINDEX_NONE);
|
||||
edituv_edge_add(data, mp_hidden || !real_edge, mp_select, corner, corner_next);
|
||||
IndexMaskMemory memory;
|
||||
IndexMask visible = faces.index_range();
|
||||
if (!mr.hide_poly.is_empty()) {
|
||||
visible = IndexMask::from_bools_inverse(visible, mr.hide_poly, memory);
|
||||
}
|
||||
if (!sync_selection) {
|
||||
if (mr.select_poly.is_empty()) {
|
||||
visible = {};
|
||||
}
|
||||
else {
|
||||
visible = IndexMask::from_bools(visible, mr.select_poly, memory);
|
||||
}
|
||||
}
|
||||
visible.foreach_index([&](const int face_index) {
|
||||
const IndexRange face = faces[face_index];
|
||||
for (const int corner : face) {
|
||||
const int edge = corner_edges[corner];
|
||||
if (!orig_index_edge.is_empty() && orig_index_edge[edge] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
const int corner_next = bke::mesh::face_corner_next(face, corner);
|
||||
GPU_indexbuf_add_line_verts(&builder, corner, corner_next);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_finish(const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *_data)
|
||||
void extract_edituv_lines(const MeshRenderData &mr, gpu::IndexBuf &ibo)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPU_indexbuf_build_in_place(&data->elb, ibo);
|
||||
const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(&builder, GPU_PRIM_LINES, mr.corners_num, mr.corners_num);
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_lines_bm(mr, sync_selection, builder);
|
||||
}
|
||||
else {
|
||||
extract_edituv_lines_mesh(mr, sync_selection, builder);
|
||||
}
|
||||
|
||||
GPU_indexbuf_build_in_place(&builder, &ibo);
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*buf*/,
|
||||
void *tls_data)
|
||||
static void extract_edituv_lines_subdiv_bm(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
|
||||
const BMesh &bm = *mr.bm;
|
||||
const Span<int> subdiv_loop_edge_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)),
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
|
||||
for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
const BMFace &face_orig = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
|
||||
if (skip_bm_face(face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
const IndexRange subdiv_face(subdiv_quad * 4, 4);
|
||||
for (const int subdiv_corner : subdiv_face) {
|
||||
const int coarse_edge = subdiv_loop_edge_index[subdiv_corner];
|
||||
if (coarse_edge == -1) {
|
||||
continue;
|
||||
}
|
||||
const int subdiv_corner_next = bke::mesh::face_corner_next(subdiv_face, subdiv_corner);
|
||||
GPU_indexbuf_add_line_verts(&builder, subdiv_corner, subdiv_corner_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_subdiv_mesh(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
/* NOTE: #subdiv_loop_edge_index already has the origindex layer baked in. */
|
||||
const Span<int> subdiv_loop_edge_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.edges_orig_index)),
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
/* TODO: Replace subdiv quad iteration with coarse face iteration. */
|
||||
for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
if (const BMesh *bm = mr.bm) {
|
||||
const BMFace &face_orig = *BM_face_at_index(const_cast<BMesh *>(bm), coarse_face);
|
||||
if (skip_bm_face(face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!mr.hide_poly.is_empty() && mr.hide_poly[coarse_face]) {
|
||||
continue;
|
||||
}
|
||||
if (!sync_selection) {
|
||||
if (mr.select_poly.is_empty() || !mr.select_poly[coarse_face]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
const IndexRange subdiv_face(subdiv_quad * 4, 4);
|
||||
for (const int subdiv_corner : subdiv_face) {
|
||||
const int coarse_edge = subdiv_loop_edge_index[subdiv_corner];
|
||||
if (coarse_edge == -1) {
|
||||
continue;
|
||||
}
|
||||
const int subdiv_corner_next = bke::mesh::face_corner_next(subdiv_face, subdiv_corner);
|
||||
GPU_indexbuf_add_line_verts(&builder, subdiv_corner, subdiv_corner_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void extract_edituv_lines_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::IndexBuf &ibo)
|
||||
{
|
||||
const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(
|
||||
&data->elb, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
|
||||
data->sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_iter_subdiv_bm(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const BMFace *coarse_face)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache.edges_orig_index);
|
||||
|
||||
const bool mp_hidden = BM_elem_flag_test_bool(coarse_face, BM_ELEM_HIDDEN);
|
||||
const bool mp_select = BM_elem_flag_test_bool(coarse_face, BM_ELEM_SELECT);
|
||||
|
||||
uint start_loop_idx = subdiv_quad_index * 4;
|
||||
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
|
||||
for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) {
|
||||
const int edge_origindex = subdiv_loop_edge_index[loop_idx];
|
||||
const bool real_edge = (edge_origindex != -1 &&
|
||||
(mr.orig_index_edge == nullptr ||
|
||||
mr.orig_index_edge[edge_origindex] != ORIGINDEX_NONE));
|
||||
edituv_edge_add(data,
|
||||
mp_hidden || !real_edge,
|
||||
mp_select,
|
||||
loop_idx,
|
||||
(loop_idx + 1 == end_loop_idx) ? start_loop_idx : (loop_idx + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const int coarse_face_index)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache.edges_orig_index);
|
||||
bool mp_hidden, mp_select;
|
||||
if (mr.bm) {
|
||||
const BMFace *efa = bm_original_face_get(mr, coarse_face_index);
|
||||
mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
|
||||
mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
|
||||
&builder, GPU_PRIM_LINES, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_lines_subdiv_bm(mr, subdiv_cache, sync_selection, builder);
|
||||
}
|
||||
else {
|
||||
mp_hidden = mr.hide_poly.is_empty() ? false : mr.hide_poly[coarse_face_index];
|
||||
mp_select = !mr.select_poly.is_empty() && mr.select_poly[coarse_face_index];
|
||||
extract_edituv_lines_subdiv_mesh(mr, subdiv_cache, sync_selection, builder);
|
||||
}
|
||||
|
||||
uint start_loop_idx = subdiv_quad_index * 4;
|
||||
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
|
||||
for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) {
|
||||
const int edge_origindex = subdiv_loop_edge_index[loop_idx];
|
||||
const bool real_edge = (edge_origindex != -1 &&
|
||||
(mr.orig_index_edge == nullptr ||
|
||||
mr.orig_index_edge[edge_origindex] != ORIGINDEX_NONE));
|
||||
edituv_edge_add(data,
|
||||
mp_hidden || !real_edge,
|
||||
mp_select,
|
||||
loop_idx,
|
||||
(loop_idx + 1 == end_loop_idx) ? start_loop_idx : (loop_idx + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_lines_finish_subdiv(const DRWSubdivCache & /*subdiv_cache*/,
|
||||
const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPU_indexbuf_build_in_place(&data->elb, ibo);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_edituv_lines()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_edituv_lines_init;
|
||||
extractor.iter_face_bm = extract_edituv_lines_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_edituv_lines_iter_face_mesh;
|
||||
extractor.finish = extract_edituv_lines_finish;
|
||||
extractor.init_subdiv = extract_edituv_lines_init_subdiv;
|
||||
extractor.iter_subdiv_bm = extract_edituv_lines_iter_subdiv_bm;
|
||||
extractor.iter_subdiv_mesh = extract_edituv_lines_iter_subdiv_mesh;
|
||||
extractor.finish_subdiv = extract_edituv_lines_finish_subdiv;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
|
||||
extractor.use_threading = false;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_lines);
|
||||
return extractor;
|
||||
GPU_indexbuf_build_in_place(&builder, &ibo);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -353,153 +342,141 @@ constexpr MeshExtract create_extractor_edituv_lines()
|
||||
/** \name Extract Edit UV Points Indices
|
||||
* \{ */
|
||||
|
||||
static void extract_edituv_points_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*ibo*/,
|
||||
void *tls_data)
|
||||
static void extract_edituv_points_bm(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
|
||||
GPU_indexbuf_init(&data->elb, GPU_PRIM_POINTS, mr.corners_num, mr.corners_num);
|
||||
data->sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
}
|
||||
|
||||
BLI_INLINE void edituv_point_add(MeshExtract_EditUvElem_Data *data,
|
||||
bool hidden,
|
||||
bool selected,
|
||||
int v1)
|
||||
{
|
||||
if (!hidden && (data->sync_selection || selected)) {
|
||||
GPU_indexbuf_add_point_vert(&data->elb, v1);
|
||||
const BMesh &bm = *mr.bm;
|
||||
const BMFace *face;
|
||||
BMIter f_iter;
|
||||
BM_ITER_MESH (face, &f_iter, &const_cast<BMesh &>(bm), BM_FACES_OF_MESH) {
|
||||
if (skip_bm_face(*face, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
const BMLoop *loop = BM_FACE_FIRST_LOOP(face);
|
||||
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
|
||||
GPU_indexbuf_add_point_vert(&builder, BM_elem_index_get(loop));
|
||||
loop = loop->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_points_iter_face_bm(const MeshRenderData & /*mr*/,
|
||||
const BMFace *f,
|
||||
const int /*f_index*/,
|
||||
void *_data)
|
||||
static void extract_edituv_points_mesh(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
BMLoop *l_iter, *l_first;
|
||||
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
|
||||
do {
|
||||
const int l_index = BM_elem_index_get(l_iter);
|
||||
|
||||
edituv_point_add(
|
||||
data, BM_elem_flag_test(f, BM_ELEM_HIDDEN), BM_elem_flag_test(f, BM_ELEM_SELECT), l_index);
|
||||
} while ((l_iter = l_iter->next) != l_first);
|
||||
}
|
||||
|
||||
static void extract_edituv_points_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
|
||||
const BMFace *efa = bm_original_face_get(mr, face_index);
|
||||
const bool mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
|
||||
const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
|
||||
|
||||
for (const int corner : mr.faces[face_index]) {
|
||||
const int vert = mr.corner_verts[corner];
|
||||
|
||||
const bool real_vert = !mr.orig_index_vert || mr.orig_index_vert[vert] != ORIGINDEX_NONE;
|
||||
edituv_point_add(data, mp_hidden || !real_vert, mp_select, corner);
|
||||
const OffsetIndices faces = mr.faces;
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
const Span<int> orig_index_vert = mr.orig_index_vert ?
|
||||
Span<int>(mr.orig_index_vert, mr.verts_num) :
|
||||
Span<int>();
|
||||
for (const int face_index : faces.index_range()) {
|
||||
const BMFace *face_orig = bm_original_face_get(mr, face_index);
|
||||
if (!face_orig) {
|
||||
continue;
|
||||
}
|
||||
if (skip_bm_face(*face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
for (const int corner : faces[face_index]) {
|
||||
const int vert = corner_verts[corner];
|
||||
if (!orig_index_vert.is_empty() && orig_index_vert[vert] == ORIGINDEX_NONE) {
|
||||
continue;
|
||||
}
|
||||
GPU_indexbuf_add_point_vert(&builder, corner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_points_finish(const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *_data)
|
||||
void extract_edituv_points(const MeshRenderData &mr, gpu::IndexBuf &ibo)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPU_indexbuf_build_in_place(&data->elb, ibo);
|
||||
const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, mr.corners_num, mr.corners_num);
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_points_bm(mr, sync_selection, builder);
|
||||
}
|
||||
else {
|
||||
extract_edituv_points_mesh(mr, sync_selection, builder);
|
||||
}
|
||||
GPU_indexbuf_build_in_place(&builder, &ibo);
|
||||
}
|
||||
|
||||
static void extract_edituv_points_init_subdiv(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*buf*/,
|
||||
void *tls_data)
|
||||
static void extract_edituv_points_subdiv_bm(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
|
||||
const BMesh &bm = *mr.bm;
|
||||
const Span<int> subdiv_loop_vert_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.verts_orig_index)),
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
|
||||
for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
const BMFace &face_orig = *BM_face_at_index(&const_cast<BMesh &>(bm), coarse_face);
|
||||
if (skip_bm_face(face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
|
||||
const int coarse_vert = subdiv_loop_vert_index[subdiv_corner];
|
||||
if (coarse_vert == -1) {
|
||||
continue;
|
||||
}
|
||||
GPU_indexbuf_add_point_vert(&builder, subdiv_corner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_points_subdiv_mesh(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
const bool sync_selection,
|
||||
GPUIndexBufBuilder &builder)
|
||||
{
|
||||
const Span<int> subdiv_loop_vert_index(
|
||||
static_cast<const int *>(GPU_vertbuf_get_data(subdiv_cache.verts_orig_index)),
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
|
||||
subdiv_cache.num_subdiv_loops);
|
||||
|
||||
for (const int subdiv_quad : IndexRange(subdiv_cache.num_subdiv_quads)) {
|
||||
const int coarse_face = subdiv_loop_face_index[subdiv_quad * 4];
|
||||
const BMFace *face_orig = bm_original_face_get(mr, coarse_face);
|
||||
if (!face_orig) {
|
||||
continue;
|
||||
}
|
||||
if (skip_bm_face(*face_orig, sync_selection)) {
|
||||
continue;
|
||||
}
|
||||
for (const int subdiv_corner : IndexRange(subdiv_quad * 4, 4)) {
|
||||
const int coarse_vert = subdiv_loop_vert_index[subdiv_corner];
|
||||
if (coarse_vert == -1) {
|
||||
continue;
|
||||
}
|
||||
GPU_indexbuf_add_point_vert(&builder, subdiv_corner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void extract_edituv_points_subdiv(const MeshRenderData &mr,
|
||||
const DRWSubdivCache &subdiv_cache,
|
||||
gpu::IndexBuf &ibo)
|
||||
{
|
||||
const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(
|
||||
&data->elb, GPU_PRIM_POINTS, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
|
||||
data->sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
}
|
||||
|
||||
static void extract_edituv_points_iter_subdiv_bm(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData & /*mr*/,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const BMFace *coarse_quad)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache.verts_orig_index);
|
||||
|
||||
uint start_loop_idx = subdiv_quad_index * 4;
|
||||
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
|
||||
for (uint i = start_loop_idx; i < end_loop_idx; i++) {
|
||||
const int vert_origindex = subdiv_loop_vert_index[i];
|
||||
edituv_point_add(data,
|
||||
(BM_elem_flag_test(coarse_quad, BM_ELEM_HIDDEN) || vert_origindex == -1),
|
||||
BM_elem_flag_test(coarse_quad, BM_ELEM_SELECT) != 0,
|
||||
i);
|
||||
&builder, GPU_PRIM_POINTS, subdiv_cache.num_subdiv_loops, subdiv_cache.num_subdiv_loops);
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_points_subdiv_bm(mr, subdiv_cache, sync_selection, builder);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache &subdiv_cache,
|
||||
const MeshRenderData &mr,
|
||||
void *_data,
|
||||
uint subdiv_quad_index,
|
||||
const int coarse_quad_index)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache.verts_orig_index);
|
||||
|
||||
const BMFace *efa = bm_original_face_get(mr, coarse_quad_index);
|
||||
const bool mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
|
||||
const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
|
||||
|
||||
uint start_loop_idx = subdiv_quad_index * 4;
|
||||
uint end_loop_idx = (subdiv_quad_index + 1) * 4;
|
||||
for (uint i = start_loop_idx; i < end_loop_idx; i++) {
|
||||
const int vert_origindex = subdiv_loop_vert_index[i];
|
||||
const bool real_vert = !mr.orig_index_vert ||
|
||||
(vert_origindex != -1 &&
|
||||
mr.orig_index_vert[vert_origindex] != ORIGINDEX_NONE);
|
||||
edituv_point_add(data, mp_hidden || !real_vert, mp_select, i);
|
||||
else {
|
||||
extract_edituv_points_subdiv_mesh(mr, subdiv_cache, sync_selection, builder);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_points_finish_subdiv(const DRWSubdivCache & /*subdiv_cache*/,
|
||||
const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPU_indexbuf_build_in_place(&data->elb, ibo);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_edituv_points()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_edituv_points_init;
|
||||
extractor.iter_face_bm = extract_edituv_points_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_edituv_points_iter_face_mesh;
|
||||
extractor.finish = extract_edituv_points_finish;
|
||||
extractor.init_subdiv = extract_edituv_points_init_subdiv;
|
||||
extractor.iter_subdiv_bm = extract_edituv_points_iter_subdiv_bm;
|
||||
extractor.iter_subdiv_mesh = extract_edituv_points_iter_subdiv_mesh;
|
||||
extractor.finish_subdiv = extract_edituv_points_finish_subdiv;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
|
||||
extractor.use_threading = false;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_points);
|
||||
return extractor;
|
||||
GPU_indexbuf_build_in_place(&builder, &ibo);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -508,99 +485,68 @@ constexpr MeshExtract create_extractor_edituv_points()
|
||||
/** \name Extract Edit UV Face-dots Indices
|
||||
* \{ */
|
||||
|
||||
static void extract_edituv_fdots_init(const MeshRenderData &mr,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void * /*ibo*/,
|
||||
void *tls_data)
|
||||
static void extract_edituv_face_dots_bm(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
gpu::IndexBuf &ibo)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
|
||||
GPU_indexbuf_init(&data->elb, GPU_PRIM_POINTS, mr.faces_num, mr.faces_num);
|
||||
data->sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
const BMesh &bm = *mr.bm;
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask visible = IndexMask::from_predicate(
|
||||
IndexMask(bm.totface), GrainSize(4096), memory, [&](const int i) {
|
||||
return !skip_bm_face(*BM_face_at_index(&const_cast<BMesh &>(bm), i), sync_selection);
|
||||
});
|
||||
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, visible.size(), bm.totface);
|
||||
visible.to_indices(GPU_indexbuf_get_data(&builder).cast<int>());
|
||||
GPU_indexbuf_build_in_place_ex(&builder, 0, bm.totface, false, &ibo);
|
||||
}
|
||||
|
||||
BLI_INLINE void edituv_facedot_add(MeshExtract_EditUvElem_Data *data,
|
||||
bool hidden,
|
||||
bool selected,
|
||||
int face_index)
|
||||
static void extract_edituv_face_dots_mesh(const MeshRenderData &mr,
|
||||
const bool sync_selection,
|
||||
gpu::IndexBuf &ibo)
|
||||
{
|
||||
if (!hidden && (data->sync_selection || selected)) {
|
||||
GPU_indexbuf_set_point_vert(&data->elb, face_index, face_index);
|
||||
}
|
||||
else {
|
||||
GPU_indexbuf_set_point_restart(&data->elb, face_index);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_fdots_iter_face_bm(const MeshRenderData & /*mr*/,
|
||||
const BMFace *f,
|
||||
const int f_index,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
edituv_facedot_add(data,
|
||||
BM_elem_flag_test_bool(f, BM_ELEM_HIDDEN),
|
||||
BM_elem_flag_test_bool(f, BM_ELEM_SELECT),
|
||||
f_index);
|
||||
}
|
||||
|
||||
static void extract_edituv_fdots_iter_face_mesh(const MeshRenderData &mr,
|
||||
const int face_index,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
|
||||
const BMFace *efa = bm_original_face_get(mr, face_index);
|
||||
const bool mp_hidden = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_HIDDEN) : true;
|
||||
const bool mp_select = (efa) ? BM_elem_flag_test_bool(efa, BM_ELEM_SELECT) : false;
|
||||
|
||||
const OffsetIndices faces = mr.faces;
|
||||
IndexMaskMemory memory;
|
||||
IndexMask visible = IndexMask::from_predicate(
|
||||
faces.index_range(), GrainSize(4096), memory, [&](const int i) {
|
||||
const BMFace *face_orig = bm_original_face_get(mr, i);
|
||||
if (!face_orig) {
|
||||
return false;
|
||||
}
|
||||
if (skip_bm_face(*face_orig, sync_selection)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (mr.use_subsurf_fdots) {
|
||||
const BitSpan facedot_tags = mr.mesh->runtime->subsurf_face_dot_tags;
|
||||
const Span<int> corner_verts = mr.corner_verts;
|
||||
visible = IndexMask::from_predicate(visible, GrainSize(4096), memory, [&](const int i) {
|
||||
const Span<int> face_verts = corner_verts.slice(faces[i]);
|
||||
return std::any_of(face_verts.begin(), face_verts.end(), [&](const int vert) {
|
||||
return facedot_tags[vert];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
for (const int corner : mr.faces[face_index]) {
|
||||
const int vert = mr.corner_verts[corner];
|
||||
GPUIndexBufBuilder builder;
|
||||
GPU_indexbuf_init(&builder, GPU_PRIM_POINTS, visible.size(), faces.size());
|
||||
visible.to_indices(GPU_indexbuf_get_data(&builder).cast<int>());
|
||||
GPU_indexbuf_build_in_place_ex(&builder, 0, faces.size(), false, &ibo);
|
||||
}
|
||||
|
||||
const bool real_fdot = !mr.orig_index_face ||
|
||||
(mr.orig_index_face[face_index] != ORIGINDEX_NONE);
|
||||
const bool subd_fdot = facedot_tags[vert];
|
||||
edituv_facedot_add(data, mp_hidden || !real_fdot || !subd_fdot, mp_select, face_index);
|
||||
}
|
||||
void extract_edituv_face_dots(const MeshRenderData &mr, gpu::IndexBuf &ibo)
|
||||
{
|
||||
const bool sync_selection = (mr.toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
|
||||
if (mr.extract_type == MR_EXTRACT_BMESH) {
|
||||
extract_edituv_face_dots_bm(mr, sync_selection, ibo);
|
||||
}
|
||||
else {
|
||||
const bool real_fdot = !mr.orig_index_face ||
|
||||
(mr.orig_index_face[face_index] != ORIGINDEX_NONE);
|
||||
edituv_facedot_add(data, mp_hidden || !real_fdot, mp_select, face_index);
|
||||
extract_edituv_face_dots_mesh(mr, sync_selection, ibo);
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edituv_fdots_finish(const MeshRenderData & /*mr*/,
|
||||
MeshBatchCache & /*cache*/,
|
||||
void *buf,
|
||||
void *_data)
|
||||
{
|
||||
MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
|
||||
gpu::IndexBuf *ibo = static_cast<gpu::IndexBuf *>(buf);
|
||||
GPU_indexbuf_build_in_place(&data->elb, ibo);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_edituv_fdots()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_edituv_fdots_init;
|
||||
extractor.iter_face_bm = extract_edituv_fdots_iter_face_bm;
|
||||
extractor.iter_face_mesh = extract_edituv_fdots_iter_face_mesh;
|
||||
extractor.finish = extract_edituv_fdots_finish;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
|
||||
extractor.use_threading = false;
|
||||
extractor.mesh_buffer_offset = offsetof(MeshBufferList, ibo.edituv_fdots);
|
||||
return extractor;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
const MeshExtract extract_edituv_tris = create_extractor_edituv_tris();
|
||||
const MeshExtract extract_edituv_lines = create_extractor_edituv_lines();
|
||||
const MeshExtract extract_edituv_points = create_extractor_edituv_points();
|
||||
const MeshExtract extract_edituv_fdots = create_extractor_edituv_fdots();
|
||||
|
||||
} // namespace blender::draw
|
||||
|
||||
Reference in New Issue
Block a user