Mesh Batch Cache: Split Edit Mesh mode Vertex Buffers for faster update.

This commit is contained in:
Clément Foucault 2017-05-13 16:45:06 +02:00
parent b3e62a8aa2
commit 5a377521aa
7 changed files with 565 additions and 141 deletions

View File

@ -1747,6 +1747,19 @@ void DRW_cache_mesh_wire_overlay_get(
*r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
}
void DRW_cache_mesh_normals_overlay_get(
Object *ob,
Batch **r_tris, Batch **r_ledges, Batch **r_lverts)
{
BLI_assert(ob->type == OB_MESH);
Mesh *me = ob->data;
*r_tris = DRW_mesh_batch_cache_get_overlay_triangles_nor(me);
*r_ledges = DRW_mesh_batch_cache_get_overlay_loose_edges_nor(me);
*r_lverts = DRW_mesh_batch_cache_get_overlay_loose_verts(me);
}
Batch *DRW_cache_face_centers_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);

View File

@ -91,6 +91,9 @@ struct Batch *DRW_cache_mesh_surface_overlay_get(struct Object *ob);
void DRW_cache_mesh_wire_overlay_get(
struct Object *ob,
struct Batch **r_tris, struct Batch **r_ledges, struct Batch **r_lverts);
void DRW_cache_mesh_normals_overlay_get(
struct Object *ob,
struct Batch **r_tris, struct Batch **r_ledges, struct Batch **r_lverts);
struct Batch *DRW_cache_face_centers_get(struct Object *ob);
struct Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
struct Batch *DRW_cache_mesh_surface_get(struct Object *ob);

View File

