From ff6e61f09ab2c86edef651fc38c242f5fefdd569 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Fri, 23 Nov 2018 18:02:34 +0100 Subject: DRW: Support Wireframe for metaball objects --- source/blender/draw/intern/draw_cache.c | 11 ++- source/blender/draw/intern/draw_cache.h | 2 + source/blender/draw/intern/draw_cache_impl.h | 2 + .../blender/draw/intern/draw_cache_impl_displist.c | 53 ++++++++----- .../blender/draw/intern/draw_cache_impl_metaball.c | 92 +++++++++++++++++++++- 5 files changed, 136 insertions(+), 24 deletions(-) (limited to 'source/blender/draw/intern') diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index a2430d12f41..d6caabcb203 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -709,7 +709,9 @@ void DRW_cache_object_face_wireframe_get( case OB_FONT: DRW_cache_text_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count); break; - /* TODO, metaballs' */ + case OB_MBALL: + DRW_cache_mball_face_wireframe_get(ob, r_vert_tx, r_faceid_tx, r_tri_count); + break; } } @@ -3287,6 +3289,13 @@ GPUBatch *DRW_cache_mball_surface_get(Object *ob) return DRW_metaball_batch_cache_get_triangles_with_normals(ob); } +void DRW_cache_mball_face_wireframe_get( + Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count) +{ + BLI_assert(ob->type == OB_MBALL); + return DRW_metaball_batch_cache_get_wireframes_face_texbuf(ob, r_vert_tx, r_faceid_tx, r_tri_count); +} + GPUBatch **DRW_cache_mball_surface_shaded_get( Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len) { diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 39bbcf2c93a..d2aa2622246 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -209,5 +209,7 @@ struct GPUBatch *DRW_cache_particles_get_prim(int type); /* Metaball */ struct GPUBatch *DRW_cache_mball_surface_get(struct Object *ob); struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len); +void DRW_cache_mball_face_wireframe_get( + Object *ob, struct GPUTexture **r_vert_tx, struct GPUTexture **r_faceid_tx, int *r_tri_count); #endif /* __DRAW_CACHE_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 97e7cd240ff..9dc735807c0 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -82,6 +82,8 @@ void DRW_curve_batch_cache_get_wireframes_face_texbuf( /* Metaball */ struct GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob); struct GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(struct Object *ob, struct MetaBall *mb, struct GPUMaterial **gpumat_array, uint gpumat_array_len); +void DRW_metaball_batch_cache_get_wireframes_face_texbuf( + struct Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count); /* Curve (Font) */ struct GPUBatch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu); diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index 1053e8fa4f7..d6a57676a8d 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -91,6 +91,7 @@ typedef void (setTriIndicesFn)(void *thunk, uint v1, uint v2, uint v3); static void displist_indexbufbuilder_set( setTriIndicesFn *set_tri_indices, + setTriIndicesFn *set_quad_tri_indices, /* meh, find a better solution. */ void *thunk, const DispList *dl, const int ofs) { if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) { @@ -104,18 +105,20 @@ static void displist_indexbufbuilder_set( else if (dl->type == DL_SURF) { const int i_end = dl->totindex; for (int i = 0; i < i_end; i++, idx += 4) { - set_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs); - set_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[3] + ofs); + set_quad_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[1] + ofs); + set_quad_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[3] + ofs); } } else { BLI_assert(dl->type == DL_INDEX4); const int i_end = dl->parts; for (int i = 0; i < i_end; i++, idx += 4) { - set_tri_indices(thunk, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs); - if (idx[2] != idx[3]) { - set_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs); + set_quad_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[1] + ofs); + set_quad_tri_indices(thunk, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs); + } + else { + set_tri_indices(thunk, idx[2] + ofs, idx[0] + ofs, idx[1] + ofs); } } } @@ -173,7 +176,9 @@ GPUIndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb) int ofs = 0; for (const DispList *dl = lb->first; dl; dl = dl->next) { - displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts, &elb, dl, ofs); + displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts, + (setTriIndicesFn *)GPU_indexbuf_add_tri_verts, + &elb, dl, ofs); ofs += dl_vert_len(dl); } @@ -198,7 +203,9 @@ GPUIndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(Li /* calc each index buffer builder */ int ofs = 0; for (const DispList *dl = lb->first; dl; dl = dl->next) { - displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts, &elb[dl->col], dl, ofs); + displist_indexbufbuilder_set((setTriIndicesFn *)GPU_indexbuf_add_tri_verts, + (setTriIndicesFn *)GPU_indexbuf_add_tri_verts, + &elb[dl->col], dl, ofs); ofs += dl_vert_len(dl); } @@ -219,18 +226,21 @@ typedef struct DRWDisplistWireThunk { static void set_overlay_wires_tri_indices(void *thunk, uint v1, uint v2, uint v3) { DRWDisplistWireThunk *dwt = (DRWDisplistWireThunk *)thunk; - /* TODO consider non-manifold edges correctly. */ - if (dwt->dl_type == DL_SURF) { - /* Tag real edges. */ - v2 |= (1 << 30); - v3 |= (1 << 30); - } - else { - /* Tag real edges. */ - v1 |= (1 << 30); - v2 |= (1 << 30); - v3 |= (1 << 30); - } + /* Tag real edges. */ + v1 |= (1 << 30); + v2 |= (1 << 30); + v3 |= (1 << 30); + GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v1); + GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v2); + GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v3); +} + +static void set_overlay_wires_quad_tri_indices(void *thunk, uint v1, uint v2, uint v3) +{ + DRWDisplistWireThunk *dwt = (DRWDisplistWireThunk *)thunk; + /* Tag real edges. */ + v2 |= (1 << 30); + v3 |= (1 << 30); GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v1); GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v2); GPU_vertbuf_attr_set(dwt->vbo, dwt->index_id, dwt->vidx++, &v3); @@ -249,7 +259,10 @@ GPUVertBuf *DRW_displist_create_edges_overlay_texture_buf(ListBase *lb) int ofs = 0; for (const DispList *dl = lb->first; dl; dl = dl->next) { thunk.dl_type = dl->type; - displist_indexbufbuilder_set(set_overlay_wires_tri_indices, &thunk, dl, ofs); + /* TODO consider non-manifold edges correctly. */ + displist_indexbufbuilder_set(set_overlay_wires_tri_indices, + set_overlay_wires_quad_tri_indices, + &thunk, dl, ofs); ofs += dl_vert_len(dl); } diff --git a/source/blender/draw/intern/draw_cache_impl_metaball.c b/source/blender/draw/intern/draw_cache_impl_metaball.c index 6dab46ccaa0..b41b443039a 100644 --- a/source/blender/draw/intern/draw_cache_impl_metaball.c +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -39,6 +39,8 @@ #include "GPU_batch.h" +#include "DRW_render.h" + #include "draw_cache_impl.h" /* own include */ @@ -50,8 +52,19 @@ static void metaball_batch_cache_clear(MetaBall *mb); typedef struct MetaBallBatchCache { GPUBatch *batch; GPUBatch **shaded_triangles; - int mat_len; + + /* Shared */ + GPUVertBuf *pos_nor_in_order; + + /* Wireframe */ + struct { + GPUVertBuf *elem_vbo; + GPUTexture *elem_tx; + GPUTexture *verts_tx; + int tri_count; + } face_wire; + /* settings to determine if cache is invalid */ bool is_dirty; } MetaBallBatchCache; @@ -80,6 +93,11 @@ static void metaball_batch_cache_init(MetaBall *mb) cache->mat_len = 0; cache->shaded_triangles = NULL; cache->is_dirty = false; + cache->pos_nor_in_order = NULL; + cache->face_wire.elem_vbo = NULL; + cache->face_wire.elem_tx = NULL; + cache->face_wire.verts_tx = NULL; + cache->face_wire.tri_count = 0; } static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb) @@ -113,7 +131,12 @@ static void metaball_batch_cache_clear(MetaBall *mb) return; } + GPU_VERTBUF_DISCARD_SAFE(cache->face_wire.elem_vbo); + DRW_TEXTURE_FREE_SAFE(cache->face_wire.elem_tx); + DRW_TEXTURE_FREE_SAFE(cache->face_wire.verts_tx); + GPU_BATCH_DISCARD_SAFE(cache->batch); + GPU_VERTBUF_DISCARD_SAFE(cache->pos_nor_in_order); /* Note: shaded_triangles[0] is already freed by cache->batch */ MEM_SAFE_FREE(cache->shaded_triangles); cache->mat_len = 0; @@ -125,6 +148,45 @@ void DRW_mball_batch_cache_free(MetaBall *mb) MEM_SAFE_FREE(mb->batch_cache); } +static GPUVertBuf *mball_batch_cache_get_pos_and_normals(Object *ob, MetaBallBatchCache *cache) +{ + if (cache->pos_nor_in_order == NULL) { + ListBase *lb = &ob->runtime.curve_cache->disp; + cache->pos_nor_in_order = DRW_displist_vertbuf_calc_pos_with_normals(lb); + } + return cache->pos_nor_in_order; +} + +static GPUTexture *mball_batch_cache_get_edges_overlay_texture_buf(Object *ob, MetaBallBatchCache *cache) +{ + if (cache->face_wire.elem_tx != NULL) { + return cache->face_wire.elem_tx; + } + + ListBase *lb = &ob->runtime.curve_cache->disp; + + /* We need a special index buffer. */ + GPUVertBuf *vbo = cache->face_wire.elem_vbo = DRW_displist_create_edges_overlay_texture_buf(lb); + + /* Upload data early because we need to create the texture for it. */ + GPU_vertbuf_use(vbo); + cache->face_wire.elem_tx = GPU_texture_create_from_vertbuf(vbo); + cache->face_wire.tri_count = vbo->vertex_alloc / 3; + + return cache->face_wire.elem_tx; +} + +static GPUTexture *mball_batch_cache_get_vert_pos_and_nor_in_order_buf(Object *ob, MetaBallBatchCache *cache) +{ + if (cache->face_wire.verts_tx == NULL) { + GPUVertBuf *vbo = mball_batch_cache_get_pos_and_normals(ob, cache); + GPU_vertbuf_use(vbo); /* Upload early for buffer texture creation. */ + cache->face_wire.verts_tx = GPU_texture_create_buffer(GPU_R32F, vbo->vbo_id); + } + + return cache->face_wire.verts_tx; +} + /* -------------------------------------------------------------------- */ /** \name Public Object/MetaBall API @@ -143,9 +205,9 @@ GPUBatch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob) ListBase *lb = &ob->runtime.curve_cache->disp; cache->batch = GPU_batch_create_ex( GPU_PRIM_TRIS, - DRW_displist_vertbuf_calc_pos_with_normals(lb), + mball_batch_cache_get_pos_and_normals(ob, cache), DRW_displist_indexbuf_calc_triangles_in_order(lb), - GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX); + GPU_BATCH_OWNS_INDEX); } return cache->batch; @@ -169,3 +231,27 @@ GPUBatch **DRW_metaball_batch_cache_get_surface_shaded(Object *ob, MetaBall *mb, return cache->shaded_triangles; } + +void DRW_metaball_batch_cache_get_wireframes_face_texbuf( + Object *ob, struct GPUTexture **verts_data, struct GPUTexture **face_indices, int *tri_count) +{ + if (!BKE_mball_is_basis(ob)) { + *verts_data = NULL; + *face_indices = NULL; + *tri_count = 0; + return; + } + + MetaBall *mb = ob->data; + MetaBallBatchCache *cache = metaball_batch_cache_get(mb); + + if (cache->face_wire.verts_tx == NULL) { + *verts_data = mball_batch_cache_get_vert_pos_and_nor_in_order_buf(ob, cache); + *face_indices = mball_batch_cache_get_edges_overlay_texture_buf(ob, cache); + } + else { + *verts_data = cache->face_wire.verts_tx; + *face_indices = cache->face_wire.elem_tx; + } + *tri_count = cache->face_wire.tri_count; +} \ No newline at end of file -- cgit v1.2.3