diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2018-05-31 19:43:19 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2018-05-31 20:09:20 +0300 |
commit | 712885c30ef2a8dbde91b7d8b4ffb9784a70fca5 (patch) | |
tree | ec2e82668e1524b82d77d8b20950f56d6c0e7e4c /source | |
parent | f43e3d0b6bee3bef69649e4ebb85bdebdf19e8ce (diff) |
DRW: Add wireframe buffer texture generation for wireframe drawing.
Only OB_MESH is supported for now.
Creates a simple index buffer with negative indices if the edges is not a
real edge.
Also create the buffer texture representation of this buffer along with the
pos_in_order buffer texture.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 14 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 4 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 115 |
4 files changed, 129 insertions, 6 deletions
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index ddf41ceff8a..33fb801af5a 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -502,7 +502,6 @@ Gwn_Batch *DRW_cache_object_wire_outline_get(Object *ob) } } -/* Returns a buffer texture. */ Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold) { switch (ob->type) { @@ -515,6 +514,19 @@ Gwn_Batch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold) } } +/* Returns a buffer texture. */ +void DRW_cache_object_face_wireframe_get( + Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count) +{ + switch (ob->type) { + case OB_MESH: + DRW_mesh_batch_cache_get_wireframes_face_texbuf((Mesh *)ob->data, r_vert_tx, r_faceid_tx, r_tri_count); + + /* TODO, should match 'DRW_cache_object_surface_get' */ + } +} + + Gwn_Batch *DRW_cache_object_surface_get(Object *ob) { switch (ob->type) { diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 1fd6b22c221..e962d513c9b 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -53,6 +53,8 @@ struct Gwn_Batch *DRW_cache_object_surface_get(struct Object *ob); struct Gwn_Batch **DRW_cache_object_surface_material_get( struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len, char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count); +void DRW_cache_object_face_wireframe_get( + Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count); /* Empties */ struct Gwn_Batch *DRW_cache_plain_axes_get(void); diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index f77dafc9b31..8a8d41cb38a 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -28,6 +28,7 @@ struct CurveCache; struct GPUMaterial; +struct GPUTexture; struct Gwn_Batch; struct Gwn_IndexBuf; struct Gwn_VertBuf; @@ -121,6 +122,9 @@ struct Gwn_Batch *DRW_mesh_batch_cache_get_overlay_facedots(struct Mesh *me); struct Gwn_Batch *DRW_mesh_batch_cache_get_facedots_with_select_id(struct Mesh *me, uint select_id_offset); struct Gwn_Batch *DRW_mesh_batch_cache_get_edges_with_select_id(struct Mesh *me, uint select_id_offset); struct Gwn_Batch *DRW_mesh_batch_cache_get_verts_with_select_id(struct Mesh *me, uint select_id_offset); +/* Object mode Wireframe overlays */ +void DRW_mesh_batch_cache_get_wireframes_face_texbuf( + struct Mesh *me, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count); void DRW_mesh_cache_sculpt_coords_ensure(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 e1b66a85ca2..d6651125b58 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1541,11 +1541,12 @@ static void add_overlay_loose_vert( typedef struct MeshBatchCache { Gwn_VertBuf *pos_in_order; - Gwn_VertBuf *nor_in_order; Gwn_IndexBuf *edges_in_order; Gwn_IndexBuf *edges_adjacency; /* Store edges with adjacent vertices. */ Gwn_IndexBuf *triangles_in_order; + GPUTexture *pos_in_order_tx; /* Depending on pos_in_order */ + Gwn_Batch *all_verts; Gwn_Batch *all_edges; Gwn_Batch *all_triangles; @@ -1584,6 +1585,9 @@ typedef struct MeshBatchCache { Gwn_Batch *edge_detection; + GPUTexture *edges_face_overlay_tx; + int edges_face_overlay_tri_count; /* Number of tri in edges_face_overlay_tx */ + /* Maybe have shaded_triangles_data split into pos_nor and uv_tangent * to minimise data transfer for skinned mesh. */ Gwn_VertFormat shaded_triangles_format; @@ -1816,6 +1820,7 @@ static void mesh_batch_cache_clear(Mesh *me) GWN_BATCH_DISCARD_SAFE(cache->all_triangles); GWN_VERTBUF_DISCARD_SAFE(cache->pos_in_order); + DRW_TEXTURE_FREE_SAFE(cache->pos_in_order_tx); GWN_INDEXBUF_DISCARD_SAFE(cache->edges_in_order); GWN_INDEXBUF_DISCARD_SAFE(cache->triangles_in_order); @@ -1859,6 +1864,8 @@ static void mesh_batch_cache_clear(Mesh *me) GWN_INDEXBUF_DISCARD_SAFE(cache->edges_adjacency); GWN_BATCH_DISCARD_SAFE(cache->edge_detection); + DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_tx); + GWN_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data); if (cache->shaded_triangles_in_order) { for (int i = 0; i < cache->mat_len; ++i) { @@ -2826,8 +2833,9 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order( static Gwn_VertFormat format = { 0 }; static struct { uint pos, nor; } attr_id; if (format.attrib_ct == 0) { + /* Normal is padded so that the vbo can be used as a buffer texture */ attr_id.pos = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 3, GWN_FETCH_INT_TO_FLOAT_UNIT); + attr_id.nor = GWN_vertformat_attr_add(&format, "nor", GWN_COMP_I16, 4, GWN_FETCH_INT_TO_FLOAT_UNIT); } Gwn_VertBuf *vbo = cache->pos_in_order = GWN_vertbuf_create_with_format(&format); @@ -2841,7 +2849,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order( uint i; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - static short no_short[3]; + static short no_short[4]; normal_float_to_short_v3(no_short, eve->no); GWN_vertbuf_attr_set(vbo, attr_id.pos, i, eve->co); @@ -2852,7 +2860,7 @@ static Gwn_VertBuf *mesh_batch_cache_get_vert_pos_and_nor_in_order( else { for (int i = 0; i < vbo_len_capacity; ++i) { GWN_vertbuf_attr_set(vbo, attr_id.pos, i, rdata->mvert[i].co); - GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no); + GWN_vertbuf_attr_set(vbo, attr_id.nor, i, rdata->mvert[i].no); /* XXX actually reading 4 shorts */ } } } @@ -3323,10 +3331,86 @@ static Gwn_IndexBuf *mesh_batch_cache_get_edges_adjacency(MeshRenderData *rdata, } return cache->edges_adjacency; - } #undef NO_EDGE +static GPUTexture *mesh_batch_cache_get_edges_overlay_texture_buf(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI)); + + BLI_assert(rdata->edit_bmesh == NULL); /* Not supported in edit mode */ + + if (cache->edges_face_overlay_tx != NULL) { + return cache->edges_face_overlay_tx; + } + + const int tri_len = mesh_render_data_looptri_len_get(rdata); + + cache->is_manifold = true; + + Gwn_VertFormat format = {0}; + uint index_id = GWN_vertformat_attr_add(&format, "index", GWN_COMP_I32, 1, GWN_FETCH_INT); + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(&format); + + int vbo_len_capacity = tri_len * 3; + GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); + + int vidx = 0; + + for (int i = 0; i < tri_len; i++) { + bool edge_is_real[3] = {false, false, false}; + + MEdge *medge = rdata->medge; + MLoop *mloop = rdata->mloop; + MLoopTri *mlt = rdata->mlooptri + i; + + int j, j_next; + for (j = 2, j_next = 0; j_next < 3; j = j_next++) { + MEdge *ed = &medge[mloop[mlt->tri[j]].e]; + unsigned int tri_edge[2] = {mloop[mlt->tri[j]].v, mloop[mlt->tri[j_next]].v}; + + if (((ed->v1 == tri_edge[0]) && (ed->v2 == tri_edge[1])) || + ((ed->v1 == tri_edge[1]) && (ed->v2 == tri_edge[0]))) + { + edge_is_real[j] = true; + } + } + + for (int e = 0; e < 3; ++e) { + /* Save if there is an edge or not inside the sign bit. */ + int value = (int)mloop[mlt->tri[e]].v + 1; /* Int 0 cannot be signed */ + value = (edge_is_real[e]) ? -value : value; + GWN_vertbuf_attr_set(vbo, index_id, vidx++, &value); + } + } + + int vbo_len_used = vidx; + + if (vbo_len_capacity != vbo_len_used) { + GWN_vertbuf_data_resize(vbo, vbo_len_used); + } + + /* Upload data early because we need to create the texture for it. */ + GWN_vertbuf_use(vbo); + cache->edges_face_overlay_tx = GPU_texture_create_from_vertbuf(vbo); + cache->edges_face_overlay_tri_count = vbo_len_used / 3; + + return cache->edges_face_overlay_tx; +} + +static GPUTexture *mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(MeshRenderData *rdata, MeshBatchCache *cache) +{ + BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI)); + + if (cache->pos_in_order_tx == NULL) { + Gwn_VertBuf *pos_in_order = mesh_batch_cache_get_vert_pos_and_nor_in_order(rdata, cache); + GWN_vertbuf_use(pos_in_order); /* Upload early for buffer texture creation. */ + cache->pos_in_order_tx = GPU_texture_create_buffer(GPU_R32F, pos_in_order->vbo_id); + } + + return cache->pos_in_order_tx; +} + static Gwn_IndexBuf *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache) { BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI)); @@ -3857,6 +3941,27 @@ Gwn_Batch *DRW_mesh_batch_cache_get_edge_detection(Mesh *me, bool *r_is_manifold return cache->edge_detection; } +void DRW_mesh_batch_cache_get_wireframes_face_texbuf( + Mesh *me, GPUTexture **verts_data, GPUTexture **face_indices, int *tri_count) +{ + MeshBatchCache *cache = mesh_batch_cache_get(me); + + if (cache->edges_face_overlay_tx == NULL || cache->pos_in_order_tx == NULL) { + const int options = MR_DATATYPE_VERT | MR_DATATYPE_EDGE | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI; + + MeshRenderData *rdata = mesh_render_data_create(me, options); + + mesh_batch_cache_get_edges_overlay_texture_buf(rdata, cache); + mesh_batch_cache_get_vert_pos_and_nor_in_order_buf(rdata, cache); + + mesh_render_data_free(rdata); + } + + *tri_count = cache->edges_face_overlay_tri_count; + *face_indices = cache->edges_face_overlay_tx; + *verts_data = cache->pos_in_order_tx; +} + static void mesh_batch_cache_create_overlay_batches(Mesh *me) { BLI_assert(me->edit_btmesh != NULL); |