Fix T51210: Draw Manager: Support for Metaball Drawing
authorGermano <germano.costa@ig.com.br>
Thu, 16 Nov 2017 17:12:32 +0000 (15:12 -0200)
committerGermano <germano.costa@ig.com.br>
Thu, 16 Nov 2017 17:12:32 +0000 (15:12 -0200)
Differential Revision: D2914

22 files changed:
source/blender/blenkernel/BKE_mball.h
source/blender/blenkernel/intern/mball.c
source/blender/blenkernel/intern/object_update.c
source/blender/blenloader/intern/readfile.c
source/blender/draw/CMakeLists.txt
source/blender/draw/intern/draw_cache.c
source/blender/draw/intern/draw_cache.h
source/blender/draw/intern/draw_cache_impl.h
source/blender/draw/intern/draw_cache_impl_displist.c
source/blender/draw/intern/draw_cache_impl_metaball.c [new file with mode: 0644]
source/blender/draw/intern/draw_common.c
source/blender/draw/intern/draw_common.h
source/blender/draw/intern/draw_manager.c
source/blender/draw/modes/edit_metaball_mode.c
source/blender/draw/modes/object_mode.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/GPU_shader.h
source/blender/gpu/intern/gpu_shader.c
source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl [new file with mode: 0644]
source/blender/makesdna/DNA_meta_types.h
source/blender/makesrna/intern/rna_meta_api.c

index 0c07ce55781f613f460fe361d4499800ef0f59c1..9db277f95fb04101a263b865e976e083baf07801 100644 (file)
@@ -75,5 +75,16 @@ struct EvaluationContext;
 
 void BKE_mball_eval_geometry(const struct EvaluationContext *eval_ctx,
                              struct MetaBall *mball);
+/* Draw Cache */
+
+void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
+                                         const float obmat[4][4],
+                                         const float local_pos[3]);
+
+enum {
+       BKE_MBALL_BATCH_DIRTY_ALL = 0,
+};
+void BKE_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
+void BKE_mball_batch_cache_free(struct MetaBall *mb);
 
 #endif
index f2c39d6cc7247fd63b4ebe0b3371bda32d9c391d..d5cddf34eb5f7b4464db747ccfbc0195fbd12387 100644 (file)
@@ -75,6 +75,8 @@ void BKE_mball_free(MetaBall *mb)
 {
        BKE_animdata_free((ID *)mb, false);
 
+       BKE_mball_batch_cache_free(mb);
+
        MEM_SAFE_FREE(mb->mat);
 
        BLI_freelistN(&mb->elems);
@@ -120,6 +122,7 @@ void BKE_mball_copy_data(Main *UNUSED(bmain), MetaBall *mb_dst, const MetaBall *
 
        mb_dst->editelems = NULL;
        mb_dst->lastelem = NULL;
+       mb_dst->batch_cache = NULL;
 }
 
 MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb)
@@ -542,3 +545,47 @@ void BKE_mball_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx),
                              MetaBall *UNUSED(mball))
 {
 }
+
+/* Draw Engine */
+
+/* use for draw-manager only. */
+void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
+                                         const float obmat[4][4],
+                                         const float local_pos[3])
+{
+       float world_pos[3], scamat[3][3];
+       mul_v3_m4v3(world_pos, obmat, local_pos);
+       copy_m3_m4(scamat, obmat);
+       {
+               /* Get the normalized inverse matrix to extract only
+                * the scale of Scamat */
+               float iscamat[3][3];
+               invert_m3_m3(iscamat, scamat);
+               normalize_m3(iscamat);
+               mul_m3_m3_post(scamat, iscamat);
+       }
+
+       copy_v3_v3(r_scale_xform[0], scamat[0]);
+       copy_v3_v3(r_scale_xform[1], scamat[1]);
+       copy_v3_v3(r_scale_xform[2], scamat[2]);
+
+       r_scale_xform[0][3] = world_pos[0];
+       r_scale_xform[1][3] = world_pos[1];
+       r_scale_xform[2][3] = world_pos[2];
+}
+
+void (*BKE_mball_batch_cache_dirty_cb)(MetaBall *mb, int mode) = NULL;
+void (*BKE_mball_batch_cache_free_cb)(MetaBall *mb) = NULL;
+
+void BKE_mball_batch_cache_dirty(MetaBall *mb, int mode)
+{
+       if (mb->batch_cache) {
+               BKE_mball_batch_cache_dirty_cb(mb, mode);
+       }
+}
+void BKE_mball_batch_cache_free(MetaBall *mb)
+{
+       if (mb->batch_cache) {
+               BKE_mball_batch_cache_free_cb(mb);
+       }
+}
index 665fc357a32403eaf9fe7de144209a794432f5df..9c235fb8d8c6dfcfe1eb9780b2e4b9addf3ee002 100644 (file)
@@ -58,6 +58,7 @@
 #include "BKE_pointcache.h"
 #include "BKE_scene.h"
 #include "BKE_material.h"
