diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-12-23 01:57:12 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2019-01-11 18:00:23 +0300 |
commit | 55ddb21b7ca79664922699a383130881b7761f43 (patch) | |
tree | d0b5170c67d8432e91c1d96bf83af0929fad767f | |
parent | 4c0c4e7f9fed6e675d11363865594fb294bdc4b6 (diff) |
Mesh Selection: Port to batch cache request
This makes it more future proof and remove baked id offset inside the vbos.
Instead we add the offset as a uniform. This makes it possible to reuse
the vbos instead of discarding them all the time.
Also using batch request may reduce batches creation time.
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 1130 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 131 |
3 files changed, 667 insertions, 604 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 385147039d6..dfdbd7f47e7 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -125,11 +125,11 @@ struct GPUBatch *DRW_mesh_batch_cache_get_edit_loose_edges_nor(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edit_loose_verts(struct Mesh *me); struct GPUBatch *DRW_mesh_batch_cache_get_edit_facedots(struct Mesh *me); /* edit-mesh selection */ -struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me, bool use_hide, uint select_id_offset); -struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me, bool use_hide); -struct GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset); -struct GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset); -struct GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset); +struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_mask(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me); +struct GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me); /* Object mode Wireframe overlays */ struct GPUBatch *DRW_mesh_batch_cache_get_wireframes_face(struct Mesh *me); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index be37787ae7c..6e28bd6a916 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1236,6 +1236,12 @@ static int mesh_render_data_loops_len_get(const MeshRenderData *rdata) return rdata->loop_len; } +static int mesh_render_data_loops_len_get_maybe_mapped(const MeshRenderData *rdata) +{ + BLI_assert(rdata->types & MR_DATATYPE_LOOP); + return ((rdata->mapped.use == false) ? rdata->loop_len : rdata->mapped.loop_len); +} + static int mesh_render_data_polys_len_get(const MeshRenderData *rdata) { BLI_assert(rdata->types & MR_DATATYPE_POLY); @@ -1952,7 +1958,7 @@ static bool drw_mesh_weight_state_compare(const struct DRW_MeshWeightState *a, c } static void drw_mesh_weight_state_extract( - Object *ob, Mesh *me, ToolSettings *ts, bool paint_mode, + Object *ob, Mesh *me, const ToolSettings *ts, bool paint_mode, struct DRW_MeshWeightState *wstate) { /* Extract complete vertex weight group selection state and mode flags. */ @@ -2022,6 +2028,12 @@ typedef struct MeshBatchCache { GPUVertBuf *data_ledges; GPUVertBuf *data_lverts; GPUVertBuf *lnor; + /* Selection */ + GPUVertBuf *loop_pos; + GPUVertBuf *loop_vert_idx; + GPUVertBuf *loop_edge_idx; + GPUVertBuf *loop_face_idx; + GPUVertBuf *facedots_idx; } edit; /* Index Buffers: @@ -2038,6 +2050,10 @@ typedef struct MeshBatchCache { /* Contains indices to unique edit vertices to not * draw the same vert multiple times (because of tesselation). */ GPUIndexBuf *edit_verts_points; + /* Edit mode selection. */ + GPUIndexBuf *edit_loops_points; /* verts */ + GPUIndexBuf *edit_loops_lines; /* edges */ + GPUIndexBuf *edit_loops_tris; /* faces */ } ibo; struct { @@ -2053,6 +2069,11 @@ typedef struct MeshBatchCache { GPUBatch *edit_triangles_lnor; GPUBatch *edit_loose_edges_nor; GPUBatch *edit_facedots; + /* Edit selection */ + GPUBatch *edit_selection_verts; + GPUBatch *edit_selection_edges; + GPUBatch *edit_selection_faces; + GPUBatch *edit_selection_facedots; /* Common display / Other */ GPUBatch *all_verts; GPUBatch *all_edges; @@ -2729,460 +2750,327 @@ static void mesh_create_pos_and_nor_tess(MeshRenderData *rdata, GPUVertBuf *vbo, } } -static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex( - MeshRenderData *rdata, const bool use_hide, - GPUVertBuf **r_vbo) +BLI_INLINE void mesh_edit_add_select_index(GPUVertBufRaw *buf, GPUVertCompType comp, uint index) { - BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); - - if (*r_vbo == NULL) { - *r_vbo = GPU_vertbuf_create(GPU_USAGE_STATIC); - mesh_create_pos_and_nor_tess(rdata, *r_vbo, use_hide); + /* We don't need to sanitize the value because the elements + * with these undefined values will never get drawn. */ + switch (comp) { + case GPU_COMP_U32: + *((uint *)GPU_vertbuf_raw_step(buf)) = index; + break; + case GPU_COMP_U16: + *((ushort *)GPU_vertbuf_raw_step(buf)) = (ushort)index; + break; + case GPU_COMP_U8: + *((uchar *)GPU_vertbuf_raw_step(buf)) = (uchar)index; + break; + default: + BLI_assert(0); + break; } - return *r_vbo; } -static GPUVertBuf *mesh_batch_cache_get_tri_pos_and_normals_edit( - MeshRenderData *rdata, MeshBatchCache *cache, bool use_hide) -{ - return mesh_batch_cache_get_tri_pos_and_normals_ex( - rdata, use_hide, - use_hide ? &cache->pos_with_normals_visible_only_edit : &cache->pos_with_normals_edit); -} +#define SELECT_COMP_FORMAT(el_len) (el_len > 0xFF ? (el_len > 0xFFFF ? GPU_COMP_U32 : GPU_COMP_U16) : GPU_COMP_U8) -/* DEPRECATED Need to be ported */ -static GPUVertBuf *mesh_batch_cache_get_facedot_pos_with_normals_and_flag( - MeshRenderData *rdata, MeshBatchCache *cache) -{ - BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); - - if (cache->edit.pos_nor_data_facedots == NULL) { - cache->edit.pos_nor_data_facedots = GPU_vertbuf_create(GPU_USAGE_STATIC); - mesh_create_edit_facedots(rdata, cache->edit.pos_nor_data_facedots); - } - - return cache->edit.pos_nor_data_facedots; -} - -static GPUVertBuf *mesh_batch_cache_get_edges_visible( - MeshRenderData *rdata, MeshBatchCache *cache) +static void mesh_create_edit_select_id( + MeshRenderData *rdata, + GPUVertBuf *vbo_pos, GPUVertBuf *vbo_verts, GPUVertBuf *vbo_edges, GPUVertBuf *vbo_faces) { - BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE)); - - if (cache->ed_edge_pos == NULL) { - static GPUVertFormat format = { 0 }; - static struct { uint pos, data; } attr_id; - if (format.attr_len == 0) { - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - - const int vbo_len_capacity = mesh_render_data_edges_len_get_maybe_mapped(rdata) * 2; - int vidx = 0; - - GPUVertBuf *vbo = cache->ed_edge_pos = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); - - if (rdata->mapped.use == false) { - if (rdata->edit_bmesh) { - BMesh *bm = rdata->edit_bmesh->bm; - BMIter iter; - BMEdge *eed; + const int vert_len = mesh_render_data_verts_len_get_maybe_mapped(rdata); + const int edge_len = mesh_render_data_edges_len_get_maybe_mapped(rdata); + const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata); + const int lvert_len = mesh_render_data_loose_verts_len_get_maybe_mapped(rdata); + const int ledge_len = mesh_render_data_loose_edges_len_get_maybe_mapped(rdata); + const int loop_len = mesh_render_data_loops_len_get_maybe_mapped(rdata); + const int tot_loop_len = loop_len + ledge_len * 2 + lvert_len; + + /* Choose the most compact vertex format. */ + GPUVertCompType vert_comp = SELECT_COMP_FORMAT(vert_len); + GPUVertCompType edge_comp = SELECT_COMP_FORMAT(edge_len); + GPUVertCompType face_comp = SELECT_COMP_FORMAT(poly_len); + + GPUVertFormat format_vert = { 0 }, format_edge = { 0 }, format_face = { 0 }, format_pos = { 0 }; + struct { uint vert, edge, face, pos; } attr_id; + attr_id.vert = GPU_vertformat_attr_add(&format_vert, "color", vert_comp, 1, GPU_FETCH_INT); + attr_id.edge = GPU_vertformat_attr_add(&format_edge, "color", edge_comp, 1, GPU_FETCH_INT); + attr_id.face = GPU_vertformat_attr_add(&format_face, "color", face_comp, 1, GPU_FETCH_INT); + attr_id.pos = GPU_vertformat_attr_add(&format_pos, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + + GPUVertBufRaw raw_verts, raw_edges, raw_faces, raw_pos; + if (DRW_TEST_ASSIGN_VBO(vbo_pos)) { + GPU_vertbuf_init_with_format(vbo_pos, &format_pos); + GPU_vertbuf_data_alloc(vbo_pos, tot_loop_len); + GPU_vertbuf_attr_get_raw_data(vbo_pos, attr_id.pos, &raw_pos); + } + if (DRW_TEST_ASSIGN_VBO(vbo_verts)) { + GPU_vertbuf_init_with_format(vbo_verts, &format_vert); + GPU_vertbuf_data_alloc(vbo_verts, tot_loop_len); + GPU_vertbuf_attr_get_raw_data(vbo_verts, attr_id.vert, &raw_verts); + } + if (DRW_TEST_ASSIGN_VBO(vbo_edges)) { + GPU_vertbuf_init_with_format(vbo_edges, &format_edge); + GPU_vertbuf_data_alloc(vbo_edges, tot_loop_len); + GPU_vertbuf_attr_get_raw_data(vbo_edges, attr_id.edge, &raw_edges); + } + if (DRW_TEST_ASSIGN_VBO(vbo_faces)) { + GPU_vertbuf_init_with_format(vbo_faces, &format_face); + GPU_vertbuf_data_alloc(vbo_faces, tot_loop_len); + GPU_vertbuf_attr_get_raw_data(vbo_faces, attr_id.face, &raw_faces); + } + + if (rdata->edit_bmesh && rdata->mapped.use == false) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter iter_efa, iter_loop, iter_edge, iter_vert; + BMFace *efa; + BMEdge *eed; + BMVert *eve; + BMLoop *loop; - BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v1->co); - vidx += 1; - GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, eed->v2->co); - vidx += 1; - } + /* Face Loops */ + BM_ITER_MESH (efa, &iter_efa, bm, BM_FACES_OF_MESH) { + int fidx = BM_elem_index_get(efa); + BM_ITER_ELEM (loop, &iter_loop, efa, BM_LOOPS_OF_FACE) { + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), loop->v->co); } - } - else { - /* not yet done! */ - BLI_assert(0); - } - } - else { - BMesh *bm = rdata->edit_bmesh->bm; - const MVert *mvert = rdata->mapped.me_cage->mvert; - const MEdge *medge = rdata->mapped.me_cage->medge; - const int *e_origindex = rdata->mapped.e_origindex; - for (int i = 0; i < rdata->mapped.edge_len; i++) { - const int e_orig = e_origindex[i]; - if (e_orig != ORIGINDEX_NONE) { - BMEdge *eed = BM_edge_at_index(bm, e_orig); - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - const MEdge *ed = &medge[i]; - GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, mvert[ed->v1].co); - vidx += 1; - GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, mvert[ed->v2].co); - vidx += 1; - } + if (vbo_verts) { + int vidx = BM_elem_index_get(loop->v); + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); } - } - } - const int vbo_len_used = vidx; - if (vbo_len_used != vbo_len_capacity) { - GPU_vertbuf_data_resize(vbo, vbo_len_used); - } - UNUSED_VARS_NDEBUG(vbo_len_used); - } - - return cache->ed_edge_pos; -} - -static GPUVertBuf *mesh_batch_cache_get_verts_visible( - MeshRenderData *rdata, MeshBatchCache *cache) -{ - BLI_assert(rdata->types & MR_DATATYPE_VERT); - - if (cache->ed_vert_pos == NULL) { - static GPUVertFormat format = { 0 }; - static struct { uint pos, data; } attr_id; - if (format.attr_len == 0) { - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - - const int vbo_len_capacity = mesh_render_data_verts_len_get_maybe_mapped(rdata); - uint vidx = 0; - - GPUVertBuf *vbo = cache->ed_vert_pos = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); - if (rdata->mapped.use == false) { - if (rdata->edit_bmesh) { - BMesh *bm = rdata->edit_bmesh->bm; - BMIter iter; - BMVert *eve; - - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, eve->co); - vidx += 1; - } + if (vbo_edges) { + int eidx = BM_elem_index_get(loop->e); + mesh_edit_add_select_index(&raw_edges, edge_comp, eidx); } - } - else { - for (int i = 0; i < vbo_len_capacity; i++) { - const MVert *mv = &rdata->mvert[i]; - if (!(mv->flag & ME_HIDE)) { - GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, mv->co); - vidx += 1; - } + if (vbo_faces) { + mesh_edit_add_select_index(&raw_faces, face_comp, fidx); } } } - else { - BMesh *bm = rdata->edit_bmesh->bm; - const MVert *mvert = rdata->mapped.me_cage->mvert; - const int *v_origindex = rdata->mapped.v_origindex; - for (int i = 0; i < vbo_len_capacity; i++) { - const int v_orig = v_origindex[i]; - if (v_orig != ORIGINDEX_NONE) { - BMVert *eve = BM_vert_at_index(bm, v_orig); - if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - const MVert *mv = &mvert[i]; - GPU_vertbuf_attr_set(vbo, attr_id.pos, vidx, mv->co); - vidx += 1; - } + /* Loose edges */ + BM_ITER_MESH (eed, &iter_edge, bm, BM_EDGES_OF_MESH) { + if (eed->l != NULL) { + continue; + } + BM_ITER_ELEM (eve, &iter_vert, eed, BM_VERTS_OF_EDGE) { + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), eve->co); + } + if (vbo_verts) { + int vidx = BM_elem_index_get(eve); + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); + } + if (vbo_edges) { + int eidx = BM_elem_index_get(eed); + mesh_edit_add_select_index(&raw_edges, edge_comp, eidx); } } } - const uint vbo_len_used = vidx; - if (vbo_len_used != vbo_len_capacity) { - GPU_vertbuf_data_resize(vbo, vbo_len_used); + /* Loose verts */ + BM_ITER_MESH (eve, &iter_vert, bm, BM_VERTS_OF_MESH) { + if (eve->e != NULL) { + continue; + } + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), eve->co); + } + if (vbo_verts) { + int vidx = BM_elem_index_get(eve); + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); + } } - - UNUSED_VARS_NDEBUG(vbo_len_used); } + else if (rdata->mapped.use == true) { + const MPoly *mpoly = rdata->mapped.me_cage->mpoly; + const MEdge *medge = rdata->mapped.me_cage->medge; + const MVert *mvert = rdata->mapped.me_cage->mvert; + const MLoop *mloop = rdata->mapped.me_cage->mloop; + BMesh *bm = rdata->edit_bmesh->bm; - return cache->ed_vert_pos; -} - -static GPUVertBuf *mesh_create_facedot_select_id( - MeshRenderData *rdata, uint select_id_offset) -{ - BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); - - GPUVertBuf *vbo; - { - static GPUVertFormat format = { 0 }; - static struct { uint pos, col; } attr_id; - if (format.attr_len == 0) { - attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT); - } - - const int vbo_len_capacity = mesh_render_data_polys_len_get(rdata); - int vidx = 0; - - vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); - uint select_index = select_id_offset; - - if (rdata->edit_bmesh) { - BMesh *bm = rdata->edit_bmesh->bm; - BMIter iter; - BMEdge *efa; + const int *v_origindex = rdata->mapped.v_origindex; + const int *e_origindex = rdata->mapped.e_origindex; + const int *p_origindex = rdata->mapped.p_origindex; - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - int select_id; - GPU_select_index_get(select_index, &select_id); - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; + /* Face Loops */ + for (int poly = 0; poly < poly_len; poly++, mpoly++) { + const MLoop *l = &mloop[mpoly->loopstart]; + int fidx = p_origindex[poly]; + for (int i = 0; i < mpoly->totloop; i++, l++) { + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), mvert[l->v].co); + } + if (vbo_verts) { + int vidx = v_origindex[l->v]; + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); + } + if (vbo_edges) { + int eidx = e_origindex[l->e]; + mesh_edit_add_select_index(&raw_edges, edge_comp, eidx); + } + if (vbo_faces) { + mesh_edit_add_select_index(&raw_faces, face_comp, fidx); } - select_index += 1; } } - else { - /* not yet done! */ - BLI_assert(0); - } - const int vbo_len_used = vidx; - if (vbo_len_used != vbo_len_capacity) { - GPU_vertbuf_data_resize(vbo, vbo_len_used); - } - } - - return vbo; -} - -static GPUVertBuf *mesh_create_edges_select_id( - MeshRenderData *rdata, uint select_id_offset) -{ - BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE)); - - GPUVertBuf *vbo; - { - static GPUVertFormat format = { 0 }; - static struct { uint pos, col; } attr_id; - if (format.attr_len == 0) { - attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT); - } - - const int vbo_len_capacity = mesh_render_data_edges_len_get_maybe_mapped(rdata) * 2; - int vidx = 0; - - vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); - - if (rdata->mapped.use == false) { - uint select_index = select_id_offset; - if (rdata->edit_bmesh) { - BMesh *bm = rdata->edit_bmesh->bm; - BMIter iter; - BMEdge *eed; - - BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - int select_id; - GPU_select_index_get(select_index, &select_id); - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; + /* Loose edges */ + for (int e = 0; e < edge_len; e++, medge++) { + int eidx = e_origindex[e]; + if (eidx != ORIGINDEX_NONE && (medge->flag & ME_LOOSEEDGE)) { + for (int i = 0; i < 2; ++i) { + int vidx = (i == 0) ? medge->v1 : medge->v2; + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), mvert[vidx].co); + } + if (vbo_verts) { + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); + } + if (vbo_edges) { + mesh_edit_add_select_index(&raw_edges, edge_comp, eidx); } - select_index += 1; } } - else { - /* not yet done! */ - BLI_assert(0); - } } - else { - BMesh *bm = rdata->edit_bmesh->bm; - const int *e_origindex = rdata->mapped.e_origindex; - for (int i = 0; i < rdata->mapped.edge_len; i++) { - const int e_orig = e_origindex[i]; - if (e_orig != ORIGINDEX_NONE) { - BMEdge *eed = BM_edge_at_index(bm, e_orig); - if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { - uint select_index = select_id_offset + e_orig; - int select_id; - GPU_select_index_get(select_index, &select_id); - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; + /* Loose verts */ + for (int v = 0; v < vert_len; v++, mvert++) { + int vidx = v_origindex[v]; + if (vidx != ORIGINDEX_NONE) { + BMVert *eve = BM_vert_at_index(bm, vidx); + if (eve->e == NULL) { + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), mvert->co); + } + if (vbo_verts) { + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); } } } } - const int vbo_len_used = vidx; - if (vbo_len_used != vbo_len_capacity) { - GPU_vertbuf_data_resize(vbo, vbo_len_used); - } } + else { + const MPoly *mpoly = rdata->mpoly; + const MVert *mvert = rdata->mvert; + const MLoop *mloop = rdata->mloop; - return vbo; -} - -static GPUVertBuf *mesh_create_verts_select_id( - MeshRenderData *rdata, uint select_id_offset) -{ - BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); - - GPUVertBuf *vbo; - { - static GPUVertFormat format = { 0 }; - static struct { uint pos, col; } attr_id; - if (format.attr_len == 0) { - attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT); - } - - const int vbo_len_capacity = mesh_render_data_verts_len_get_maybe_mapped(rdata); - int vidx = 0; - - vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); - - if (rdata->mapped.use == false) { - uint select_index = select_id_offset; - if (rdata->edit_bmesh) { - BMesh *bm = rdata->edit_bmesh->bm; - BMIter iter; - BMVert *eve; - - BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) { - if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - int select_id; - GPU_select_index_get(select_index, &select_id); - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; - } - select_index += 1; + const int *v_origindex = CustomData_get_layer(&rdata->me->vdata, CD_ORIGINDEX); + const int *e_origindex = CustomData_get_layer(&rdata->me->edata, CD_ORIGINDEX); + const int *p_origindex = CustomData_get_layer(&rdata->me->pdata, CD_ORIGINDEX); + + /* Face Loops */ + for (int poly = 0; poly < poly_len; poly++, mpoly++) { + const MLoop *l = &mloop[mpoly->loopstart]; + int fidx = p_origindex ? p_origindex[poly] : poly; + for (int i = 0; i < mpoly->totloop; i++, l++) { + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), mvert[l->v].co); + } + if (vbo_verts) { + int vidx = v_origindex ? v_origindex[l->v] : l->v; + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); + } + if (vbo_edges) { + int eidx = e_origindex ? e_origindex[l->e] : l->e; + mesh_edit_add_select_index(&raw_edges, edge_comp, eidx); + } + if (vbo_faces) { + mesh_edit_add_select_index(&raw_faces, face_comp, fidx); } } - else { - for (int i = 0; i < vbo_len_capacity; i++) { - const MVert *mv = &rdata->mvert[i]; - if (!(mv->flag & ME_HIDE)) { - int select_id; - GPU_select_index_get(select_index, &select_id); - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; + } + /* TODO(fclem): Until we find a way to detect + * loose verts easily outside of edit mode, this + * will remain disabled. */ +#if 0 + /* Loose edges */ + for (int e = 0; e < edge_len; e++, medge++) { + int eidx = e_origindex[e]; + if (eidx != ORIGINDEX_NONE && (medge->flag & ME_LOOSEEDGE)) { + for (int i = 0; i < 2; ++i) { + int vidx = (i == 0) ? medge->v1 : medge->v2; + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), mvert[vidx].co); + } + if (vbo_verts) { + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); + } + if (vbo_edges) { + mesh_edit_add_select_index(&raw_edges, edge_comp, eidx); } - select_index += 1; } } } - else { - BMesh *bm = rdata->edit_bmesh->bm; - const int *v_origindex = rdata->mapped.v_origindex; - for (int i = 0; i < vbo_len_capacity; i++) { - const int v_orig = v_origindex[i]; - if (v_orig != ORIGINDEX_NONE) { - BMVert *eve = BM_vert_at_index(bm, v_orig); - if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { - uint select_index = select_id_offset + v_orig; - int select_id; - GPU_select_index_get(select_index, &select_id); - GPU_vertbuf_attr_set(vbo, attr_id.col, vidx, &select_id); - vidx += 1; + /* Loose verts */ + for (int v = 0; v < vert_len; v++, mvert++) { + int vidx = v_origindex[v]; + if (vidx != ORIGINDEX_NONE) { + MVert *eve = BM_vert_at_index(bm, vidx); + if (eve->e == NULL) { + if (vbo_pos) { + copy_v3_v3(GPU_vertbuf_raw_step(&raw_pos), mvert->co); + } + if (vbo_verts) { + mesh_edit_add_select_index(&raw_verts, vert_comp, vidx); } } } } - const int vbo_len_used = vidx; - if (vbo_len_used != vbo_len_capacity) { - GPU_vertbuf_data_resize(vbo, vbo_len_used); - } +#endif } - - return vbo; + /* Don't resize */ } -static GPUVertBuf *mesh_create_tri_select_id( - MeshRenderData *rdata, bool use_hide, uint select_id_offset) +/* TODO: We could use gl_PrimitiveID as index instead of using another VBO. */ +static void mesh_create_edit_facedots_select_id( + MeshRenderData *rdata, + GPUVertBuf *vbo) { - BLI_assert( - rdata->types & - (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY)); - - GPUVertBuf *vbo; - { - uint cidx = 0; - - static GPUVertFormat format = { 0 }; - static struct { uint col; } attr_id; - if (format.attr_len == 0) { - attr_id.col = GPU_vertformat_attr_add(&format, "color", GPU_COMP_I32, 1, GPU_FETCH_INT); - } - - const int tri_len = mesh_render_data_looptri_len_get_maybe_mapped(rdata); - - vbo = GPU_vertbuf_create_with_format(&format); + const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata); - const int vbo_len_capacity = tri_len * 3; - int vbo_len_used = 0; - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); + GPUVertCompType comp = SELECT_COMP_FORMAT(poly_len); + GPUVertFormat format = { 0 }; + struct { uint idx; } attr_id; + attr_id.idx = GPU_vertformat_attr_add(&format, "color", comp, 1, GPU_FETCH_INT); - if (rdata->mapped.use == false) { - if (rdata->edit_bmesh) { - for (int i = 0; i < tri_len; i++) { - const BMLoop **ltri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; - /* Assume 'use_hide' */ - if (!BM_elem_flag_test(ltri[0]->f, BM_ELEM_HIDDEN)) { - const int poly_index = BM_elem_index_get(ltri[0]->f); - int select_id; - GPU_select_index_get(poly_index + select_id_offset, &select_id); - for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { - GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id); - } - } - } - } - else { - const int *p_origindex = NULL; - if (rdata->me != NULL) { - p_origindex = CustomData_get_layer(&rdata->me->pdata, CD_ORIGINDEX); - } + GPUVertBufRaw idx_step; + GPU_vertbuf_init_with_format(vbo, &format); + GPU_vertbuf_data_alloc(vbo, poly_len); + GPU_vertbuf_attr_get_raw_data(vbo, attr_id.idx, &idx_step); - for (int i = 0; i < tri_len; i++) { - const MLoopTri *mlt = &rdata->mlooptri[i]; - const int poly_index = mlt->poly; - if (!(use_hide && (rdata->mpoly[poly_index].flag & ME_HIDE))) { - int orig_index = p_origindex ? p_origindex[poly_index] : poly_index; - if (orig_index != ORIGINDEX_NONE) { - int select_id; - GPU_select_index_get(orig_index + select_id_offset, &select_id); - for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { - GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id); - } - } - } + /* Keep in sync with mesh_create_edit_facedots(). */ + if (rdata->mapped.use == false) { + if (rdata->edit_bmesh) { + for (int poly = 0; poly < poly_len; poly++) { + const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, poly); + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + mesh_edit_add_select_index(&idx_step, comp, poly); } } } else { - BMesh *bm = rdata->edit_bmesh->bm; - Mesh *me_cage = rdata->mapped.me_cage; - const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage); - for (int i = 0; i < tri_len; i++) { - const MLoopTri *mlt = &mlooptri[i]; - const int p_orig = rdata->mapped.p_origindex[mlt->poly]; - if (p_orig != ORIGINDEX_NONE) { - /* Assume 'use_hide' */ - BMFace *efa = BM_face_at_index(bm, p_orig); - if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - int select_id; - GPU_select_index_get(select_id_offset + p_orig, &select_id); - for (uint tri_corner = 0; tri_corner < 3; tri_corner++) { - GPU_vertbuf_attr_set(vbo, attr_id.col, cidx++, &select_id); - } - } + for (int poly = 0; poly < poly_len; poly++) { + mesh_edit_add_select_index(&idx_step, comp, poly); + } + } + } + else { + const int *p_origindex = rdata->mapped.p_origindex; + for (int poly = 0; poly < poly_len; poly++) { + const int p_orig = p_origindex[poly]; + if (p_orig != ORIGINDEX_NONE) { + const BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, p_orig); + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + mesh_edit_add_select_index(&idx_step, comp, poly); } } } - vbo_len_used = cidx; + } - if (vbo_len_capacity != vbo_len_used) { - GPU_vertbuf_data_resize(vbo, vbo_len_used); - } + /* Resize & Finish */ + int facedot_len_used = GPU_vertbuf_raw_used(&idx_step); + if (facedot_len_used != poly_len) { + GPU_vertbuf_data_resize(vbo, facedot_len_used); } - return vbo; } +#undef SELECT_COMP_FORMAT static void mesh_create_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo) { @@ -3261,7 +3149,7 @@ static void mesh_create_weights(MeshRenderData *rdata, GPUVertBuf *vbo, DRW_Mesh GPU_vertbuf_attr_fill(vbo, attr_id.weight, vert_weight); } -static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo, const bool use_face_sel) +static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo) { /* TODO deduplicate format creation*/ static GPUVertFormat format = { 0 }; @@ -3330,6 +3218,7 @@ static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo, const MLoop *mloop = rdata->mloop + mpoly->loopstart; const float (*lnors)[3] = (rdata->loop_normals) ? &rdata->loop_normals[mpoly->loopstart] : NULL; const GPUPackedNormal *fnor = (mpoly->flag & ME_SMOOTH) ? NULL : &rdata->poly_normals_pack[a]; + const int hide_select_flag = (mpoly->flag & ME_HIDE) ? -1 : ((mpoly->flag & ME_FACE_SEL) ? 1 : 0); for (int b = 0; b < mpoly->totloop; b++, mloop++) { copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), mvert[mloop->v].co); GPUPackedNormal *pnor = (GPUPackedNormal *)GPU_vertbuf_raw_step(&nor_step); @@ -3342,9 +3231,7 @@ static void mesh_create_loop_pos_and_nor(MeshRenderData *rdata, GPUVertBuf *vbo, else { *pnor = GPU_normal_convert_i10_s3(mvert[mloop->v].no); } - if (use_face_sel) { - pnor->w = (mpoly->flag & ME_HIDE) ? -1 : ((mpoly->flag & ME_FACE_SEL) ? 1 : 0); - } + pnor->w = hide_select_flag; } } @@ -4424,6 +4311,267 @@ static void mesh_create_loops_tris( } } +static void mesh_create_edit_loops_points_lines(MeshRenderData *rdata, GPUIndexBuf *ibo_verts, GPUIndexBuf *ibo_edges) +{ + BMIter iter_efa, iter_loop, iter_edge, iter_vert; + BMFace *efa; + BMEdge *eed; + BMVert *eve; + BMLoop *loop; + int i; + + const int loop_len = mesh_render_data_loops_len_get_maybe_mapped(rdata); + const int edge_len = mesh_render_data_edges_len_get_maybe_mapped(rdata); + const int vert_len = mesh_render_data_verts_len_get_maybe_mapped(rdata); + const int poly_len = mesh_render_data_polys_len_get_maybe_mapped(rdata); + const int lvert_len = mesh_render_data_loose_verts_len_get_maybe_mapped(rdata); + const int ledge_len = mesh_render_data_loose_edges_len_get_maybe_mapped(rdata); + const int tot_loop_len = loop_len + ledge_len * 2 + lvert_len; + + GPUIndexBufBuilder elb_vert, elb_edge; + if (DRW_TEST_ASSIGN_IBO(ibo_edges)) { + GPU_indexbuf_init(&elb_edge, GPU_PRIM_LINES, loop_len + ledge_len, tot_loop_len); + } + if (DRW_TEST_ASSIGN_IBO(ibo_verts)) { + GPU_indexbuf_init(&elb_vert, GPU_PRIM_POINTS, tot_loop_len, tot_loop_len); + } + + int loop_idx = 0; + if (rdata->edit_bmesh && (rdata->mapped.use == false)) { + BMesh *bm = rdata->edit_bmesh->bm; + /* Face Loops */ + BM_ITER_MESH (efa, &iter_efa, bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + BM_ITER_ELEM_INDEX (loop, &iter_loop, efa, BM_LOOPS_OF_FACE, i) { + if (ibo_verts) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx + i); + } + if (ibo_edges) { + int v1 = loop_idx + i; + int v2 = loop_idx + ((i + 1) % efa->len); + GPU_indexbuf_add_line_verts(&elb_edge, v1, v2); + } + } + } + loop_idx += efa->len; + } + /* Loose edges */ + if (ibo_verts || ibo_edges) { + BM_ITER_MESH (eed, &iter_edge, bm, BM_EDGES_OF_MESH) { + if (eed->l == NULL) { + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + if (ibo_verts) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx + 0); + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx + 1); + } + if (ibo_edges) { + GPU_indexbuf_add_line_verts(&elb_edge, loop_idx + 0, loop_idx + 1); + } + } + loop_idx += 2; + } + } + } + /* Loose verts */ + if (ibo_verts) { + BM_ITER_MESH (eve, &iter_vert, bm, BM_VERTS_OF_MESH) { + if (eve->e == NULL) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx); + } + loop_idx += 1; + } + } + } + } + else if (rdata->mapped.use) { + const MPoly *mpoly = rdata->mapped.me_cage->mpoly; + const MEdge *medge = rdata->mapped.me_cage->medge; + BMesh *bm = rdata->edit_bmesh->bm; + + const int *v_origindex = rdata->mapped.v_origindex; + const int *e_origindex = rdata->mapped.e_origindex; + const int *p_origindex = rdata->mapped.p_origindex; + + /* Face Loops */ + for (int poly = 0; poly < poly_len; poly++, mpoly++) { + int fidx = p_origindex[poly]; + if (fidx != ORIGINDEX_NONE) { + efa = BM_face_at_index(bm, fidx); + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + const MLoop *mloop = &rdata->mapped.me_cage->mloop[mpoly->loopstart]; + for (i = 0; i < mpoly->totloop; ++i, ++mloop) { + if (ibo_verts && (v_origindex[mloop->v] != ORIGINDEX_NONE)) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx + i); + } + if (ibo_edges && (e_origindex[mloop->e] != ORIGINDEX_NONE)) { + int v1 = loop_idx + i; + int v2 = loop_idx + ((i + 1) % mpoly->totloop); + GPU_indexbuf_add_line_verts(&elb_edge, v1, v2); + } + } + } + } + loop_idx += mpoly->totloop; + } + /* Loose edges */ + for (int e = 0; e < edge_len; e++, medge++) { + if (medge->flag & ME_LOOSEEDGE) { + int eidx = e_origindex[e]; + if (eidx != ORIGINDEX_NONE) { + eed = BM_edge_at_index(bm, eidx); + if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) { + for (int j = 0; j < 2; ++j) { + int v = (j == 0) ? medge->v1 : medge->v2; + if (ibo_verts && (v_origindex[v] != ORIGINDEX_NONE)) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx + j); + } + if (ibo_edges) { + GPU_indexbuf_add_generic_vert(&elb_edge, loop_idx + j); + } + } + } + } + loop_idx += 2; + } + } + /* Loose verts */ + for (int v = 0; v < vert_len; v++) { + int vidx = v_origindex[v]; + if (vidx != ORIGINDEX_NONE) { + eve = BM_vert_at_index(bm, vidx); + if (eve->e == NULL) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + if (ibo_verts) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx); + } + } + loop_idx += 1; + } + } + } + } + else { + const MPoly *mpoly = rdata->mpoly; + + /* Face Loops */ + for (int poly = 0; poly < poly_len; poly++, mpoly++) { + if ((mpoly->flag & ME_HIDE) == 0) { + for (i = 0; i < mpoly->totloop; ++i) { + if (ibo_verts) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx + i); + } + if (ibo_edges) { + int v1 = loop_idx + i; + int v2 = loop_idx + ((i + 1) % mpoly->totloop); + GPU_indexbuf_add_line_verts(&elb_edge, v1, v2); + } + } + } + loop_idx += mpoly->totloop; + } + /* TODO(fclem): Until we find a way to detect + * loose verts easily outside of edit mode, this + * will remain disabled. */ +#if 0 + /* Loose edges */ + for (int e = 0; e < edge_len; e++, medge++) { + if (medge->flag & ME_LOOSEEDGE) { + int eidx = e_origindex[e]; + if (eidx != ORIGINDEX_NONE) { + if ((medge->flag & ME_HIDE) == 0) { + for (int j = 0; j < 2; ++j) { + if (ibo_verts) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx + j); + } + if (ibo_edges) { + GPU_indexbuf_add_generic_vert(&elb_edge, loop_idx + j); + } + } + } + } + loop_idx += 2; + } + } + /* Loose verts */ + for (int v = 0; v < vert_len; v++, mvert++) { + int vidx = v_origindex[v]; + if (vidx != ORIGINDEX_NONE) { + if ((mvert->flag & ME_HIDE) == 0) { + if (ibo_verts) { + GPU_indexbuf_add_generic_vert(&elb_vert, loop_idx); + } + if (ibo_edges) { + GPU_indexbuf_add_generic_vert(&elb_edge, loop_idx); + } + } + loop_idx += 1; + } + } +#endif + } + + if (ibo_verts) { + GPU_indexbuf_build_in_place(&elb_vert, ibo_verts); + } + if (ibo_edges) { + GPU_indexbuf_build_in_place(&elb_edge, ibo_edges); + } +} + +static void mesh_create_edit_loops_tris(MeshRenderData *rdata, GPUIndexBuf *ibo) +{ + const int loop_len = mesh_render_data_loops_len_get_maybe_mapped(rdata); + const int tri_len = mesh_render_data_looptri_len_get_maybe_mapped(rdata); + + GPUIndexBufBuilder elb; + /* TODO alloc minmum necessary. */ + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tri_len, loop_len * 3); + + if (rdata->edit_bmesh && (rdata->mapped.use == false)) { + for (int i = 0; i < tri_len; i++) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + const BMFace *bm_face = bm_looptri[0]->f; + /* use_hide always for edit-mode */ + if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) { + continue; + } + GPU_indexbuf_add_tri_verts(&elb, BM_elem_index_get(bm_looptri[0]), + BM_elem_index_get(bm_looptri[1]), + BM_elem_index_get(bm_looptri[2])); + } + } + else if (rdata->mapped.use == true) { + BMesh *bm = rdata->edit_bmesh->bm; + Mesh *me_cage = rdata->mapped.me_cage; + + const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage); + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &mlooptri[i]; + const int p_orig = rdata->mapped.p_origindex[mlt->poly]; + if (p_orig != ORIGINDEX_NONE) { + /* Assume 'use_hide' */ + BMFace *efa = BM_face_at_index(bm, p_orig); + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + GPU_indexbuf_add_tri_verts(&elb, mlt->tri[0], mlt->tri[1], mlt->tri[2]); + } + } + } + } + else { + const MLoopTri *mlt = rdata->mlooptri; + for (int i = 0; i < tri_len; i++, mlt++) { + const MPoly *mpoly = &rdata->mpoly[mlt->poly]; + /* Assume 'use_hide' */ + if ((mpoly->flag & ME_HIDE) == 0) { + GPU_indexbuf_add_tri_verts(&elb, mlt->tri[0], mlt->tri[1], mlt->tri[2]); + } + } + } + + GPU_indexbuf_build_in_place(&elb, ibo); +} + /** \} */ @@ -4629,143 +4777,28 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Mesh *me) /** \name Edit Mode selection API * \{ */ -GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(Mesh *me, bool use_hide, uint select_id_offset) -{ - MeshBatchCache *cache = mesh_batch_cache_get(me); - - if (cache->triangles_with_select_id_offset != select_id_offset) { - cache->triangles_with_select_id_offset = select_id_offset; - GPU_BATCH_DISCARD_SAFE(cache->triangles_with_select_id); - } - - if (cache->triangles_with_select_id == NULL) { - const int datatype = - MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; - MeshRenderData *rdata = mesh_render_data_create(me, datatype); - if (rdata->mapped.supported) { - rdata->mapped.use = true; - } - - cache->triangles_with_select_id = GPU_batch_create_ex( - GPU_PRIM_TRIS, mesh_create_tri_select_id(rdata, use_hide, select_id_offset), NULL, GPU_BATCH_OWNS_VBO); - - GPUVertBuf *vbo_tris = mesh_batch_cache_get_tri_pos_and_normals_edit(rdata, cache, use_hide); - GPU_batch_vertbuf_add(cache->triangles_with_select_id, vbo_tris); - - mesh_render_data_free(rdata); - } - - return cache->triangles_with_select_id; -} - -/** - * Same as #DRW_mesh_batch_cache_get_triangles_with_select_id - * without the ID's, use to mask out geometry, eg - dont select face-dots behind other faces. - */ -GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_mask(Mesh *me, bool use_hide) +GPUBatch *DRW_mesh_batch_cache_get_triangles_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - if (cache->triangles_with_select_mask == NULL) { - const int datatype = - MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY; - MeshRenderData *rdata = mesh_render_data_create(me, datatype); - if (rdata->mapped.supported) { - rdata->mapped.use = true; - } - - GPUVertBuf *vbo_tris = mesh_batch_cache_get_tri_pos_and_normals_edit(rdata, cache, use_hide); - - cache->triangles_with_select_mask = GPU_batch_create( - GPU_PRIM_TRIS, vbo_tris, NULL); - - mesh_render_data_free(rdata); - } - - return cache->triangles_with_select_mask; + return DRW_batch_request(&cache->batch.edit_selection_faces); } - -GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me, uint select_id_offset) +GPUBatch *DRW_mesh_batch_cache_get_facedots_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - - if (cache->facedot_with_select_id_offset != select_id_offset) { - cache->facedot_with_select_id_offset = select_id_offset; - GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id); - } - - if (cache->facedot_with_select_id == NULL) { - MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY); - - /* We only want the 'pos', not the normals or flag. - * Use since this is almost certainly already created. */ - cache->facedot_with_select_id = GPU_batch_create( - GPU_PRIM_POINTS, mesh_batch_cache_get_facedot_pos_with_normals_and_flag(rdata, cache), NULL); - - GPU_batch_vertbuf_add_ex( - cache->facedot_with_select_id, - mesh_create_facedot_select_id(rdata, select_id_offset), true); - - mesh_render_data_free(rdata); - } - - return cache->facedot_with_select_id; + return DRW_batch_request(&cache->batch.edit_selection_facedots); } -GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me, uint select_id_offset) +GPUBatch *DRW_mesh_batch_cache_get_edges_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - - if (cache->edges_with_select_id_offset != select_id_offset) { - cache->edges_with_select_id_offset = select_id_offset; - GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id); - } - - if (cache->edges_with_select_id == NULL) { - MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE); - if (rdata->mapped.supported) { - rdata->mapped.use = true; - } - - cache->edges_with_select_id = GPU_batch_create( - GPU_PRIM_LINES, mesh_batch_cache_get_edges_visible(rdata, cache), NULL); - - GPU_batch_vertbuf_add_ex( - cache->edges_with_select_id, - mesh_create_edges_select_id(rdata, select_id_offset), true); - - mesh_render_data_free(rdata); - } - - return cache->edges_with_select_id; + return DRW_batch_request(&cache->batch.edit_selection_edges); } -GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me, uint select_id_offset) +GPUBatch *DRW_mesh_batch_cache_get_verts_with_select_id(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - - if (cache->verts_with_select_id_offset != select_id_offset) { - cache->verts_with_select_id_offset = select_id_offset; - GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id); - } - - if (cache->verts_with_select_id == NULL) { - MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT); - if (rdata->mapped.supported) { - rdata->mapped.use = true; - } - - cache->verts_with_select_id = GPU_batch_create( - GPU_PRIM_POINTS, mesh_batch_cache_get_verts_visible(rdata, cache), NULL); - - GPU_batch_vertbuf_add_ex( - cache->verts_with_select_id, - mesh_create_verts_select_id(rdata, select_id_offset), true); - - mesh_render_data_free(rdata); - } - - return cache->verts_with_select_id; + return DRW_batch_request(&cache->batch.edit_selection_verts); } /** \} */ @@ -5402,6 +5435,31 @@ void DRW_mesh_batch_cache_create_requested( if (DRW_batch_requested(cache->batch.edit_facedots, GPU_PRIM_POINTS)) { DRW_vbo_request(cache->batch.edit_facedots, &cache->edit.pos_nor_data_facedots); } + if (DRW_batch_requested(cache->batch.edit_triangles_nor, GPU_PRIM_POINTS)) { + DRW_ibo_request(cache->batch.edit_triangles_nor, &cache->ibo.edit_verts_points); + DRW_vbo_request(cache->batch.edit_triangles_nor, &cache->edit.pos_nor); + } + + /* TODO reuse ordered.loop_pos_nor if possible. */ + if (DRW_batch_requested(cache->batch.edit_selection_verts, GPU_PRIM_POINTS)) { + DRW_ibo_request(cache->batch.edit_selection_verts, &cache->ibo.edit_loops_points); + DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_pos); + DRW_vbo_request(cache->batch.edit_selection_verts, &cache->edit.loop_vert_idx); + } + if (DRW_batch_requested(cache->batch.edit_selection_edges, GPU_PRIM_LINES)) { + DRW_ibo_request(cache->batch.edit_selection_edges, &cache->ibo.edit_loops_lines); + DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_pos); + DRW_vbo_request(cache->batch.edit_selection_edges, &cache->edit.loop_edge_idx); + } + if (DRW_batch_requested(cache->batch.edit_selection_faces, GPU_PRIM_TRIS)) { + DRW_ibo_request(cache->batch.edit_selection_faces, &cache->ibo.edit_loops_tris); + DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_pos); + DRW_vbo_request(cache->batch.edit_selection_faces, &cache->edit.loop_face_idx); + } + if (DRW_batch_requested(cache->batch.edit_selection_facedots, GPU_PRIM_POINTS)) { + DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.pos_nor_data_facedots); + DRW_vbo_request(cache->batch.edit_selection_facedots, &cache->edit.facedots_idx); + } for (int i = 0; i < cache->mat_len; ++i) { if (DRW_batch_requested(cache->surf_per_mat[i], GPU_PRIM_TRIS)) { @@ -5454,7 +5512,16 @@ void DRW_mesh_batch_cache_create_requested( DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.pos_nor_lverts, MR_DATATYPE_VERT | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.pos_nor_data_facedots, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_OVERLAY); DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.lnor, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_pos, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_vert_idx, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_edge_idx, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.loop_face_idx, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); + DRW_ADD_FLAG_FROM_VBO_REQUEST(mr_edit_flag, cache->edit.facedots_idx, MR_DATATYPE_POLY); DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edit_verts_points, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI); + /* TODO: Some of the flags here may not be needed. */ + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edit_loops_points, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edit_loops_lines, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI); + DRW_ADD_FLAG_FROM_IBO_REQUEST(mr_edit_flag, cache->ibo.edit_loops_tris, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOSE_VERT | MR_DATATYPE_LOOSE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI); Mesh *me_original = me; MBC_GET_FINAL_MESH(me); @@ -5473,7 +5540,7 @@ void DRW_mesh_batch_cache_create_requested( mesh_create_weights(rdata, cache->ordered.weights, &cache->weight_state); } if (DRW_vbo_requested(cache->ordered.loop_pos_nor)) { - mesh_create_loop_pos_and_nor(rdata, cache->ordered.loop_pos_nor, use_face_sel); + mesh_create_loop_pos_and_nor(rdata, cache->ordered.loop_pos_nor); } if (DRW_vbo_requested(cache->ordered.loop_uv_tan)) { mesh_create_loop_uv_and_tan(rdata, cache->ordered.loop_uv_tan); @@ -5538,6 +5605,25 @@ void DRW_mesh_batch_cache_create_requested( if (DRW_vbo_requested(cache->edit.pos_nor_data_facedots)) { mesh_create_edit_facedots(rdata, cache->edit.pos_nor_data_facedots); } + if (DRW_vbo_requested(cache->edit.loop_pos) || + DRW_vbo_requested(cache->edit.loop_vert_idx) || + DRW_vbo_requested(cache->edit.loop_edge_idx) || + DRW_vbo_requested(cache->edit.loop_face_idx)) + { + mesh_create_edit_select_id(rdata, cache->edit.loop_pos, cache->edit.loop_vert_idx, + cache->edit.loop_edge_idx, cache->edit.loop_face_idx); + } + if (DRW_vbo_requested(cache->edit.facedots_idx)) { + mesh_create_edit_facedots_select_id(rdata, cache->edit.facedots_idx); + } + if (DRW_ibo_requested(cache->ibo.edit_loops_points) || + DRW_ibo_requested(cache->ibo.edit_loops_lines)) + { + mesh_create_edit_loops_points_lines(rdata, cache->ibo.edit_loops_points, cache->ibo.edit_loops_lines); + } + if (DRW_ibo_requested(cache->ibo.edit_loops_tris)) { + mesh_create_edit_loops_tris(rdata, cache->ibo.edit_loops_tris); + } mesh_render_data_free(rdata); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 409f0300530..f778021a2db 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -190,99 +190,61 @@ bool view3d_camera_border_hack_test = false; /* ***************** BACKBUF SEL (BBS) ********* */ -static void bbs_obmode_mesh_verts(Object *ob, int offset) -{ - Mesh *me = ob->data; - GPUBatch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); - GPU_batch_draw(batch); -} - -static void bbs_mesh_verts(BMEditMesh *em, int offset) +static void bbs_mesh_verts(GPUBatch *batch, int offset) { GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE)); - Mesh *me = em->ob->data; - GPUBatch *batch = DRW_mesh_batch_cache_get_verts_with_select_id(me, offset); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_SELECT_ID); + GPU_batch_uniform_1ui(batch, "offset", offset); GPU_batch_draw(batch); } -static void bbs_mesh_wire(BMEditMesh *em, int offset) +static void bbs_mesh_wire(GPUBatch *batch, int offset) { GPU_line_width(1.0f); + glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - Mesh *me = em->ob->data; - GPUBatch *batch = DRW_mesh_batch_cache_get_edges_with_select_id(me, offset); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_SELECT_ID); + GPU_batch_uniform_1ui(batch, "offset", offset); GPU_batch_draw(batch); + + glProvokingVertex(GL_LAST_VERTEX_CONVENTION); } -static void bbs_mesh_face(BMEditMesh *em, const bool use_select) +/* two options, facecolors or black */ +static void bbs_mesh_face(GPUBatch *batch, const bool use_select) { - Mesh *me = em->ob->data; - GPUBatch *batch; - if (use_select) { - batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_SELECT_ID); + GPU_batch_uniform_1ui(batch, "offset", 1); GPU_batch_draw(batch); } else { - int selcol; - GPU_select_index_get(0, &selcol); - batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32); - GPU_batch_uniform_1ui(batch, "color", selcol); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID); + GPU_batch_uniform_1ui(batch, "id", 0); GPU_batch_draw(batch); } } -static void bbs_mesh_face_dot(BMEditMesh *em) +static void bbs_mesh_face_dot(GPUBatch *batch) { - Mesh *me = em->ob->data; - GPUBatch *batch = DRW_mesh_batch_cache_get_facedots_with_select_id(me, 1); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); + GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_SELECT_ID); + GPU_batch_uniform_1ui(batch, "offset", 1); GPU_batch_draw(batch); } -/* two options, facecolors or black */ -static void bbs_mesh_solid_EM(BMEditMesh *em, Scene *scene, View3D *v3d, - Object *ob, bool use_faceselect) -{ - if (use_faceselect) { - bbs_mesh_face(em, true); - - if (check_ob_drawface_dot(scene, v3d, ob->dt)) { - bbs_mesh_face_dot(em); - } - } - else { - bbs_mesh_face(em, false); - } -} - static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph), Scene *UNUSED(scene), Object *ob) { Mesh *me = ob->data; - /* Only draw faces to mask out verts, we don't want their selection ID's. */ - const int G_f_orig = G.f; - G.f &= ~G_BACKBUFSEL; - - { - int selcol; - GPUBatch *batch; - GPU_select_index_get(0, &selcol); - batch = DRW_mesh_batch_cache_get_triangles_with_select_mask(me, true); - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_UNIFORM_COLOR_U32); - GPU_batch_uniform_1ui(batch, "color", selcol); - GPU_batch_draw(batch); - } + GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); - G.f |= (G_f_orig & G_BACKBUFSEL); + /* Only draw faces to mask out verts, we don't want their selection ID's. */ + bbs_mesh_face(geom_faces, false); + bbs_mesh_verts(geom_verts, 1); - bbs_obmode_mesh_verts(ob, 1); bm_vertoffs = me->totvert + 1; } @@ -290,15 +252,12 @@ static void bbs_mesh_solid_faces(Scene *UNUSED(scene), Object *ob) { Mesh *me = ob->data; Mesh *me_orig = DEG_get_original_object(ob)->data; - GPUBatch *batch; - if ((me_orig->editflag & ME_EDIT_PAINT_FACE_SEL)) { - batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, true, 1); - } - else { - batch = DRW_mesh_batch_cache_get_triangles_with_select_id(me, false, 1); - } - GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR_U32); - GPU_batch_draw(batch); + + const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL); + GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide); + + bbs_mesh_face(geom_faces, true); } void draw_object_backbufsel( @@ -311,8 +270,6 @@ void draw_object_backbufsel( } GPU_matrix_mul(ob->obmat); - - glClearDepth(1.0); GPU_clear(GPU_DEPTH_BIT); GPU_depth_test(true); switch (ob->type) { @@ -320,10 +277,30 @@ void draw_object_backbufsel( if (ob->mode & OB_MODE_EDIT) { Mesh *me = ob->data; BMEditMesh *em = me->edit_btmesh; + const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt); + const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0; BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE); - bbs_mesh_solid_EM(em, scene, v3d, ob, (select_mode & SCE_SELECT_FACE) != 0); + GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots; + geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me); + if (select_mode & SCE_SELECT_EDGE) { + geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me); + } + if (select_mode & SCE_SELECT_VERTEX) { + geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me); + } + if (draw_facedot) { + geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me); + } + DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true); + + bbs_mesh_face(geom_faces, use_faceselect); + + if (use_faceselect && draw_facedot) { + bbs_mesh_face_dot(geom_facedots); + } + if (select_mode & SCE_SELECT_FACE) bm_solidoffs = 1 + em->bm->totface; else { @@ -334,7 +311,7 @@ void draw_object_backbufsel( /* we draw edges if edge select mode */ if (select_mode & SCE_SELECT_EDGE) { - bbs_mesh_wire(em, bm_solidoffs); + bbs_mesh_wire(geom_edges, bm_solidoffs); bm_wireoffs = bm_solidoffs + em->bm->totedge; } else { @@ -344,7 +321,7 @@ void draw_object_backbufsel( /* we draw verts if vert select mode. */ if (select_mode & SCE_SELECT_VERTEX) { - bbs_mesh_verts(em, bm_wireoffs); + bbs_mesh_verts(geom_verts, bm_wireoffs); bm_vertoffs = bm_wireoffs + em->bm->totvert; } else { @@ -354,7 +331,7 @@ void draw_object_backbufsel( ED_view3d_polygon_offset(rv3d, 0.0); } else { - Mesh *me = ob->data; + Mesh *me = DEG_get_original_object(ob)->data; if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) && /* currently vertex select supports weight paint and vertex paint*/ ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) |