diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_mesh.c')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index fbddcd60d46..5a5d0260699 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -37,11 +37,14 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_types.h" #include "BKE_customdata.h" +#include "BKE_deform.h" #include "BKE_DerivedMesh.h" #include "BKE_editmesh.h" #include "BKE_mesh.h" +#include "BKE_texture.h" #include "bmesh.h" @@ -120,6 +123,7 @@ typedef struct MeshRenderData { MLoopUV **mloopuv; MCol **mcol; float (**mtangent)[4]; + MDeformVert *dvert; BMVert *eve_act; BMEdge *eed_act; @@ -152,8 +156,10 @@ typedef struct MeshRenderData { int *loose_verts; float (*poly_normals)[3]; + float (*vert_color)[3]; short (*poly_normals_short)[3]; short (*vert_normals_short)[3]; + bool *edge_selection; } MeshRenderData; enum { @@ -164,6 +170,7 @@ enum { MR_DATATYPE_POLY = 1 << 4, MR_DATATYPE_OVERLAY = 1 << 5, MR_DATATYPE_SHADING = 1 << 6, + MR_DATATYPE_DVERT = 1 << 7, }; /** @@ -236,6 +243,10 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) rdata->crease_ofs = CustomData_get_offset(&bm->edata, CD_CREASE); rdata->bweight_ofs = CustomData_get_offset(&bm->edata, CD_BWEIGHT); } + if (types & (MR_DATATYPE_DVERT)) { + bm_ensure_types |= BM_VERT; + } + BM_mesh_elem_index_ensure(bm, bm_ensure_types); BM_mesh_elem_table_ensure(bm, bm_ensure_types & ~BM_LOOP); if (types & MR_DATATYPE_OVERLAY) { @@ -298,6 +309,10 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) rdata->poly_len = me->totpoly; rdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); } + if (types & MR_DATATYPE_DVERT) { + rdata->vert_len = me->totvert; + rdata->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); + } } if (types & MR_DATATYPE_SHADING) { @@ -450,6 +465,8 @@ static void mesh_render_data_free(MeshRenderData *rdata) MEM_SAFE_FREE(rdata->uv_names); MEM_SAFE_FREE(rdata->vcol_names); MEM_SAFE_FREE(rdata->tangent_names); + MEM_SAFE_FREE(rdata->vert_color); + MEM_SAFE_FREE(rdata->edge_selection); MEM_freeN(rdata); } @@ -958,6 +975,301 @@ static bool mesh_render_data_looptri_cos_nors_smooth_get( return true; } +static void rgb_from_weight(float r_rgb[3], const float weight) +{ + const float blend = ((weight / 2.0f) + 0.5f); + + if (weight <= 0.25f) { /* blue->cyan */ + r_rgb[0] = 0.0f; + r_rgb[1] = blend * weight * 4.0f; + r_rgb[2] = blend; + } + else if (weight <= 0.50f) { /* cyan->green */ + r_rgb[0] = 0.0f; + r_rgb[1] = blend; + r_rgb[2] = blend * (1.0f - ((weight - 0.25f) * 4.0f)); + } + else if (weight <= 0.75f) { /* green->yellow */ + r_rgb[0] = blend * ((weight - 0.50f) * 4.0f); + r_rgb[1] = blend; + r_rgb[2] = 0.0f; + } + else if (weight <= 1.0f) { /* yellow->red */ + r_rgb[0] = blend; + r_rgb[1] = blend * (1.0f - ((weight - 0.75f) * 4.0f)); + r_rgb[2] = 0.0f; + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb[0] = 1.0f; + r_rgb[1] = 0.0f; + r_rgb[2] = 1.0f; + } +} + +static bool mesh_render_data_looptri_cos_weights_get( + MeshRenderData *rdata, const int tri_idx, + float *(*r_vert_cos)[3], float *(*r_vert_weights)[3], + short **r_tri_nor, short *(*r_vert_nors)[3], bool *r_is_smooth, int index) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_DVERT | MR_DATATYPE_POLY)); + + if (rdata->edit_bmesh) { + const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[tri_idx]; + + if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) { + return false; + } + + float (*vweight)[3] = rdata->vert_color; + short (*pnors_short)[3] = rdata->poly_normals_short; + short (*vnors_short)[3] = rdata->vert_normals_short; + + if (!pnors_short) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter fiter; + BMFace *face; + int i; + + pnors_short = rdata->poly_normals_short = MEM_mallocN(sizeof(*pnors_short) * rdata->poly_len, __func__); + BM_ITER_MESH_INDEX(face, &fiter, bm, BM_FACES_OF_MESH, i) { + normal_float_to_short_v3(pnors_short[i], face->no); + } + } + if (!vnors_short) { + BMesh *bm = rdata->edit_bmesh->bm; + BMIter viter; + BMVert *vert; + int i; + + vnors_short = rdata->vert_normals_short = MEM_mallocN(sizeof(*vnors_short) * rdata->vert_len, __func__); + BM_ITER_MESH_INDEX(vert, &viter, bm, BM_VERT, i) { + normal_float_to_short_v3(vnors_short[i], vert->no); + } + } + + if (!vweight) { + BMesh *bm = rdata->edit_bmesh->bm; + + if (CustomData_has_layer(&bm->vdata, CD_MDEFORMVERT)) { + BMIter viter; + BMVert *vert; + int i; + + const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); + BLI_assert(cd_dvert_offset != -1); + + vweight = rdata->vert_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__); + BM_ITER_MESH_INDEX(vert, &viter, bm, BM_VERT, i) { + const MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(vert, cd_dvert_offset); + float weight = defvert_find_weight(dvert, index); + if (U.flag & USER_CUSTOM_RANGE) { + do_colorband(&U.coba_weight, weight, vweight[i]); + } + else { + rgb_from_weight(vweight[i], weight); + } + } + } + else { + vweight = rdata->vert_color = MEM_callocN(sizeof(*vweight) * rdata->vert_len, __func__); + + for (int i = 0; i < rdata->vert_len; i++) { + vweight[i][2] = 0.5f; + } + } + } + + (*r_vert_cos)[0] = bm_looptri[0]->v->co; + (*r_vert_cos)[1] = bm_looptri[1]->v->co; + (*r_vert_cos)[2] = bm_looptri[2]->v->co; + (*r_vert_weights)[0] = vweight[BM_elem_index_get(bm_looptri[0]->v)]; + (*r_vert_weights)[1] = vweight[BM_elem_index_get(bm_looptri[1]->v)]; + (*r_vert_weights)[2] = vweight[BM_elem_index_get(bm_looptri[2]->v)]; + *r_tri_nor = pnors_short[BM_elem_index_get(bm_looptri[0]->f)]; + (*r_vert_nors)[0] = vnors_short[BM_elem_index_get(bm_looptri[0]->v)]; + (*r_vert_nors)[1] = vnors_short[BM_elem_index_get(bm_looptri[1]->v)]; + (*r_vert_nors)[2] = vnors_short[BM_elem_index_get(bm_looptri[2]->v)]; + + *r_is_smooth = BM_elem_flag_test_bool(bm_looptri[0]->f, BM_ELEM_SMOOTH); + } + else { + const MLoopTri *mlt = &rdata->mlooptri[tri_idx]; + float (*vweight)[3] = rdata->vert_color; + short (*pnors_short)[3] = rdata->poly_normals_short; + + if (!pnors_short) { + float (*pnors)[3] = rdata->poly_normals; + + if (!pnors) { + pnors = rdata->poly_normals = MEM_mallocN(sizeof(*pnors) * rdata->poly_len, __func__); + BKE_mesh_calc_normals_poly( + rdata->mvert, NULL, rdata->vert_len, + rdata->mloop, rdata->mpoly, rdata->loop_len, rdata->poly_len, pnors, true); + } + + pnors_short = rdata->poly_normals_short = MEM_mallocN(sizeof(*pnors_short) * rdata->poly_len, __func__); + for (int i = 0; i < rdata->poly_len; i++) { + normal_float_to_short_v3(pnors_short[i], pnors[i]); + } + } + + if (!vweight) { + if (rdata->dvert) { + vweight = rdata->vert_color = MEM_mallocN(sizeof(*vweight) * rdata->vert_len, __func__); + + for (int i = 0; i < rdata->vert_len; i++) { + float weight = defvert_find_weight(&rdata->dvert[i], index); + if (U.flag & USER_CUSTOM_RANGE) { + do_colorband(&U.coba_weight, weight, vweight[i]); + } + else { + rgb_from_weight(vweight[i], weight); + } + } + } + else { + vweight = rdata->vert_color = MEM_callocN(sizeof(*vweight) * rdata->vert_len, __func__); + + for (int i = 0; i < rdata->vert_len; i++) { + vweight[i][2] = 0.5f; + } + } + } + + (*r_vert_cos)[0] = rdata->mvert[rdata->mloop[mlt->tri[0]].v].co; + (*r_vert_cos)[1] = rdata->mvert[rdata->mloop[mlt->tri[1]].v].co; + (*r_vert_cos)[2] = rdata->mvert[rdata->mloop[mlt->tri[2]].v].co; + (*r_vert_weights)[0] = vweight[rdata->mloop[mlt->tri[0]].v]; + (*r_vert_weights)[1] = vweight[rdata->mloop[mlt->tri[1]].v]; + (*r_vert_weights)[2] = vweight[rdata->mloop[mlt->tri[2]].v]; + *r_tri_nor = pnors_short[mlt->poly]; + (*r_vert_nors)[0] = rdata->mvert[rdata->mloop[mlt->tri[0]].v].no; + (*r_vert_nors)[1] = rdata->mvert[rdata->mloop[mlt->tri[1]].v].no; + (*r_vert_nors)[2] = rdata->mvert[rdata->mloop[mlt->tri[2]].v].no; + + *r_is_smooth = (rdata->mpoly[mlt->poly].flag & ME_SMOOTH) != 0; + } + + return true; +} + +static bool mesh_render_data_edge_cos_sel_get( + MeshRenderData *rdata, const int edge_idx, + float r_vert_cos[2][3], float r_vert_col[3], + bool use_wire, bool use_sel) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP)); + + if (rdata->edit_bmesh) { + return false; + } + else { + const MEdge *ed = &rdata->medge[edge_idx]; + + if (!rdata->edge_selection && use_sel) { + rdata->edge_selection = MEM_callocN(sizeof(*rdata->edge_selection) * rdata->edge_len, __func__); + + for (int i = 0; i < rdata->poly_len; i++) { + MPoly *poly = &rdata->mpoly[i]; + + if (poly->flag & ME_FACE_SEL) { + for (int j = 0; j < poly->totloop; j++) { + MLoop *loop = &rdata->mloop[poly->loopstart + j]; + if (use_wire) { + rdata->edge_selection[loop->e] = true; + } + else { + rdata->edge_selection[loop->e] = !rdata->edge_selection[loop->e]; + } + } + } + } + } + + if (use_sel && rdata->edge_selection[edge_idx]) { + r_vert_col[0] = 1.0f; + r_vert_col[1] = 1.0f; + r_vert_col[2] = 1.0f; + } + else { + if (use_wire) { + r_vert_col[0] = 0.5f; + r_vert_col[1] = 0.5f; + r_vert_col[2] = 0.5f; + } + else { + return false; + } + } + + copy_v3_v3(r_vert_cos[0], rdata->mvert[ed->v1].co); + copy_v3_v3(r_vert_cos[1], rdata->mvert[ed->v2].co); + } + + return true; +} + +static bool mesh_render_data_tri_cos_sel_get( + MeshRenderData *rdata, const int tri_idx, + float r_vert_cos[3][3], float r_vert_col[4]) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI)); + + if (rdata->edit_bmesh) { + return false; + } + else { + const MLoopTri *mlt = &rdata->mlooptri[tri_idx]; + + if (rdata->mpoly[mlt->poly].flag & ME_FACE_SEL) { + r_vert_col[3] = 0.0f; + } + else { + r_vert_col[0] = 1.0f; + r_vert_col[1] = 1.0f; + r_vert_col[2] = 1.0f; + r_vert_col[3] = 0.2f; + } + + copy_v3_v3(r_vert_cos[0], rdata->mvert[rdata->mloop[mlt->tri[0]].v].co); + copy_v3_v3(r_vert_cos[1], rdata->mvert[rdata->mloop[mlt->tri[1]].v].co); + copy_v3_v3(r_vert_cos[2], rdata->mvert[rdata->mloop[mlt->tri[2]].v].co); + } + + return true; +} + +static bool mesh_render_data_vert_cos_sel_get( + MeshRenderData *rdata, const int vert_idx, + float r_vert_co[3], float r_vert_col[3]) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT)); + + if (rdata->edit_bmesh) { + return false; + } + else { + const MVert *mv = &rdata->mvert[vert_idx]; + + if (mv->flag & SELECT) { + r_vert_col[0] = 1.0f; + r_vert_col[1] = 1.0f; + r_vert_col[2] = 1.0f; + } + else { + r_vert_col[0] = 0.4f; + r_vert_col[1] = 0.4f; + r_vert_col[2] = 0.4f; + } + + copy_v3_v3(r_vert_co, mv->co); + } + + return true; +} + /* First 2 bytes are bit flags * 3rd is for sharp edges * 4rd is for creased edges */ @@ -1141,7 +1453,12 @@ typedef struct MeshBatchCache { Batch *all_triangles; VertexBuffer *pos_with_normals; + VertexBuffer *pos_with_weights; + VertexBuffer *edge_pos_with_sel; + VertexBuffer *tri_pos_with_sel; + VertexBuffer *pos_with_sel; Batch *triangles_with_normals; + Batch *triangles_with_weights; Batch *points_with_normals; Batch *fancy_edges; /* owns its vertex buffer (not shared) */ @@ -1160,9 +1477,13 @@ typedef struct MeshBatchCache { Batch *overlay_loose_verts; Batch *overlay_loose_edges; Batch *overlay_facedots; + Batch *overlay_weight_edges; + Batch *overlay_weight_faces; + Batch *overlay_weight_verts; /* settings to determine if cache is invalid */ bool is_dirty; + bool is_weight_dirty; int edge_len; int tri_len; int poly_len; @@ -1190,6 +1511,10 @@ static bool mesh_batch_cache_valid(Mesh *me) return false; } + if (cache->is_weight_dirty) { + return false; + } + if (cache->is_dirty == false) { return true; } @@ -1233,6 +1558,7 @@ static void mesh_batch_cache_init(Mesh *me) cache->mat_ct = mesh_render_mat_ct_get(me); cache->is_dirty = false; + cache->is_weight_dirty = false; } static MeshBatchCache *mesh_batch_cache_get(Mesh *me) @@ -1261,6 +1587,9 @@ void DRW_mesh_batch_cache_dirty(Mesh *me, int mode) BATCH_DISCARD_ALL_SAFE(cache->overlay_loose_edges); BATCH_DISCARD_ALL_SAFE(cache->overlay_facedots); break; + case BKE_MESH_BATCH_DIRTY_WEIGHT: + cache->is_weight_dirty = true; + break; default: BLI_assert(0); } @@ -1285,10 +1614,14 @@ static void mesh_batch_cache_clear(Mesh *me) BATCH_DISCARD_ALL_SAFE(cache->overlay_loose_verts); BATCH_DISCARD_ALL_SAFE(cache->overlay_loose_edges); BATCH_DISCARD_ALL_SAFE(cache->overlay_facedots); + BATCH_DISCARD_ALL_SAFE(cache->overlay_weight_edges); + BATCH_DISCARD_ALL_SAFE(cache->overlay_weight_faces); + BATCH_DISCARD_ALL_SAFE(cache->overlay_weight_verts); BATCH_DISCARD_SAFE(cache->triangles_with_normals); BATCH_DISCARD_SAFE(cache->points_with_normals); VERTEXBUFFER_DISCARD_SAFE(cache->pos_with_normals); + BATCH_DISCARD_ALL_SAFE(cache->triangles_with_weights); BATCH_DISCARD_ALL_SAFE(cache->fancy_edges); @@ -1539,6 +1872,68 @@ static VertexBuffer *mesh_batch_cache_get_pos_and_normals(MeshRenderData *rdata, return cache->pos_with_normals; } +static VertexBuffer *mesh_batch_cache_get_pos_normals_and_weights(MeshRenderData *rdata, MeshBatchCache *cache, int index) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_DVERT | MR_DATATYPE_POLY)); + + if (cache->pos_with_weights == NULL) { + unsigned int vidx = 0, cidx = 0, nidx = 0; + + static VertexFormat format = { 0 }; + static unsigned int pos_id, col_id, nor_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + nor_id = VertexFormat_add_attrib(&format, "nor", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT); + col_id = VertexFormat_add_attrib(&format, "color", COMP_F32, 3, KEEP_FLOAT); + } + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + VertexBuffer *vbo = cache->pos_with_weights = VertexBuffer_create_with_format(&format); + + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + VertexBuffer_allocate_data(vbo, vbo_len_capacity); + + for (int i = 0; i < tri_len; i++) { + float *tri_vert_cos[3], *tri_vert_weights[3]; + short *tri_nor, *tri_vert_nors[3]; + bool is_smooth; + + if (mesh_render_data_looptri_cos_weights_get( + rdata, i, &tri_vert_cos, &tri_vert_weights, &tri_nor, &tri_vert_nors, &is_smooth, index)) + { + VertexBuffer_set_attrib(vbo, col_id, cidx++, tri_vert_weights[0]); + VertexBuffer_set_attrib(vbo, col_id, cidx++, tri_vert_weights[1]); + VertexBuffer_set_attrib(vbo, col_id, cidx++, tri_vert_weights[2]); + + VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[0]); + VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[1]); + VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[2]); + + if (is_smooth) { + VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_vert_nors[0]); + VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_vert_nors[1]); + VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_vert_nors[2]); + } + else { + VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_nor); + VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_nor); + VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_nor); + } + } + } + vbo_len_used = vidx; + + if (vbo_len_capacity != vbo_len_used) { + VertexBuffer_resize_data(vbo, vbo_len_used); + } + } + + return cache->pos_with_weights; +} + static VertexBuffer *mesh_batch_cache_get_pos_and_nor_in_order(MeshRenderData *rdata, MeshBatchCache *cache) { BLI_assert(rdata->types & MR_DATATYPE_VERT); @@ -1657,6 +2052,146 @@ static ElementList **mesh_batch_cache_get_shaded_triangles_in_order(MeshRenderDa return cache->shaded_triangles_in_order; } +static VertexBuffer *mesh_batch_cache_get_edge_pos_with_sel(MeshRenderData *rdata, MeshBatchCache *cache, bool use_wire, bool use_sel) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP)); + + if (!cache->edge_pos_with_sel) { + unsigned int vidx = 0, cidx = 0; + + static VertexFormat format = { 0 }; + static unsigned int pos_id, col_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + col_id = VertexFormat_add_attrib(&format, "color", COMP_F32, 3, KEEP_FLOAT); + } + + const int edge_len = mesh_render_data_edges_len_get(rdata); + + VertexBuffer *vbo = cache->edge_pos_with_sel = VertexBuffer_create_with_format(&format); + + const int vbo_len_capacity = edge_len * 2; + int vbo_len_used = 0; + VertexBuffer_allocate_data(vbo, vbo_len_capacity); + + for (int i = 0; i < edge_len; i++) { + static float edge_vert_cos[2][3], edge_vert_col[3]; + + if (mesh_render_data_edge_cos_sel_get( + rdata, i, edge_vert_cos, edge_vert_col, use_wire, use_sel)) + { + VertexBuffer_set_attrib(vbo, col_id, cidx++, edge_vert_col); + VertexBuffer_set_attrib(vbo, col_id, cidx++, edge_vert_col); + + VertexBuffer_set_attrib(vbo, pos_id, vidx++, edge_vert_cos[0]); + VertexBuffer_set_attrib(vbo, pos_id, vidx++, edge_vert_cos[1]); + } + } + + vbo_len_used = vidx; + + if (vbo_len_capacity != vbo_len_used) { + VertexBuffer_resize_data(vbo, vbo_len_used); + } + } + + return cache->edge_pos_with_sel; +} + +static VertexBuffer *mesh_batch_cache_get_tri_pos_with_sel(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI)); + + if (cache->tri_pos_with_sel == NULL) { + unsigned int vidx = 0, cidx = 0; + + static VertexFormat format = { 0 }; + static unsigned int pos_id, col_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + col_id = VertexFormat_add_attrib(&format, "color", COMP_F32, 4, KEEP_FLOAT); + } + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + VertexBuffer *vbo = cache->tri_pos_with_sel = VertexBuffer_create_with_format(&format); + + const int vbo_len_capacity = tri_len * 3; + int vbo_len_used = 0; + VertexBuffer_allocate_data(vbo, vbo_len_capacity); + + for (int i = 0; i < tri_len; i++) { + static float tri_vert_cos[3][3], tri_vert_col[4]; + + if (mesh_render_data_tri_cos_sel_get( + rdata, i, tri_vert_cos, tri_vert_col)) + { + VertexBuffer_set_attrib(vbo, col_id, cidx++, tri_vert_col); + VertexBuffer_set_attrib(vbo, col_id, cidx++, tri_vert_col); + VertexBuffer_set_attrib(vbo, col_id, cidx++, tri_vert_col); + + VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[0]); + VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[1]); + VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[2]); + } + } + + vbo_len_used = vidx; + + if (vbo_len_capacity != vbo_len_used) { + VertexBuffer_resize_data(vbo, vbo_len_used); + } + } + + return cache->tri_pos_with_sel; +} + +static VertexBuffer *mesh_batch_cache_get_pos_with_sel(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT)); + + if (cache->pos_with_sel == NULL) { + unsigned int vidx = 0, cidx = 0; + + static VertexFormat format = { 0 }; + static unsigned int pos_id, col_id; + if (format.attrib_ct == 0) { + /* initialize vertex format */ + pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT); + col_id = VertexFormat_add_attrib(&format, "color", COMP_F32, 3, KEEP_FLOAT); + } + + const int vert_len = mesh_render_data_verts_len_get(rdata); + + VertexBuffer *vbo = cache->pos_with_sel = VertexBuffer_create_with_format(&format); + + const int vbo_len_capacity = vert_len; + int vbo_len_used = 0; + VertexBuffer_allocate_data(vbo, vbo_len_capacity); + + for (int i = 0; i < vert_len; i++) { + static float vert_co[3], vert_col[3]; + + if (mesh_render_data_vert_cos_sel_get( + rdata, i, vert_co, vert_col)) + { + VertexBuffer_set_attrib(vbo, col_id, cidx++, vert_col); + VertexBuffer_set_attrib(vbo, pos_id, vidx++, vert_co); + } + } + + vbo_len_used = vidx; + + if (vbo_len_capacity != vbo_len_used) { + VertexBuffer_resize_data(vbo, vbo_len_used); + } + } + + return cache->pos_with_sel; +} + Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); @@ -1706,6 +2241,21 @@ Batch *DRW_mesh_batch_cache_get_triangles_with_normals(Mesh *me) return cache->triangles_with_normals; } +Batch *DRW_mesh_batch_cache_get_triangles_with_normals_and_weights(Mesh *me, int index) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->triangles_with_weights == NULL) { + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_DVERT | MR_DATATYPE_POLY); + + cache->triangles_with_weights = Batch_create(PRIM_TRIANGLES, mesh_batch_cache_get_pos_normals_and_weights(rdata, cache, index), NULL); + + mesh_render_data_free(rdata); + } + + return cache->triangles_with_weights; +} + Batch *DRW_mesh_batch_cache_get_points_with_normals(Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); @@ -2009,4 +2559,52 @@ Batch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me) return cache->shaded_triangles; } +Batch *DRW_mesh_batch_cache_get_weight_overlay_edges(Mesh *me, bool use_wire, bool use_sel) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_weight_edges == NULL) { + /* create batch from Mesh */ + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_POLY | MR_DATATYPE_LOOP); + + cache->overlay_weight_edges = Batch_create(PRIM_LINES, mesh_batch_cache_get_edge_pos_with_sel(rdata, cache, use_wire, use_sel), NULL); + + mesh_render_data_free(rdata); + } + + return cache->overlay_weight_edges; +} + +Batch *DRW_mesh_batch_cache_get_weight_overlay_faces(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_weight_faces == NULL) { + /* create batch from Mesh */ + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_POLY | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI); + + cache->overlay_weight_faces = Batch_create(PRIM_TRIANGLES, mesh_batch_cache_get_tri_pos_with_sel(rdata, cache), NULL); + + mesh_render_data_free(rdata); + } + + return cache->overlay_weight_faces; +} + +Batch *DRW_mesh_batch_cache_get_weight_overlay_verts(Mesh *me) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->overlay_weight_verts == NULL) { + /* create batch from Mesh */ + MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT); + + cache->overlay_weight_verts = Batch_create(PRIM_POINTS, mesh_batch_cache_get_pos_with_sel(rdata, cache), NULL); + + mesh_render_data_free(rdata); + } + + return cache->overlay_weight_verts; +} + #undef MESH_RENDER_FUNCTION |