+#include "BKE_mball.h"
 #include "BKE_mesh.h"
 #include "BKE_image.h"
 
@@ -322,6 +323,9 @@ void BKE_object_eval_uber_data(const EvaluationContext *eval_ctx,
                case OB_SURF:
                        BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_ALL);
                        break;
+               case OB_MBALL:
+                       BKE_mball_batch_cache_dirty(ob->data, BKE_MBALL_BATCH_DIRTY_ALL);
+                       break;
        }
 
        if (DEG_depsgraph_use_copy_on_write()) {
index 0fc00945b4c6139fce23388c6a83620a7eb0b57f..7c08b909920c544e8fa7dbb11da55583fd770bcb 100644 (file)
@@ -3692,6 +3692,7 @@ static void direct_link_mball(FileData *fd, MetaBall *mb)
        mb->editelems = NULL;
 /*     mb->edit_elems.first= mb->edit_elems.last= NULL;*/
        mb->lastelem = NULL;
+       mb->batch_cache = NULL;
 }
 
 /* ************ READ WORLD ***************** */
index c3ae8050491d99e82023927314575703c60ace70..9c806f26fda8270353ec0ef5c91fefa4d2146b12 100644 (file)
@@ -59,6 +59,7 @@ set(SRC
        intern/draw_cache_impl_displist.c
        intern/draw_cache_impl_lattice.c
        intern/draw_cache_impl_mesh.c
+       intern/draw_cache_impl_metaball.c
        intern/draw_cache_impl_particles.c
        intern/draw_common.c
        intern/draw_manager.c
index 13df65cf7414005f387b6595aae172918e0d405e..8010a232f899db0c56f62ae03c2a37676c2c4e50 100644 (file)
@@ -507,6 +507,8 @@ Gwn_Batch *DRW_cache_object_surface_get(Object *ob)
                        return DRW_cache_surf_surface_get(ob);
                case OB_FONT:
                        return DRW_cache_text_surface_get(ob);
+               case OB_MBALL:
+                       return DRW_cache_mball_surface_get(ob);
                default:
                        return NULL;
        }
@@ -2336,6 +2338,19 @@ Gwn_Batch *DRW_cache_curve_surface_get(Object *ob)
 
 /* -------------------------------------------------------------------- */
 
+/** \name MetaBall
+ * \{ */
+
+Gwn_Batch *DRW_cache_mball_surface_get(Object *ob)
+{
+       BLI_assert(ob->type == OB_MBALL);
+       return DRW_metaball_batch_cache_get_triangles_with_normals(ob);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
 /** \name Font
  * \{ */
 
index 54b840edfe602a3984929a84c342fccc0e9427bc..35ac8f4a35d38cbab2ef7a2657abf28b7673186d 100644 (file)
@@ -157,4 +157,7 @@ struct Gwn_Batch *DRW_cache_particles_get_hair(struct ParticleSystem *psys, stru
 struct Gwn_Batch *DRW_cache_particles_get_dots(struct ParticleSystem *psys);
 struct Gwn_Batch *DRW_cache_particles_get_prim(int type);
 
+/* Metaball */
+struct Gwn_Batch *DRW_cache_mball_surface_get(struct Object *ob);
+
 #endif /* __DRAW_CACHE_H__ */
index 82972b9f75b705fe6735825a704bd185bf360da3..e0da2227a7782e69d718e022e0955f8e2f64411f 100644 (file)
@@ -38,6 +38,9 @@ struct Lattice;
 struct Mesh;
 
 /* Expose via BKE callbacks */
+void DRW_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
+void DRW_mball_batch_cache_free(struct MetaBall *mb);
+
 void DRW_curve_batch_cache_dirty(struct Curve *cu, int mode);
 void DRW_curve_batch_cache_free(struct Curve *cu);
 
@@ -59,6 +62,9 @@ struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu);
 
 struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu, struct CurveCache *ob_curve_cache);
 
+/* Metaball */
+struct Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
+
 /* Curve (Font) */
 struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
 struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu);
index e051d61d0561257e0a006d049182fa446e7787f6..96386f82faf7e43a41b55894630a256c9f545148 100644 (file)
@@ -136,27 +136,31 @@ Gwn_Batch *BLI_displist_batch_calc_surface(ListBase *lb)
                GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
 
                int ofs = 0;
