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.
This commit is contained in:
Campbell Barton 2018-10-11 15:07:29 +11:00
parent d74b89aed0
commit 641190adff
1 changed files with 140 additions and 11 deletions

View File

@ -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;
}
}
}
}