Merge branch 'master' into blender2.8
[blender.git] / source / blender / draw / intern / draw_cache_impl_metaball.c
index 6dab46ccaa037655e2879521391da4dc26b15dd5..17ca9ec317e7670e91a2a2067b74a76a8d872a79 100644 (file)
@@ -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, bool UNUSED(reduce_len))
+{
+       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;
+}