-               int tri_len_used = 0;
                for (const DispList *dl = lb->first; dl; dl = dl->next) {
                        if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
+                               const int *idx = dl->index;
                                if (dl->type == DL_INDEX3) {
-                                       const int *idx = dl->index;
                                        const int i_end = dl->parts;
-                                       for (int i = 0; i < i_end; i++) {
+                                       for (int i = 0; i < i_end; i++, idx += 3) {
                                                GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
-                                               tri_len_used += 1;
-                                               idx += 3;
                                        }
                                }
-                               else if (ELEM(dl->type, DL_INDEX4, DL_SURF)) {
-                                       const int *idx = dl->index;
+                               else if (dl->type == DL_SURF) {
                                        const int i_end = dl->totindex;
-                                       for (int i = 0; i < i_end; i++) {
+                                       for (int i = 0; i < i_end; i++, idx += 4) {
                                                GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
-                                               tri_len_used += 1;
                                                GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
-                                               tri_len_used += 1;
-                                               idx += 4;
+                                       }
+                               }
+                               else {
+                                       BLI_assert(dl->type == DL_INDEX4);
+                                       const int i_end = dl->parts;
+                                       for (int i = 0; i < i_end; i++, idx += 4) {
+                                               GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
+
+                                               if (idx[2] != idx[3]) {
+                                                       GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + 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
new file mode 100644 (file)
index 0000000..cf7d2f8
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2017 by Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file draw_cache_impl_metaball.c
+ *  \ingroup draw
+ *
+ * \brief MetaBall API for render engines
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_utildefines.h"
+
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_curve.h"
+#include "BKE_mball.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache_impl.h"  /* own include */
+
+
+static void metaball_batch_cache_clear(MetaBall *mb);
+
+/* ---------------------------------------------------------------------- */
+/* MetaBall Interface, indirect, partially cached access to complex data. */
+
+typedef struct MetaBallRenderData {
+       int types;
+
+       /* borrow from 'Object' */
+       CurveCache *ob_curve_cache;
+} MetaBallRenderData;
+
+enum {
+       /* Geometry */
+       MBALL_DATATYPE_SURFACE = 1 << 0,
+//     MBALL_DATATYPE_WIRE    = 1 << 1,
+//     MBALL_DATATYPE_SHADING = 1 << 2,
+};
+
+static MetaBallRenderData *metaball_render_data_create(MetaBall *mb, CurveCache *ob_curve_cache, const int types)
+{
+       MetaBallRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
+       rdata->types = types;
+       rdata->ob_curve_cache = ob_curve_cache;
+
+/*
+       **TODO**
+       if (types & MBALL_DATATYPE_WIRE) {}
+       if (types & MBALL_DATATYPE_SHADING) {}
+*/
+
+       return rdata;
+}
+
+static void metaball_render_data_free(MetaBallRenderData *rdata)
+{
+       MEM_freeN(rdata);
+}
+
+/* ---------------------------------------------------------------------- */
+/* MetaBall Gwn_Batch Cache */
+
+typedef struct MetaBallBatchCache {
+       Gwn_Batch *batch;
+
+       /* settings to determine if cache is invalid */
+       bool is_dirty;
+} MetaBallBatchCache;
+
+/* Gwn_Batch cache management. */
+
+static bool metaball_batch_cache_valid(MetaBall *mb)
+{
+       MetaBallBatchCache *cache = mb->batch_cache;
+
+       if (cache == NULL) {
+               return false;
+       }
+
+       return cache->is_dirty == false;
+}
+
+static void metaball_batch_cache_init(MetaBall *mb)
+{
+       MetaBallBatchCache *cache = mb->batch_cache;
+
+       if (!cache) {
+               cache = mb->batch_cache = MEM_mallocN(sizeof(*cache), __func__);
+       }
+       cache->batch = NULL;
+       cache->is_dirty = false;
+}
+
+static MetaBallBatchCache *metaball_batch_cache_get(MetaBall *mb)
+{
+       if (!metaball_batch_cache_valid(mb)) {
+               metaball_batch_cache_clear(mb);
+               metaball_batch_cache_init(mb);
+       }
+       return mb->batch_cache;
+}
+
+void DRW_mball_batch_cache_dirty(MetaBall *mb, int mode)
+{
+       MetaBallBatchCache *cache = mb->batch_cache;
+       if (cache == NULL) {
+               return;
+       }
+       switch (mode) {
+               case BKE_MBALL_BATCH_DIRTY_ALL:
+                       cache->is_dirty = true;
+                       break;
+               default:
+                       BLI_assert(0);
+       }
+}
+
+static void metaball_batch_cache_clear(MetaBall *mb)
+{
+       MetaBallBatchCache *cache = mb->batch_cache;
+       if (!cache) {
+               return;
+       }
+
+       GWN_BATCH_DISCARD_SAFE(cache->batch);
+}
+
+void DRW_mball_batch_cache_free(MetaBall *mb)
+{
+       metaball_batch_cache_clear(mb);
+       MEM_SAFE_FREE(mb->batch_cache);
+}
+
+/* -------------------------------------------------------------------- */
+
+/** \name Private MetaBall Cache API
+ * \{ */
+
+/* Gwn_Batch cache usage. */
+
+static Gwn_Batch *metaball_batch_cache_get_pos_and_normals(MetaBallRenderData *rdata, MetaBallBatchCache *cache)
+{
+       BLI_assert(rdata->types & MBALL_DATATYPE_SURFACE);
+       if (cache->batch == NULL) {
+               cache->batch = BLI_displist_batch_calc_surface(&rdata->ob_curve_cache->disp);
+       }
+       return cache->batch;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Public Object/MetaBall API
+ * \{ */
+
+Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
+{
+       if (!BKE_mball_is_basis(ob))
+               return NULL;
+
+       MetaBall *mb = ob->data;
+       MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
+
+       if (cache->batch == NULL) {
+               MetaBallRenderData *rdata = metaball_render_data_create(mb, ob->curve_cache, MBALL_DATATYPE_SURFACE);
+               metaball_batch_cache_get_pos_and_normals(rdata, cache);
+               metaball_render_data_free(rdata);
+       }
+
+       return cache->batch;
+}
index 125edcbc5d24b1bf807c316183d0acc395cf3325..bb7b4d7d513245228e93bd0de66bbbd2601c1b5f 100644 (file)
@@ -352,6 +352,19 @@ DRWShadingGroup *shgroup_instance_bone_envelope_solid(DRWPass *pass, struct Gwn_
        return grp;
 }
 
+DRWShadingGroup *shgroup_instance_mball_helpers(DRWPass *pass, struct Gwn_Batch *geom)
+{
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_INSTANCE_MBALL_HELPERS);
+
+       DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
+       DRW_shgroup_attrib_float(grp, "ScaleTranslationMatrix", 12);
+       DRW_shgroup_attrib_float(grp, "radius", 1);
+       DRW_shgroup_attrib_float(grp, "color", 3);
+       DRW_shgroup_uniform_vec3(grp, "screen_vecs[0]", DRW_viewport_screenvecs_get(), 2);
+
+       return grp;
+}
+
 
 /* ******************************************** COLOR UTILS *********************************************** */
 
index 41f5abfcb65a71eeca9e1613b19eadf2524a0741..51b7a25490f081e91f4495a62eba9a3b9bac62df 100644 (file)
@@ -104,6 +104,7 @@ struct DRWShadingGroup *shgroup_distance_lines_instance(struct DRWPass *pass, st
 struct DRWShadingGroup *shgroup_spot_instance(struct DRWPass *pass, struct Gwn_Batch *geom);
 struct DRWShadingGroup *shgroup_instance_bone_envelope_wire(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
 struct DRWShadingGroup *shgroup_instance_bone_envelope_solid(struct DRWPass *pass, struct Gwn_Batch *geom, float (*obmat)[4]);
+struct DRWShadingGroup *shgroup_instance_mball_helpers(struct DRWPass *pass, struct Gwn_Batch *geom);
 
 int DRW_object_wire_theme_get(struct Object *ob, struct SceneLayer *scene_layer, float **r_color);
 float *DRW_color_background_blend_get(int theme_id);
index 275edb9bf42bf086269dc5e1d53010f1bc247da7..672149b9e43fe86fbb2bb0f9bb78a8d98b975734 100644 (file)
@@ -3483,7 +3483,6 @@ void DRW_draw_select_loop(
        int obedit_mode = 0;
        if (scene->obedit && scene->obedit->type == OB_MBALL) {
                use_obedit = true;
-               DRW_engines_cache_populate(scene->obedit);
                obedit_mode = CTX_MODE_EDIT_METABALL;
        }
        else if ((scene->obedit && scene->obedit->type == OB_ARMATURE)) {
@@ -3790,6 +3789,9 @@ void DRW_engines_register(void)
 
        /* setup callbacks */
        {
+               /* BKE: mball.c */
+               extern void *BKE_mball_batch_cache_dirty_cb;
+               extern void *BKE_mball_batch_cache_free_cb;
                /* BKE: curve.c */
                extern void *BKE_curve_batch_cache_dirty_cb;
                extern void *BKE_curve_batch_cache_free_cb;
@@ -3803,6 +3805,9 @@ void DRW_engines_register(void)
                extern void *BKE_particle_batch_cache_dirty_cb;
                extern void *BKE_particle_batch_cache_free_cb;
 
+               BKE_mball_batch_cache_dirty_cb = DRW_mball_batch_cache_dirty;
+               BKE_mball_batch_cache_free_cb = DRW_mball_batch_cache_free;
+
                BKE_curve_batch_cache_dirty_cb = DRW_curve_batch_cache_dirty;
                BKE_curve_batch_cache_free_cb = DRW_curve_batch_cache_free;
 
index 202e520193bdd341b790980739bb6d4df704dc31..fb61114686b304ba70917944543c0ff5ea0ec46f 100644 (file)
 #include "DRW_engine.h"
 #include "DRW_render.h"
 
+#include "DNA_meta_types.h"
+
+#include "BKE_mball.h"
+
 /* If builtin shaders are needed */
 #include "GPU_shader.h"
+#include "GPU_select.h"
 
 #include "draw_common.h"
 
@@ -71,7 +76,7 @@ typedef struct EDIT_METABALL_StorageList {
         * Only directly MEM_(m/c)allocN'ed blocks because they are
         * free with MEM_freeN() when viewport is freed.
         * (not per object) */
-       struct CustomStruct *block;
+       // struct CustomStruct *block;
        struct EDIT_METABALL_PrivateData *g_data;
 } EDIT_METABALL_StorageList;
 
@@ -88,14 +93,6 @@ typedef struct EDIT_METABALL_Data {
 
 /* *********** STATIC *********** */
 
-static struct {
-       /* Custom shaders :
-        * Add sources to source/blender/draw/modes/shaders
-        * init in EDIT_METABALL_engine_init();
-        * free in EDIT_METABALL_engine_free(); */
-       struct GPUShader *custom_shader;
-} e_data = {NULL}; /* Engine data */
-
 typedef struct EDIT_METABALL_PrivateData {
        /* This keeps the references of the shading groups for
         * easy access in EDIT_METABALL_cache_populate() */
@@ -104,37 +101,6 @@ typedef struct EDIT_METABALL_PrivateData {
 
 /* *********** FUNCTIONS *********** */
 
-/* Init Textures, Framebuffers, Storage and Shaders.
- * It is called for every frames.
- * (Optional) */
-static void EDIT_METABALL_engine_init(void *vedata)
-{
-       EDIT_METABALL_TextureList *txl = ((EDIT_METABALL_Data *)vedata)->txl;
-       EDIT_METABALL_FramebufferList *fbl = ((EDIT_METABALL_Data *)vedata)->fbl;
-       EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
-
-       UNUSED_VARS(txl, fbl, stl);
-
-       /* Init Framebuffers like this: order is attachment order (for color texs) */
-       /*
-        * DRWFboTexture tex[2] = {{&txl->depth, DRW_TEX_DEPTH_24, 0},
-        *                         {&txl->color, DRW_TEX_RGBA_8, DRW_TEX_FILTER}};
-        */
-
-       /* DRW_framebuffer_init takes care of checking if
-        * the framebuffer is valid and has the right size*/
-       /*
-        * float *viewport_size = DRW_viewport_size_get();
-        * DRW_framebuffer_init(&fbl->occlude_wire_fb,
-        *                     (int)viewport_size[0], (int)viewport_size[1],
-        *                     tex, 2);
-        */
-
-       if (!e_data.custom_shader) {
-               e_data.custom_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
-       }
-}
-
 /* Here init all passes and shading groups
  * Assume that all Passes are NULL */
 static void EDIT_METABALL_cache_init(void *vedata)
@@ -153,70 +119,86 @@ static void EDIT_METABALL_cache_init(void *vedata)
                psl->pass = DRW_pass_create("My Pass", state);
 
                /* Create a shadingGroup using a function in draw_common.c or custom one */
-               /*
-                * stl->g_data->group = shgroup_dynlines_uniform_color(psl->pass, ts.colorWire);
-                * -- or --
-                * stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
-                */
-               stl->g_data->group = DRW_shgroup_create(e_data.custom_shader, psl->pass);
-
-               /* Uniforms need a pointer to it's value so be sure it's accessible at
-                * any given time (i.e. use static vars) */
-               static float color[4] = {0.0f, 1.0f, 0.0f, 1.0};
-               DRW_shgroup_uniform_vec4(stl->g_data->group, "color", color, 1);
+               stl->g_data->group = shgroup_instance_mball_helpers(psl->pass, DRW_cache_screenspace_circle_get());
        }
-
 }
 
-/* Add geometry to shadingGroups. Execute for each objects */
-static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
+static void EDIT_METABALL_cache_populate_radius_visualization(
+        DRWShadingGroup *group, MetaElem *ml, const float scale_xform[3][4],
+        const float *radius, const int selection_id)
 {
-       EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
-       EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
+       const float *color;
+       static const float col_radius[3] =        {0.63, 0.19, 0.19}; /* 0x3030A0 */
+       static const float col_radius_select[3] = {0.94, 0.63, 0.63}; /* 0xA0A0F0 */
 
-       UNUSED_VARS(psl, stl);
+       if ((ml->flag & SELECT) && (ml->flag & MB_SCALE_RAD)) color = col_radius_select;
+       else color = col_radius;
 
-       if (ob->type == OB_MESH) {
-               /* Get geometry cache */
-               struct Gwn_Batch *geom = DRW_cache_mesh_surface_get(ob);
+       if (selection_id != -1) {
+               ml->selcol1 = selection_id;
+               DRW_select_load_id(selection_id);
+       }
+
+       DRW_shgroup_call_dynamic_add(group, scale_xform, radius, color);
+}
+
+static void EDIT_METABALL_cache_populate_stiffness_visualization(
+        DRWShadingGroup *group, MetaElem *ml, const float scale_xform[3][4],
+        const float *radius, const int selection_id)
+{
+       const float *color;
+       static const float col_stiffness[3] =        {0.19, 0.63, 0.19}; /* 0x30A030 */
+       static const float col_stiffness_select[3] = {0.63, 0.94, 0.63}; /* 0xA0F0A0 */
 
-               /* Add geom to a shading group */
-               DRW_shgroup_call_add(stl->g_data->group, geom, ob->obmat);
+       if ((ml->flag & SELECT) && !(ml->flag & MB_SCALE_RAD)) color = col_stiffness_select;
+       else color = col_stiffness;
+
+       if (selection_id != -1) {
+               ml->selcol2 = selection_id;
+               DRW_select_load_id(selection_id);
        }
+
+       DRW_shgroup_call_dynamic_add(group, scale_xform, radius, color);
 }
 
-/* Optional: Post-cache_populate callback */
-static void EDIT_METABALL_cache_finish(void *vedata)
+/* Add geometry to shadingGroups. Execute for each objects */
+static void EDIT_METABALL_cache_populate(void *vedata, Object *ob)
 {
-       EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
+       //EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
        EDIT_METABALL_StorageList *stl = ((EDIT_METABALL_Data *)vedata)->stl;
 
-       /* Do something here! dependant on the objects gathered */
-       UNUSED_VARS(psl, stl);
+       if (ob->type == OB_MBALL) {
+               const DRWContextState *draw_ctx = DRW_context_state_get();
+               Scene *scene = draw_ctx->scene;
+               Object *obedit = scene->obedit;
+               DRWShadingGroup *group = stl->g_data->group;
+
+               if (ob == obedit) {
+                       MetaBall *mb = ob->data;
+
+                       const bool is_select = DRW_state_is_select();
+
+                       int selection_id = 0;
+
+                       for (MetaElem *ml = mb->editelems->first; ml != NULL; ml = ml->next) {
+                               BKE_mball_element_calc_display_m3x4(ml->draw_scale_xform, ob->obmat, &ml->x);
+                               ml->draw_stiffness_radius = ml->rad * atanf(ml->s) / (float)M_PI_2;
+
+                               EDIT_METABALL_cache_populate_radius_visualization(
+                                       group, ml, ml->draw_scale_xform, &ml->rad, is_select ? ++selection_id : -1);
+
+                               EDIT_METABALL_cache_populate_stiffness_visualization(
+                                       group, ml, ml->draw_scale_xform, &ml->draw_stiffness_radius, is_select ? ++selection_id : -1);
+                       }
+               }
+       }
 }
 
 /* Draw time ! Control rendering pipeline from here */
 static void EDIT_METABALL_draw_scene(void *vedata)
 {
        EDIT_METABALL_PassList *psl = ((EDIT_METABALL_Data *)vedata)->psl;
-       EDIT_METABALL_FramebufferList *fbl = ((EDIT_METABALL_Data *)vedata)->fbl;
-
-       /* Default framebuffer and texture */
-       DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
-       DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
-
-       UNUSED_VARS(fbl, dfbl, dtxl);
-
-       /* Show / hide entire passes, swap framebuffers ... whatever you fancy */
-       /*
-        * DRW_framebuffer_texture_detach(dtxl->depth);
-        * DRW_framebuffer_bind(fbl->custom_fb);
-        * DRW_draw_pass(psl->pass);
-        * DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
-        * DRW_framebuffer_bind(dfbl->default_fb);
-        */
-
-       /* ... or just render passes on default framebuffer. */
+       /* render passes on default framebuffer. */
        DRW_draw_pass(psl->pass);
 
        /* If you changed framebuffer, double check you rebind
@@ -258,11 +240,11 @@ DrawEngineType draw_engine_edit_metaball_type = {
        NULL, NULL,
        N_("EditMetaballMode"),
        &EDIT_METABALL_data_size,
-       &EDIT_METABALL_engine_init,
+       NULL,
        &EDIT_METABALL_engine_free,
        &EDIT_METABALL_cache_init,
        &EDIT_METABALL_cache_populate,
-       &EDIT_METABALL_cache_finish,
+       NULL,
        NULL, /* draw_background but not needed by mode engines */
        &EDIT_METABALL_draw_scene,
        NULL,
index a981a51a846686ed3b1c158643b29a8bcef2a6c0..534ef9fb5bdb5213996191ba1f6de78b1a43a56b 100644 (file)
@@ -31,6 +31,7 @@
 #include "DNA_camera_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
 #include "DNA_object_force.h"
 #include "DNA_lightprobe_types.h"
 #include "DNA_particle_types.h"
@@ -43,6 +44,7 @@
 #include "BKE_camera.h"
 #include "BKE_curve.h"
 #include "BKE_global.h"
+#include "BKE_mball.h"
 #include "BKE_object.h"
 #include "BKE_particle.h"
 #include "BKE_image.h"
@@ -149,6 +151,9 @@ typedef struct OBJECT_PrivateData {
        DRWShadingGroup *probe_planar;
        DRWShadingGroup *probe_grid;
 
+       /* MetaBalls */
+       DRWShadingGroup *mball_circle;
+
        /* Lamps */
        DRWShadingGroup *lamp_center;
        DRWShadingGroup *lamp_center_group;
@@ -949,6 +954,13 @@ static void OBJECT_cache_init(void *vedata)
                stl->g_data->wire_active_group = shgroup_wire(psl->non_meshes, ts.colorGroupActive, sh);
        }
 
+       {
+               /* Metaballs Helpers */
+               struct Gwn_Batch *geom;
+               geom = DRW_cache_screenspace_circle_get();
+               stl->g_data->mball_circle = shgroup_instance_mball_helpers(psl->non_meshes, geom);
+       }
+
        {
                /* Lamps */
                /* TODO
@@ -1077,6 +1089,20 @@ static void OBJECT_cache_init(void *vedata)
        }
 }
 
+static void DRW_shgroup_mball_helpers(OBJECT_StorageList *stl, Object *ob, SceneLayer *scene_layer)
+{
+       MetaBall *mb = ob->data;
+
+       float *color;
+       DRW_object_wire_theme_get(ob, scene_layer, &color);
+
+       for (MetaElem *ml = mb->elems.first; ml != NULL; ml = ml->next) {
+               /* draw radius */
+               BKE_mball_element_calc_display_m3x4(ml->draw_scale_xform, ob->obmat, &ml->x);
+               DRW_shgroup_call_dynamic_add(stl->g_data->mball_circle, ml->draw_scale_xform, &ml->rad, color);
+       }
+}
+
 static void DRW_shgroup_lamp(OBJECT_StorageList *stl, Object *ob, SceneLayer *scene_layer)
 {
        Lamp *la = ob->data;
@@ -1812,6 +1838,14 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
                        }
                        break;
                }
+               case OB_MBALL:
+               {
+                       Object *obedit = scene->obedit;
+                       if (ob != obedit) {
+                               DRW_shgroup_mball_helpers(stl, ob, scene_layer);
+                       }
+                       break;
+               }
                case OB_LAMP:
                        DRW_shgroup_lamp(stl, ob, scene_layer);
                        break;
index 44e1d999c2a2ad9eae2f09c67e52a5291e70cdde..e1e78fd8ff17a974c952ac9aeeaaf636fc24c793 100644 (file)
@@ -48,6 +48,7 @@
 #include "BKE_lattice.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_mball.h"
 #include "BKE_mesh.h"
 #include "BKE_object.h"
 #include "BKE_scene.h"
index ec6235545676bd2354fd93f94f4fd4e8a5801783..18a1ef36bdc07070bdd4529b409e6c356952f197 100644 (file)
@@ -173,6 +173,7 @@ data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_solid_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_instance_bone_envelope_wire_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_instance_mball_helpers_vert.glsl SRC)
 
 data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
index f3de3240c26425ed2d1529acef927257b7ed0df1..f2119a117e5485dc18ed76f45083c0abf3866685 100644 (file)
@@ -173,6 +173,8 @@ typedef enum GPUBuiltinShader {
        GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_SOLID,
        GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE,
 
+       GPU_SHADER_3D_INSTANCE_MBALL_HELPERS,
+
        GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
 } GPUBuiltinShader;
 
index cc1e1e8bb143a2db0bf2fc5bc1342c864b6c43a2..598722d372b59a3fc0eee6692474f7ffe6962ec5 100644 (file)
@@ -98,6 +98,7 @@ extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[];
 extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[];
 extern char datatoc_gpu_shader_instance_bone_envelope_solid_vert_glsl[];
 extern char datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl[];
+extern char datatoc_gpu_shader_instance_mball_helpers_vert_glsl[];
 
 extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
 extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
@@ -805,7 +806,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
                          datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl },
 
                [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { datatoc_gpu_shader_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
-               [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = 
+               [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] =
                    { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl,
                      datatoc_gpu_shader_flat_color_frag_glsl },
                [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] =
@@ -819,6 +820,9 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
                                                                 datatoc_gpu_shader_simple_lighting_frag_glsl },
                [GPU_SHADER_3D_INSTANCE_BONE_ENVELOPE_WIRE] = { datatoc_gpu_shader_instance_bone_envelope_wire_vert_glsl,
                                                                datatoc_gpu_shader_flat_color_frag_glsl },
+
+               [GPU_SHADER_3D_INSTANCE_MBALL_HELPERS] = { datatoc_gpu_shader_instance_mball_helpers_vert_glsl,
+                                                          datatoc_gpu_shader_flat_color_frag_glsl },
        };
 
        if (builtin_shaders[shader] == NULL) {
diff --git a/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl
new file mode 100644 (file)
index 0000000..819199c
--- /dev/null
@@ -0,0 +1,36 @@
+
+/* This shader takes a 2D shape, puts it in 3D Object space such that is stays aligned with view,
+ * and scales the shape according to per-instance attributes
+ * Note that if the stiffness is zero, it assumes the scale is directly multiplied by the radius */
+
+
+ #define M_PI_2     1.570796f   // pi/2
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+
+/* ---- Instanciated Attribs ---- */
+in vec2 pos;
+
+/* ---- Per instance Attribs ---- */
+in mat3x4 ScaleTranslationMatrix;
+in float radius;
+in vec3 color;
+
+flat out vec4 finalColor;
+
+void main()
+{
+       mat3 Scamat = mat3(ScaleTranslationMatrix);
+       vec4 world_pos = vec4(
+               ScaleTranslationMatrix[0][3],
+               ScaleTranslationMatrix[1][3],
+               ScaleTranslationMatrix[2][3],
+               1.0);
+
+       vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+       world_pos.xyz += Scamat * (screen_pos * radius);
+
+       gl_Position = ViewProjectionMatrix * world_pos;
+       finalColor = vec4(color, 1.0);
+}
index 68d16700a73b2231cbb6f5a25a23c8c983f0bdac..f9ba45efef8ca6a48db330f95c12efea9712ee13 100644 (file)
@@ -59,7 +59,11 @@ typedef struct MetaElem {
        float len;              /* old, only used for backwards compat. use dimensions now */
        
        float *mat, *imat;      /* matrix and inverted matrix */
-       
+
+       /* Draw_Data: stores pointers used for shader attributes */
+       float draw_scale_xform[3][4]; /* Matrix of Scale and Translation */
+       float draw_stiffness_radius; /* stiffness circle radius (only in edit mode) */
+       float pad;
 } MetaElem;
 
 typedef struct MetaBall {
@@ -93,6 +97,8 @@ typedef struct MetaBall {
        /* used in editmode */
        /*ListBase edit_elems;*/
        MetaElem *lastelem;
+
+       void *batch_cache;
 } MetaBall;
 
 /* **************** METABALL ********************* */
index 46547677dfd9fdcfa92484120857d8a9d21e5948..53bb3ef23349072d3144a9dac99a1c3d0dbb9581 100644 (file)
@@ -49,6 +49,11 @@ static void rna_Meta_transform(struct MetaBall *mb, float *mat)
 
        DEG_id_tag_update(&mb->id, 0);
 }
+
+static void rna_Mball_update_gpu_tag(MetaBall *mb)
+{
+       BKE_mball_batch_cache_dirty(mb, BKE_MBALL_BATCH_DIRTY_ALL);
+}
 #else
 
 void RNA_api_meta(StructRNA *srna)
@@ -60,6 +65,8 @@ void RNA_api_meta(StructRNA *srna)
        RNA_def_function_ui_description(func, "Transform meta elements by a matrix");
        parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
        RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+
+       RNA_def_function(srna, "update_gpu_tag", "rna_Mball_update_gpu_tag");
 }
 
 #endif