@ -85,7 +85,9 @@ struct Batch *DRW_mesh_batch_cache_get_points_with_normals(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_all_verts(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_fancy_edges(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_triangles(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_loose_edges(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me);

View File

@ -1190,7 +1190,10 @@ static bool mesh_render_data_looptri_cos_nors_smooth_get(
MeshRenderData *rdata, const int tri_idx,
float *(*r_vert_cos)[3], short **r_tri_nor, short *(*r_vert_nors)[3], bool *r_is_smooth)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
BLI_assert(rdata->types & MR_DATATYPE_VERT);
BLI_assert(rdata->types & MR_DATATYPE_LOOPTRI);
BLI_assert(rdata->types & MR_DATATYPE_LOOP);
BLI_assert(rdata->types & MR_DATATYPE_POLY);
if (rdata->edit_bmesh) {
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[tri_idx];
@ -1549,62 +1552,115 @@ static unsigned char mesh_render_data_vertex_flag(MeshRenderData *rdata, const i
}
static void add_overlay_tri(
MeshRenderData *rdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
MeshRenderData *rdata, VertexBuffer *vbo_pos, VertexBuffer *vbo_nor, VertexBuffer *vbo_data,
const unsigned int pos_id, const unsigned int vnor_id, const unsigned int lnor_id, const unsigned int data_id,
const int tri_vert_idx[3], const int tri_edge_idx[3], const int f, const int base_vert_idx)
{
const float *pos;
EdgeDrawAttr *eattr;
unsigned char fflag;
unsigned char vflag;
unsigned char fflag;
unsigned char vflag;
pos = mesh_render_data_vert_co(rdata, tri_vert_idx[0]);
eattr = mesh_render_data_edge_flag(rdata, tri_edge_idx[1]);
fflag = mesh_render_data_looptri_flag(rdata, f);
vflag = mesh_render_data_vertex_flag(rdata, tri_vert_idx[0]);
eattr->v_flag = fflag | vflag;
VertexBuffer_set_attrib(vbo, pos_id, base_vert_idx + 0, pos);
VertexBuffer_set_attrib(vbo, edgeMod_id, base_vert_idx + 0, eattr);
if (vbo_pos) {
for (int i = 0; i < 3; ++i) {
const float *pos = mesh_render_data_vert_co(rdata, tri_vert_idx[i]);
VertexBuffer_set_attrib(vbo_pos, pos_id, base_vert_idx + i, pos);
}
}
pos = mesh_render_data_vert_co(rdata, tri_vert_idx[1]);
eattr = mesh_render_data_edge_flag(rdata, tri_edge_idx[2]);
vflag = mesh_render_data_vertex_flag(rdata, tri_vert_idx[1]);
eattr->v_flag = fflag | vflag;
VertexBuffer_set_attrib(vbo, pos_id, base_vert_idx + 1, pos);
VertexBuffer_set_attrib(vbo, edgeMod_id, base_vert_idx + 1, eattr);
if (vbo_nor) {
float *tri_vert_cos[3];
short *tri_nor, *tri_vert_nors[3];
bool is_smooth;
pos = mesh_render_data_vert_co(rdata, tri_vert_idx[2]);
eattr = mesh_render_data_edge_flag(rdata, tri_edge_idx[0]);
vflag = mesh_render_data_vertex_flag(rdata, tri_vert_idx[2]);
eattr->v_flag = fflag | vflag;
VertexBuffer_set_attrib(vbo, pos_id, base_vert_idx + 2, pos);
VertexBuffer_set_attrib(vbo, edgeMod_id, base_vert_idx + 2, eattr);
mesh_render_data_looptri_cos_nors_smooth_get(
rdata, f, &tri_vert_cos, &tri_nor, &tri_vert_nors, &is_smooth);
for (int i = 0; i < 3; ++i) {
/* TODO real loop normal */
const short *svnor = mesh_render_data_vert_nor(rdata, tri_vert_idx[i]);
const short *slnor = tri_vert_nors[i];
fflag = mesh_render_data_looptri_flag(rdata, f);
#if USE_10_10_10
PackedNormal vnor = convert_i10_s3(svnor);
PackedNormal lnor = convert_i10_s3(slnor);
VertexBuffer_set_attrib(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
VertexBuffer_set_attrib(vbo_nor, lnor_id, base_vert_idx + i, &lnor);
#else
VertexBuffer_set_attrib(vbo_nor, vnor_id, base_vert_idx + i, svnor);
VertexBuffer_set_attrib(vbo_nor, lnor_id, base_vert_idx + i, slnor);
#endif
}
}
if (vbo_data) {
fflag = mesh_render_data_looptri_flag(rdata, f);
for (int i = 0; i < 3; ++i) {
int iedge = (i == 2) ? 0 : i+1;
eattr = mesh_render_data_edge_flag(rdata, tri_edge_idx[iedge]);
vflag = mesh_render_data_vertex_flag(rdata, tri_vert_idx[i]);
eattr->v_flag = fflag | vflag;
VertexBuffer_set_attrib(vbo_data, data_id, base_vert_idx + i, eattr);
}
}
}
static void add_overlay_loose_edge(
MeshRenderData *rdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
const int v1, const int v2, const int e, const int base_vert_idx)
MeshRenderData *rdata, VertexBuffer *vbo_pos, VertexBuffer *vbo_nor, VertexBuffer *vbo_data,
const unsigned int pos_id, const unsigned int vnor_id, const unsigned int data_id,
const int edge_vert_idx[2], const int e, const int base_vert_idx)
{
EdgeDrawAttr *eattr = mesh_render_data_edge_flag(rdata, e);
const float *pos = mesh_render_data_vert_co(rdata, v1);
eattr->v_flag = mesh_render_data_vertex_flag(rdata, v1);
VertexBuffer_set_attrib(vbo, pos_id, base_vert_idx + 0, pos);
VertexBuffer_set_attrib(vbo, edgeMod_id, base_vert_idx + 0, eattr);
if (vbo_pos) {
for (int i = 0; i < 2; ++i) {
const float *pos = mesh_render_data_vert_co(rdata, edge_vert_idx[i]);
VertexBuffer_set_attrib(vbo_pos, pos_id, base_vert_idx + i, pos);
}
}
pos = mesh_render_data_vert_co(rdata, v2);
eattr->v_flag = mesh_render_data_vertex_flag(rdata, v2);
VertexBuffer_set_attrib(vbo, pos_id, base_vert_idx + 1, pos);
VertexBuffer_set_attrib(vbo, edgeMod_id, base_vert_idx + 1, eattr);
if (vbo_nor) {
for (int i = 0; i < 2; ++i) {
short *nor = mesh_render_data_vert_nor(rdata, edge_vert_idx[i]);
#if USE_10_10_10
PackedNormal vnor = convert_i10_s3(nor);
VertexBuffer_set_attrib(vbo_nor, vnor_id, base_vert_idx + i, &vnor);
#else
VertexBuffer_set_attrib(vbo_nor, vnor_id, base_vert_idx + i, &nor);
#endif
}
}
if (vbo_data) {
EdgeDrawAttr *eattr = mesh_render_data_edge_flag(rdata, e);
for (int i = 0; i < 2; ++i) {
eattr->v_flag = mesh_render_data_vertex_flag(rdata, edge_vert_idx[i]);
VertexBuffer_set_attrib(vbo_data, data_id, base_vert_idx + i, eattr);
}
}
}
static void add_overlay_loose_vert(
MeshRenderData *rdata, VertexBuffer *vbo, const unsigned int pos_id, const unsigned int edgeMod_id,
MeshRenderData *rdata, VertexBuffer *vbo_pos, VertexBuffer *vbo_nor, VertexBuffer *vbo_data,
const unsigned int pos_id, const unsigned int vnor_id, const unsigned int data_id,
const int v, const int base_vert_idx)
{
unsigned char vflag[4] = {0, 0, 0, 0};
const float *pos = mesh_render_data_vert_co(rdata, v);
vflag[0] = mesh_render_data_vertex_flag(rdata, v);
VertexBuffer_set_attrib(vbo, pos_id, base_vert_idx + 0, pos);
VertexBuffer_set_attrib(vbo, edgeMod_id, base_vert_idx + 0, vflag);
if (vbo_pos) {
const float *pos = mesh_render_data_vert_co(rdata, v);
VertexBuffer_set_attrib(vbo_pos, pos_id, base_vert_idx, pos);
}
if (vbo_nor) {
short *nor = mesh_render_data_vert_nor(rdata, v);
#if USE_10_10_10
PackedNormal vnor = convert_i10_s3(edge_nor);
VertexBuffer_set_attrib(vbo_nor, vnor_id, base_vert_idx, &vnor);
#else
VertexBuffer_set_attrib(vbo_nor, vnor_id, base_vert_idx, nor);
#endif
}
if (vbo_data) {
unsigned char vflag[4] = {0, 0, 0, 0};
vflag[0] = mesh_render_data_vertex_flag(rdata, v);
VertexBuffer_set_attrib(vbo_data, data_id, base_vert_idx, vflag);
}
}
/** \} */
@ -1646,14 +1702,29 @@ typedef struct MeshBatchCache {
ElementList **shaded_triangles_in_order;
Batch **shaded_triangles;
/* TODO : split in 2 buffers to avoid unnecessary
* data transfer when selecting/deselecting
* and combine into one batch and use offsets to render
* Tri / edges / verts separately */
/* Edit Cage Mesh buffers */
VertexBuffer *ed_tri_pos;
VertexBuffer *ed_tri_nor; /* LoopNor, VertNor */
VertexBuffer *ed_tri_data;
VertexBuffer *ed_ledge_pos;
VertexBuffer *ed_ledge_nor; /* VertNor */
VertexBuffer *ed_ledge_data;
VertexBuffer *ed_lvert_pos;
VertexBuffer *ed_lvert_nor; /* VertNor */
VertexBuffer *ed_lvert_data;
VertexBuffer *ed_fcenter_pos;
VertexBuffer *ed_fcenter_nor;
Batch *overlay_triangles;
Batch *overlay_loose_verts;
Batch *overlay_triangles_nor; /* PRIM_POINTS */
Batch *overlay_loose_edges;
Batch *overlay_loose_edges_nor; /* PRIM_POINTS */
Batch *overlay_loose_verts;
Batch *overlay_facedots;
Batch *overlay_paint_edges;
Batch *overlay_weight_faces;
Batch *overlay_weight_verts;
@ -1758,11 +1829,14 @@ void DRW_mesh_batch_cache_dirty(Mesh *me, int mode)
cache->is_dirty = true;
break;
case BKE_MESH_BATCH_DIRTY_SELECT:
/* TODO Separate Flag vbo */
BATCH_DISCARD_ALL_SAFE(cache->overlay_triangles);
BATCH_DISCARD_ALL_SAFE(cache->overlay_loose_verts);
BATCH_DISCARD_ALL_SAFE(cache->overlay_loose_edges);
BATCH_DISCARD_ALL_SAFE(cache->overlay_facedots);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_tri_data);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_ledge_data);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_lvert_data);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_fcenter_nor); /* Contains select flag */
BATCH_DISCARD_SAFE(cache->overlay_triangles);
BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
BATCH_DISCARD_SAFE(cache->overlay_facedots);
break;
case BKE_MESH_BATCH_DIRTY_PAINT:
cache->is_paint_dirty = true;
@ -1787,10 +1861,22 @@ static void mesh_batch_cache_clear(Mesh *me)
ELEMENTLIST_DISCARD_SAFE(cache->edges_in_order);
ELEMENTLIST_DISCARD_SAFE(cache->triangles_in_order);
BATCH_DISCARD_ALL_SAFE(cache->overlay_triangles);
BATCH_DISCARD_ALL_SAFE(cache->overlay_loose_verts);
BATCH_DISCARD_ALL_SAFE(cache->overlay_loose_edges);
BATCH_DISCARD_ALL_SAFE(cache->overlay_facedots);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_tri_pos);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_tri_nor);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_tri_data);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_ledge_pos);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_ledge_nor);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_ledge_data);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_lvert_pos);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_lvert_nor);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_lvert_data);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_fcenter_pos);
VERTEXBUFFER_DISCARD_SAFE(cache->ed_fcenter_nor);
BATCH_DISCARD_SAFE(cache->overlay_triangles);
BATCH_DISCARD_SAFE(cache->overlay_loose_verts);
BATCH_DISCARD_SAFE(cache->overlay_loose_edges);
BATCH_DISCARD_SAFE(cache->overlay_facedots);
BATCH_DISCARD_ALL_SAFE(cache->overlay_paint_edges);
BATCH_DISCARD_ALL_SAFE(cache->overlay_weight_faces);
BATCH_DISCARD_ALL_SAFE(cache->overlay_weight_verts);
@ -2197,6 +2283,341 @@ static VertexBuffer *mesh_batch_cache_get_vert_pos_and_nor_in_order(
return cache->pos_in_order;
}
static VertexFormat *edit_mesh_overlay_pos_format(unsigned int *r_pos_id)
{
static VertexFormat format_pos = { 0 };
static unsigned pos_id;
if (format_pos.attrib_ct == 0) {
pos_id = VertexFormat_add_attrib(&format_pos, "pos", COMP_F32, 3, KEEP_FLOAT);
}
*r_pos_id = pos_id;
return &format_pos;
}
static VertexFormat *edit_mesh_overlay_nor_format(unsigned int *r_vnor_id, unsigned int *r_lnor_id)
{
static VertexFormat format_nor = { 0 };
static VertexFormat format_nor_loop = { 0 };
static unsigned vnor_id, vnor_loop_id, lnor_id;
if (format_nor.attrib_ct == 0) {
#if USE_10_10_10
vnor_id = VertexFormat_add_attrib(&format_nor, "vnor", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
vnor_loop_id = VertexFormat_add_attrib(&format_nor_loop, "vnor", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
lnor_id = VertexFormat_add_attrib(&format_nor_loop, "lnor", COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
#else
vnor_id = VertexFormat_add_attrib(&format_nor, "vnor", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT);
vnor_loop_id = VertexFormat_add_attrib(&format_nor_loop, "vnor", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT);
lnor_id = VertexFormat_add_attrib(&format_nor_loop, "lnor", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT);
#endif
}
if (r_lnor_id) {
*r_vnor_id = vnor_loop_id;
*r_lnor_id = lnor_id;
return &format_nor_loop;
}
else {
*r_vnor_id = vnor_id;
return &format_nor;
}
}
static VertexFormat *edit_mesh_overlay_data_format(unsigned int *r_data_id)
{
static VertexFormat format_flag = { 0 };
static unsigned data_id;
if (format_flag.attrib_ct == 0) {
data_id = VertexFormat_add_attrib(&format_flag, "data", COMP_U8, 4, KEEP_INT);
}
*r_data_id = data_id;
return &format_flag;
}
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);
const int vbo_len_capacity = tri_len * 3;
int vbo_len_used = 0;
/* Positions */
VertexBuffer *vbo_pos = NULL;
static unsigned pos_id;
if (cache->ed_tri_pos == NULL) {
vbo_pos = cache->ed_tri_pos = VertexBuffer_create_with_format(edit_mesh_overlay_pos_format(&pos_id));
VertexBuffer_allocate_data(vbo_pos, vbo_len_capacity);
}
/* Normals */
VertexBuffer *vbo_nor = NULL;
static unsigned vnor_id, lnor_id;
if (cache->ed_tri_nor == NULL) {
vbo_nor = cache->ed_tri_nor = VertexBuffer_create_with_format(edit_mesh_overlay_nor_format(&vnor_id, &lnor_id));
VertexBuffer_allocate_data(vbo_nor, vbo_len_capacity);
}
/* Data */
VertexBuffer *vbo_data = NULL;
static unsigned data_id;
if (cache->ed_tri_data == NULL) {
vbo_data = cache->ed_tri_data = VertexBuffer_create_with_format(edit_mesh_overlay_data_format(&data_id));
VertexBuffer_allocate_data(vbo_data, vbo_len_capacity);
}
for (int i = 0; i < tri_len; ++i) {
int tri_vert_idx[3], tri_edge_idx[3];
if (mesh_render_data_looptri_vert_edge_indices_get(rdata, i, tri_vert_idx, tri_edge_idx)) {
add_overlay_tri(
rdata, vbo_pos, vbo_nor, vbo_data,
pos_id, vnor_id, lnor_id, data_id,
tri_vert_idx, tri_edge_idx, i, vbo_len_used);
vbo_len_used += 3;
}
}
/* Finish */
if (vbo_len_used != vbo_len_capacity) {
if (vbo_pos != NULL) {
VertexBuffer_resize_data(vbo_pos, vbo_len_used);
}
if (vbo_nor != NULL) {
VertexBuffer_resize_data(vbo_nor, vbo_len_used);
}
if (vbo_data != NULL) {
VertexBuffer_resize_data(vbo_data, vbo_len_used);
}
}
}
static void mesh_batch_cache_create_overlay_ledge_buffers(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
const int ledge_len = mesh_render_data_loose_edges_len_get(rdata);
const int vbo_len_capacity = ledge_len * 2;
int vbo_len_used = 0;
/* Positions */
VertexBuffer *vbo_pos = NULL;
static unsigned pos_id;
if (cache->ed_ledge_pos == NULL) {
vbo_pos = cache->ed_ledge_pos = VertexBuffer_create_with_format(edit_mesh_overlay_pos_format(&pos_id));
VertexBuffer_allocate_data(vbo_pos, vbo_len_capacity);
}
/* Normals */
VertexBuffer *vbo_nor = NULL;
static unsigned vnor_id;
if (cache->ed_ledge_nor == NULL) {
vbo_nor = cache->ed_ledge_nor = VertexBuffer_create_with_format(edit_mesh_overlay_nor_format(&vnor_id, NULL));
VertexBuffer_allocate_data(vbo_nor, vbo_len_capacity);
}
/* Data */
VertexBuffer *vbo_data = NULL;
static unsigned data_id;
if (cache->ed_ledge_data == NULL) {
vbo_data = cache->ed_ledge_data = VertexBuffer_create_with_format(edit_mesh_overlay_data_format(&data_id));
VertexBuffer_allocate_data(vbo_data, vbo_len_capacity);
}
for (int i = 0; i < ledge_len; ++i) {
int vert_idx[2];
bool ok = mesh_render_data_edge_verts_indices_get(rdata, rdata->loose_edges[i], vert_idx);
BLI_assert(ok); /* we don't add */
add_overlay_loose_edge(
rdata, vbo_pos, vbo_nor, vbo_data,
pos_id, vnor_id, data_id,
vert_idx, i, vbo_len_used);
vbo_len_used += 2;
}
/* Finish */
if (vbo_len_used != vbo_len_capacity) {
if (vbo_pos != NULL) {
VertexBuffer_resize_data(vbo_pos, vbo_len_used);
}
if (vbo_nor != NULL) {
VertexBuffer_resize_data(vbo_nor, vbo_len_used);
}
if (vbo_data != NULL) {
VertexBuffer_resize_data(vbo_data, vbo_len_used);
}
}
}
static void mesh_batch_cache_create_overlay_lvert_buffers(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI));
const int lvert_len = mesh_render_data_loose_verts_len_get(rdata);
const int vbo_len_capacity = lvert_len;
int vbo_len_used = 0;
/* Positions */
VertexBuffer *vbo_pos = NULL;
static unsigned pos_id;
if (cache->ed_lvert_pos == NULL) {
vbo_pos = cache->ed_lvert_pos = VertexBuffer_create_with_format(edit_mesh_overlay_pos_format(&pos_id));
VertexBuffer_allocate_data(vbo_pos, vbo_len_capacity);
}
/* Normals */
VertexBuffer *vbo_nor = NULL;
static unsigned vnor_id;
if (cache->ed_lvert_nor == NULL) {
vbo_nor = cache->ed_lvert_nor = VertexBuffer_create_with_format(edit_mesh_overlay_nor_format(&vnor_id, NULL));
VertexBuffer_allocate_data(vbo_nor, vbo_len_capacity);
}
/* Data */
VertexBuffer *vbo_data = NULL;
static unsigned data_id;
if (cache->ed_lvert_data == NULL) {
vbo_data = cache->ed_lvert_data = VertexBuffer_create_with_format(edit_mesh_overlay_data_format(&data_id));
VertexBuffer_allocate_data(vbo_data, vbo_len_capacity);
}
for (int i = 0; i < lvert_len; ++i) {
add_overlay_loose_vert(
rdata, vbo_pos, vbo_nor, vbo_data,
pos_id, vnor_id, data_id,
rdata->loose_verts[i], vbo_len_used);
vbo_len_used += 1;
}
/* Finish */
if (vbo_len_used != vbo_len_capacity) {
if (vbo_pos != NULL) {
VertexBuffer_resize_data(vbo_pos, vbo_len_used);
}
if (vbo_nor != NULL) {
VertexBuffer_resize_data(vbo_nor, vbo_len_used);
}
if (vbo_data != NULL) {
VertexBuffer_resize_data(vbo_data, vbo_len_used);
}
}
}
/* Position */
static VertexBuffer *mesh_batch_cache_get_edit_tri_pos(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_tri_pos == NULL) {
mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
}
return cache->ed_tri_pos;
}
static VertexBuffer *mesh_batch_cache_get_edit_ledge_pos(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_ledge_pos == NULL) {
mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
}
return cache->ed_ledge_pos;
}
static VertexBuffer *mesh_batch_cache_get_edit_lvert_pos(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_lvert_pos == NULL) {
mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
}
return cache->ed_lvert_pos;
}
/* Normal */
static VertexBuffer *mesh_batch_cache_get_edit_tri_nor(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_tri_nor == NULL) {
mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
}
return cache->ed_tri_nor;
}
static VertexBuffer *mesh_batch_cache_get_edit_ledge_nor(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_ledge_nor == NULL) {
mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
}
return cache->ed_ledge_nor;
}
static VertexBuffer *mesh_batch_cache_get_edit_lvert_nor(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_lvert_nor == NULL) {
mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
}
return cache->ed_lvert_nor;
}
/* Data */
static VertexBuffer *mesh_batch_cache_get_edit_tri_data(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_tri_data == NULL) {
mesh_batch_cache_create_overlay_tri_buffers(rdata, cache);
}
return cache->ed_tri_data;
}
static VertexBuffer *mesh_batch_cache_get_edit_ledge_data(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_ledge_data == NULL) {
mesh_batch_cache_create_overlay_ledge_buffers(rdata, cache);
}
return cache->ed_ledge_data;
}
static VertexBuffer *mesh_batch_cache_get_edit_lvert_data(
MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
if (cache->ed_lvert_data == NULL) {
mesh_batch_cache_create_overlay_lvert_buffers(rdata, cache);
}
return cache->ed_lvert_data;
}
static ElementList *mesh_batch_cache_get_edges_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE));
@ -2671,76 +3092,37 @@ Batch *DRW_mesh_batch_cache_get_fancy_edges(Mesh *me)
static void mesh_batch_cache_create_overlay_batches(Mesh *me)
{
/* Since MR_DATATYPE_OVERLAY is slow to generate, generate them all at once */
int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY;
int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_OVERLAY;
MeshBatchCache *cache = mesh_batch_cache_get(me);
MeshRenderData *rdata = mesh_render_data_create(me, options);
static VertexFormat format = { 0 };
static unsigned pos_id, data_id;
if (format.attrib_ct == 0) {
/* initialize vertex format */
pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
data_id = VertexFormat_add_attrib(&format, "data", COMP_U8, 4, KEEP_INT);
}
const int tri_len = mesh_render_data_looptri_len_get(rdata);
const int ledge_len = mesh_render_data_loose_edges_len_get(rdata);
const int lvert_len = mesh_render_data_loose_verts_len_get(rdata);
if (cache->overlay_triangles == NULL) {
VertexBuffer *vbo = 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) {
int tri_vert_idx[3], tri_edge_idx[3];
if (mesh_render_data_looptri_vert_edge_indices_get(rdata, i, tri_vert_idx, tri_edge_idx)) {
add_overlay_tri(
rdata, vbo, pos_id, data_id,
tri_vert_idx, tri_edge_idx, i, vbo_len_used);
vbo_len_used += 3;
}
}
if (vbo_len_used != vbo_len_capacity) {
VertexBuffer_resize_data(vbo, vbo_len_used);
}
cache->overlay_triangles = Batch_create(PRIM_TRIANGLES, vbo, NULL);
cache->overlay_triangles = Batch_create(PRIM_TRIANGLES, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
Batch_add_VertexBuffer(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
Batch_add_VertexBuffer(cache->overlay_triangles, mesh_batch_cache_get_edit_tri_data(rdata, cache));
}
if (cache->overlay_loose_edges == NULL) {
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
const int vbo_len_capacity = ledge_len * 2;
int vbo_len_used = 0;
VertexBuffer_allocate_data(vbo, vbo_len_capacity);
for (int i = 0; i < ledge_len; ++i) {
int vert_idx[2];
bool ok = mesh_render_data_edge_verts_indices_get(rdata, rdata->loose_edges[i], vert_idx);
assert(ok); /* we don't add */
add_overlay_loose_edge(
rdata, vbo, pos_id, data_id,
vert_idx[0], vert_idx[1], rdata->loose_edges[i], vbo_len_used);
vbo_len_used += 2;
}
BLI_assert(vbo_len_used == vbo_len_capacity);
cache->overlay_loose_edges = Batch_create(PRIM_LINES, vbo, NULL);
cache->overlay_loose_edges = Batch_create(PRIM_LINES, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
Batch_add_VertexBuffer(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
Batch_add_VertexBuffer(cache->overlay_loose_edges, mesh_batch_cache_get_edit_ledge_data(rdata, cache));
}
if (cache->overlay_loose_verts == NULL) {
VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
const int vbo_len_capacity = lvert_len;
int vbo_len_used = 0;
VertexBuffer_allocate_data(vbo, vbo_len_capacity);
cache->overlay_loose_verts = Batch_create(PRIM_POINTS, mesh_batch_cache_get_edit_lvert_pos(rdata, cache), NULL);
Batch_add_VertexBuffer(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_nor(rdata, cache));
Batch_add_VertexBuffer(cache->overlay_loose_verts, mesh_batch_cache_get_edit_lvert_data(rdata, cache));
}
for (int i = 0; i < lvert_len; ++i) {
add_overlay_loose_vert(rdata, vbo, pos_id, data_id,
rdata->loose_verts[i], vbo_len_used);
vbo_len_used += 1;
}
BLI_assert(vbo_len_used == vbo_len_capacity);
cache->overlay_loose_verts = Batch_create(PRIM_POINTS, vbo, NULL);
if (cache->overlay_triangles_nor == NULL) {
cache->overlay_triangles_nor = Batch_create(PRIM_POINTS, mesh_batch_cache_get_edit_tri_pos(rdata, cache), NULL);
Batch_add_VertexBuffer(cache->overlay_triangles_nor, mesh_batch_cache_get_edit_tri_nor(rdata, cache));
}
if (cache->overlay_loose_edges_nor == NULL) {
cache->overlay_loose_edges_nor = Batch_create(PRIM_POINTS, mesh_batch_cache_get_edit_ledge_pos(rdata, cache), NULL);
Batch_add_VertexBuffer(cache->overlay_loose_edges_nor, mesh_batch_cache_get_edit_ledge_nor(rdata, cache));
}
mesh_render_data_free(rdata);
@ -2779,6 +3161,28 @@ Batch *DRW_mesh_batch_cache_get_overlay_loose_verts(Mesh *me)
return cache->overlay_loose_verts;
}
Batch *DRW_mesh_batch_cache_get_overlay_triangles_nor(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->overlay_triangles_nor == NULL) {
mesh_batch_cache_create_overlay_batches(me);
}
return cache->overlay_triangles_nor;
}
Batch *DRW_mesh_batch_cache_get_overlay_loose_edges_nor(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
if (cache->overlay_loose_edges_nor == NULL) {
mesh_batch_cache_create_overlay_batches(me);
}
return cache->overlay_loose_edges_nor;
}
Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);

View File

@ -101,6 +101,7 @@ static struct {
GPUShader *overlay_mix_sh;
GPUShader *overlay_facefill_sh;
GPUShader *normals_face_sh;
GPUShader *normals_loop_sh;
GPUShader *normals_sh;
GPUShader *depth_sh;
} e_data = {NULL}; /* Engine data */
@ -224,6 +225,13 @@ static void EDIT_MESH_engine_init(void *vedata)
datatoc_gpu_shader_uniform_color_frag_glsl,
"#define FACE_NORMALS\n");
}
if (!e_data.normals_loop_sh) {
e_data.normals_loop_sh = DRW_shader_create(
datatoc_edit_normals_vert_glsl,
datatoc_edit_normals_geom_glsl,
datatoc_gpu_shader_uniform_color_frag_glsl,
"#define LOOP_NORMALS\n");
}
if (!e_data.normals_sh) {
e_data.normals_sh = DRW_shader_create(
datatoc_edit_normals_vert_glsl,
@ -347,7 +355,7 @@ static void EDIT_MESH_cache_init(void *vedata)
DRW_shgroup_uniform_float(stl->g_data->vnormals_shgrp, "normalSize", &size_normal, 1);
DRW_shgroup_uniform_vec4(stl->g_data->vnormals_shgrp, "color", ts.colorVNormal, 1);
stl->g_data->lnormals_shgrp = DRW_shgroup_create(e_data.normals_sh, psl->normals);
stl->g_data->lnormals_shgrp = DRW_shgroup_create(e_data.normals_loop_sh, psl->normals);
DRW_shgroup_uniform_float(stl->g_data->lnormals_shgrp, "normalSize", &size_normal, 1);
DRW_shgroup_uniform_vec4(stl->g_data->lnormals_shgrp, "color", ts.colorLNormal, 1);
}
@ -454,14 +462,19 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_add(stl->g_data->fnormals_shgrp, geom, ob->obmat);
}
if (vnormals_do) {
geom = DRW_cache_mesh_verts_get(ob);
DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geom, ob->obmat);
}
if (vnormals_do || lnormals_do) {
struct Batch *geo_ovl_tris, *geo_ovl_ledges, *geo_ovl_lverts;
DRW_cache_mesh_normals_overlay_get(ob, &geo_ovl_tris, &geo_ovl_ledges, &geo_ovl_lverts);
if (lnormals_do) {
geom = DRW_cache_mesh_surface_verts_get(ob);
DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geom, ob->obmat);
if (vnormals_do) {
DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_tris, ob->obmat);
DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_ledges, ob->obmat);
DRW_shgroup_call_add(stl->g_data->vnormals_shgrp, geo_ovl_lverts, ob->obmat);
}
if (lnormals_do) {
DRW_shgroup_call_add(stl->g_data->lnormals_shgrp, geo_ovl_tris, ob->obmat);
}
}
if ((v3d->flag & V3D_ZBUF_SELECT) == 0) {
@ -543,6 +556,7 @@ static void EDIT_MESH_engine_free(void)
DRW_SHADER_FREE_SAFE(e_data.overlay_facedot_sh);
DRW_SHADER_FREE_SAFE(e_data.overlay_mix_sh);
DRW_SHADER_FREE_SAFE(e_data.overlay_facefill_sh);
DRW_SHADER_FREE_SAFE(e_data.normals_loop_sh);
DRW_SHADER_FREE_SAFE(e_data.normals_face_sh);
DRW_SHADER_FREE_SAFE(e_data.normals_sh);
}

View File

@ -1,18 +0,0 @@
uniform mat4 ModelViewProjectionMatrix;
uniform mat3 NormalMatrix;
uniform mat4 ProjectionMatrix;
uniform float normalSize;
in vec3 pos;
in vec4 norAndFlag;
flat out vec4 v1;
flat out vec4 v2;
void main()
{
v1 = ModelViewProjectionMatrix * vec4(pos, 1.0);
vec3 n = normalize(NormalMatrix * norAndFlag.xyz); /* viewspace */
v2 = v1 + ProjectionMatrix * vec4(n * normalSize, 0.0);
}

View File

@ -6,11 +6,17 @@ uniform float normalSize;
in vec3 pos;
#ifdef FACE_NORMALS
#ifdef LOOP_NORMALS
in vec3 lnor;
#define nor lnor
#elif defined(FACE_NORMALS)
in vec4 norAndFlag;
#define nor norAndFlag.xyz
#else
in vec3 nor;
in vec3 vnor;
#define nor vnor
#endif
flat out vec4 v1;