From 88c88c4610260ef3d00420c3e9fc3c1cd56aad14 Mon Sep 17 00:00:00 2001 From: Germano Date: Thu, 16 Nov 2017 15:12:32 -0200 Subject: Fix T51210: Draw Manager: Support for Metaball Drawing Differential Revision: D2914 --- source/blender/blenkernel/BKE_mball.h | 11 ++ source/blender/blenkernel/intern/mball.c | 47 +++++ source/blender/blenkernel/intern/object_update.c | 4 + source/blender/blenloader/intern/readfile.c | 1 + source/blender/draw/CMakeLists.txt | 1 + source/blender/draw/intern/draw_cache.c | 15 ++ source/blender/draw/intern/draw_cache.h | 3 + source/blender/draw/intern/draw_cache_impl.h | 6 + .../blender/draw/intern/draw_cache_impl_displist.c | 26 +-- .../blender/draw/intern/draw_cache_impl_metaball.c | 196 +++++++++++++++++++++ source/blender/draw/intern/draw_common.c | 13 ++ source/blender/draw/intern/draw_common.h | 1 + source/blender/draw/intern/draw_manager.c | 7 +- source/blender/draw/modes/edit_metaball_mode.c | 156 ++++++++-------- source/blender/draw/modes/object_mode.c | 34 ++++ source/blender/editors/space_view3d/space_view3d.c | 1 + source/blender/gpu/CMakeLists.txt | 1 + source/blender/gpu/GPU_shader.h | 2 + source/blender/gpu/intern/gpu_shader.c | 6 +- .../gpu_shader_instance_mball_helpers_vert.glsl | 36 ++++ source/blender/makesdna/DNA_meta_types.h | 8 +- source/blender/makesrna/intern/rna_meta_api.c | 7 + 22 files changed, 481 insertions(+), 101 deletions(-) create mode 100644 source/blender/draw/intern/draw_cache_impl_metaball.c create mode 100644 source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 0c07ce55781..9db277f95fb 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -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 diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index f2c39d6cc72..d5cddf34eb5 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -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); + } +} diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 665fc357a32..9c235fb8d8c 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -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()) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0fc00945b4c..7c08b909920 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -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 ***************** */ diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index c3ae8050491..9c806f26fda 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -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 diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 13df65cf741..8010a232f89 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -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 * \{ */ diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index 54b840edfe6..35ac8f4a35d 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -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__ */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 82972b9f75b..e0da2227a77 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -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); diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c index e051d61d056..96386f82faf 100644 --- a/source/blender/draw/intern/draw_cache_impl_displist.c +++ b/source/blender/draw/intern/draw_cache_impl_displist.c @@ -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 index 00000000000..cf7d2f84133 --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_metaball.c @@ -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; +} diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 125edcbc5d2..bb7b4d7d513 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -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 *********************************************** */ diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h index 41f5abfcb65..51b7a25490f 100644 --- a/source/blender/draw/intern/draw_common.h +++ b/source/blender/draw/intern/draw_common.h @@ -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); diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 275edb9bf42..672149b9e43 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -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; diff --git a/source/blender/draw/modes/edit_metaball_mode.c b/source/blender/draw/modes/edit_metaball_mode.c index 202e520193b..fb61114686b 100644 --- a/source/blender/draw/modes/edit_metaball_mode.c +++ b/source/blender/draw/modes/edit_metaball_mode.c @@ -26,8 +26,13 @@ #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, diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c index a981a51a846..534ef9fb5bd 100644 --- a/source/blender/draw/modes/object_mode.c +++ b/source/blender/draw/modes/object_mode.c @@ -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; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 44e1d999c2a..e1e78fd8ff1 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -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" diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index ec623554567..18a1ef36bdc 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -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) diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index f3de3240c26..f2119a117e5 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -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; diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index cc1e1e8bb14..598722d372b 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -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 index 00000000000..819199c26c7 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_mball_helpers_vert.glsl @@ -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); +} diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h index 68d16700a73..f9ba45efef8 100644 --- a/source/blender/makesdna/DNA_meta_types.h +++ b/source/blender/makesdna/DNA_meta_types.h @@ -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 ********************* */ diff --git a/source/blender/makesrna/intern/rna_meta_api.c b/source/blender/makesrna/intern/rna_meta_api.c index 46547677dfd..53bb3ef2334 100644 --- a/source/blender/makesrna/intern/rna_meta_api.c +++ b/source/blender/makesrna/intern/rna_meta_api.c @@ -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 -- cgit v1.2.3