diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-10-11 07:07:29 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-10-11 08:53:25 +0300 |
commit | 641190adfff95d7117a4159975161eed9f13a9f5 (patch) | |
tree | a493d0b58bfeb443eab5fdd6f7e1486039787244 /source/blender/draw/intern/draw_cache_impl_mesh.c | |
parent | d74b89aed0310bcead9e17a8100f69b9b1872313 (diff) |
DRW: Initial edit-mode cage support
Modifiers such as sub-surf and mirror now work with show-on-cage.
Selection and loose geometry still needs to be supported.
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_mesh.c')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 151 |
1 files changed, 140 insertions, 11 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 05b1a2499d3..4fce2e6ac6e 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -52,6 +52,7 @@ #include "BKE_editmesh_tangent.h" #include "BKE_mesh.h" #include "BKE_mesh_tangent.h" +#include "BKE_mesh_runtime.h" #include "BKE_colorband.h" #include "BKE_cdderivedmesh.h" @@ -144,6 +145,17 @@ typedef struct MeshRenderData { int loose_vert_len; int loose_edge_len; + /* Support for mapped mesh data. */ + struct { + bool use; + + /* origindex layers */ + int *v_origindex; + int *e_origindex; + int *l_origindex; + int *p_origindex; + } mapped; + BMEditMesh *edit_bmesh; struct EditMeshData *edit_data; @@ -415,6 +427,18 @@ static MeshRenderData *mesh_render_data_create_ex( rdata->edit_bmesh = embm; rdata->edit_data = me->runtime.edit_data; + if (embm->mesh_eval_cage && (embm->mesh_eval_cage->runtime.is_original == false)) { + Mesh *me_cage = embm->mesh_eval_cage; + rdata->mapped.v_origindex = CustomData_get_layer(&me_cage->vdata, CD_ORIGINDEX); + rdata->mapped.e_origindex = CustomData_get_layer(&me_cage->edata, CD_ORIGINDEX); + rdata->mapped.l_origindex = CustomData_get_layer(&me_cage->ldata, CD_ORIGINDEX); + rdata->mapped.p_origindex = CustomData_get_layer(&me_cage->pdata, CD_ORIGINDEX); + rdata->mapped.use = ( + rdata->mapped.v_origindex && + rdata->mapped.e_origindex && + rdata->mapped.p_origindex); + } + int bm_ensure_types = 0; if (types & MR_DATATYPE_VERT) { rdata->vert_len = bm->totvert; @@ -1504,6 +1528,85 @@ static void add_overlay_tri( } } } +static void add_overlay_tri_mapped( + MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, + const uint pos_id, const uint vnor_id, const uint lnor_id, const uint data_id, + BMFace *efa, const MLoopTri *mlt, const float poly_normal[3], const int base_vert_idx) +{ + BMEditMesh *embm = rdata->edit_bmesh; + BMesh *bm = embm->bm; + Mesh *me_cage = embm->mesh_eval_cage; + + const MVert *mvert = me_cage->mvert; + const MEdge *medge = me_cage->medge; + const MLoop *mloop = me_cage->mloop; +#if 0 + const MPoly *mpoly = me_cage->mpoly; +#endif + + const int *v_origindex = rdata->mapped.v_origindex; + const int *e_origindex = rdata->mapped.e_origindex; +#if 0 + const int *l_origindex = rdata->mapped.l_origindex; + const int *p_origindex = rdata->mapped.p_origindex; +#endif + + uchar fflag; + uchar vflag; + + if (vbo_pos) { + for (uint i = 0; i < 3; i++) { + const float *pos = mvert[mloop[mlt->tri[i]].v].co; + GPU_vertbuf_attr_set(vbo_pos, pos_id, base_vert_idx + i, pos); + } + } + + if (vbo_nor) { + /* TODO real loop normal */ + GPUPackedNormal lnor = GPU_normal_convert_i10_v3(poly_normal); + for (uint i = 0; i < 3; i++) { + GPUPackedNormal vnor = GPU_normal_convert_i10_s3(mvert[mloop[mlt->tri[i]].v].no); + GPU_vertbuf_attr_set(vbo_nor, vnor_id, base_vert_idx + i, &vnor); + GPU_vertbuf_attr_set(vbo_nor, lnor_id, base_vert_idx + i, &lnor); + } + } + + if (vbo_data) { + fflag = mesh_render_data_looptri_flag(rdata, efa); + uint i_prev = 1, i = 2; + for (uint i_next = 0; i_next < 3; i_next++) { + const int v_orig = v_origindex[mloop[mlt->tri[i]].v]; + if (v_orig != ORIGINDEX_NONE) { + BMVert *v = BM_vert_at_index(bm, v_orig); + vflag = mesh_render_data_vertex_flag(rdata, v); + } + else { + /* Importantly VFLAG_VERTEX_EXISTS is not set. */ + vflag = 0; + } + /* Opposite edge to the vertex at 'i'. */ + EdgeDrawAttr eattr = {0}; + const int e_idx = mloop[mlt->tri[i_next]].e; + const int e_orig = e_origindex[e_idx]; + if (e_orig != ORIGINDEX_NONE) { + const MEdge *ed = &medge[e_idx]; + const uint tri_edge[2] = {mloop[mlt->tri[i_prev]].v, mloop[mlt->tri[i_next]].v}; + const bool is_edge_real = ( + ((ed->v1 == tri_edge[0]) && (ed->v2 == tri_edge[1])) || + ((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0]))); + if (is_edge_real) { + BMEdge *eed = BM_edge_at_index(bm, e_orig); + mesh_render_data_edge_flag(rdata, eed, &eattr); + } + } + eattr.v_flag = fflag | vflag; + GPU_vertbuf_attr_set(vbo_data, data_id, base_vert_idx + i, &eattr); + + i_prev = i; + i = i_next; + } + } +} static void add_overlay_loose_edge( MeshRenderData *rdata, GPUVertBuf *vbo_pos, GPUVertBuf *vbo_nor, GPUVertBuf *vbo_data, @@ -3105,8 +3208,10 @@ static void mesh_batch_cache_create_overlay_tri_buffers( MeshRenderData *rdata, MeshBatchCache *cache) { BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); - - const int tri_len = mesh_render_data_looptri_len_get(rdata); + Mesh *me_cage = rdata->mapped.use ? rdata->edit_bmesh->mesh_eval_cage : NULL; + const int tri_len = ( + rdata->mapped.use ? poly_to_tri_count(me_cage->totpoly, me_cage->totloop) : + mesh_render_data_looptri_len_get(rdata)); const int vbo_len_capacity = tri_len * 3; int vbo_len_used = 0; @@ -3136,15 +3241,39 @@ static void mesh_batch_cache_create_overlay_tri_buffers( GPU_vertbuf_data_alloc(vbo_data, vbo_len_capacity); } - for (int i = 0; i < tri_len; i++) { - const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; - if (!BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { - add_overlay_tri( - rdata, vbo_pos, vbo_nor, vbo_data, - attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data, - bm_looptri, vbo_len_used); - - vbo_len_used += 3; + if (rdata->mapped.use == false) { + for (int i = 0; i < tri_len; i++) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; + if (!BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { + add_overlay_tri( + rdata, vbo_pos, vbo_nor, vbo_data, + attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data, + bm_looptri, vbo_len_used); + vbo_len_used += 3; + } + } + } + else { + const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me_cage); + if (!CustomData_has_layer(&me_cage->pdata, CD_NORMAL)) { + /* TODO(campbell): this is quite an expensive operation for something + * that's not used unless 'normal' display option is enabled. */ + BKE_mesh_ensure_normals_for_display(me_cage); + } + const float (*polynors)[3] = CustomData_get_layer(&me_cage->pdata, CD_NORMAL); + for (int i = 0; i < tri_len; i++) { + const MLoopTri *mlt = &mlooptri[i]; + int orig = rdata->mapped.p_origindex[mlt->poly]; + if (orig != ORIGINDEX_NONE) { + BMFace *efa = BM_face_at_index(rdata->edit_bmesh->bm, orig); + if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + add_overlay_tri_mapped( + rdata, vbo_pos, vbo_nor, vbo_data, + attr_id.pos, attr_id.vnor, attr_id.lnor, attr_id.data, + efa, mlt, polynors[mlt->poly], vbo_len_used); + vbo_len_used += 3; + } + } } } |