diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_editstrands.h | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/editstrands.c | 34 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_sample.c | 4 | ||||
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 2 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 25 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.h | 7 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 10 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_strands.c | 322 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 10 | ||||
-rw-r--r-- | source/blender/draw/modes/draw_mode_engines.h | 3 | ||||
-rw-r--r-- | source/blender/draw/modes/edit_strands_mode.c | 243 | ||||
-rw-r--r-- | source/blender/editors/hair/hair_cursor.c | 2 | ||||
-rw-r--r-- | source/blender/editors/hair/hair_edit.c | 2 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 12 |
15 files changed, 673 insertions, 19 deletions
diff --git a/source/blender/blenkernel/BKE_editstrands.h b/source/blender/blenkernel/BKE_editstrands.h index cc641918dbc..90f86701e5d 100644 --- a/source/blender/blenkernel/BKE_editstrands.h +++ b/source/blender/blenkernel/BKE_editstrands.h @@ -57,6 +57,7 @@ typedef struct BMEditStrands { unsigned int vertex_glbuf; unsigned int elem_glbuf; unsigned int dot_glbuf; + void *batch_cache; } BMEditStrands; /* BMEditStrands->flag */ @@ -70,7 +71,7 @@ struct BMEditStrands *BKE_editstrands_from_object(struct Object *ob); void BKE_editstrands_update_linked_customdata(struct BMEditStrands *es); void BKE_editstrands_free(struct BMEditStrands *es); -/* === constraints === */ +/* === Constraints === */ /* Stores vertex locations for temporary reference: * Vertex locations get modified by tools, but then need to be corrected @@ -83,13 +84,20 @@ void BKE_editstrands_free_locations(BMEditStrandsLocations locs); void BKE_editstrands_solve_constraints(struct Object *ob, struct BMEditStrands *es, BMEditStrandsLocations orig); void BKE_editstrands_ensure(struct BMEditStrands *es); -/* === particle conversion === */ +/* === Particle Conversion === */ struct BMesh *BKE_editstrands_particles_to_bmesh(struct Object *ob, struct ParticleSystem *psys); void BKE_editstrands_particles_from_bmesh(struct Object *ob, struct ParticleSystem *psys); -/* === mesh conversion === */ +/* === Mesh Conversion === */ struct BMesh *BKE_editstrands_mesh_to_bmesh(struct Object *ob, struct Mesh *me); void BKE_editstrands_mesh_from_bmesh(struct Object *ob); +/* === Draw Cache === */ +enum { + BKE_STRANDS_BATCH_DIRTY_ALL = 0, +}; +void BKE_editstrands_batch_cache_dirty(struct BMEditStrands *es, int mode); +void BKE_editstrands_batch_cache_free(struct BMEditStrands *es); + #endif diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c index 799c55b8b35..d1494d2a997 100644 --- a/source/blender/blenkernel/intern/editstrands.c +++ b/source/blender/blenkernel/intern/editstrands.c @@ -64,6 +64,8 @@ BMEditStrands *BKE_editstrands_create(BMesh *bm, DerivedMesh *root_dm) es->base.bm = bm; es->root_dm = CDDM_copy(root_dm); + BKE_editstrands_batch_cache_dirty(es, BKE_STRANDS_BATCH_DIRTY_ALL); + return es; } @@ -75,6 +77,8 @@ BMEditStrands *BKE_editstrands_copy(BMEditStrands *es) es_copy->base.bm = BM_mesh_copy(es->base.bm); es_copy->root_dm = CDDM_copy(es->root_dm); + BKE_editstrands_batch_cache_dirty(es_copy, BKE_STRANDS_BATCH_DIRTY_ALL); + return es_copy; } @@ -83,7 +87,7 @@ BMEditStrands *BKE_editstrands_copy(BMEditStrands *es) */ BMEditStrands *BKE_editstrands_from_object(Object *ob) { - if (ob->type == OB_MESH) { + if (ob && ob->type == OB_MESH) { Mesh *me = ob->data; if (me->edit_strands) return me->edit_strands; @@ -105,13 +109,15 @@ void BKE_editstrands_update_linked_customdata(BMEditStrands *UNUSED(es)) /*does not free the BMEditStrands struct itself*/ void BKE_editstrands_free(BMEditStrands *es) { + BKE_editstrands_batch_cache_free(es); + if (es->base.bm) BM_mesh_free(es->base.bm); if (es->root_dm) es->root_dm->release(es->root_dm); } -/* === constraints === */ +/* === Constraints === */ BMEditStrandsLocations BKE_editstrands_get_locations(BMEditStrands *edit) { @@ -139,6 +145,8 @@ void BKE_editstrands_solve_constraints(Object *ob, BMEditStrands *es, BMEditStra BKE_editstrands_ensure(es); BPH_strands_solve_constraints(ob, es, orig); + + BKE_editstrands_batch_cache_dirty(es, BKE_STRANDS_BATCH_DIRTY_ALL); } static void editstrands_calc_segment_lengths(BMesh *bm) @@ -170,7 +178,7 @@ void BKE_editstrands_ensure(BMEditStrands *es) } -/* === particle conversion === */ +/* === Particle Conversion === */ BMesh *BKE_editstrands_particles_to_bmesh(Object *ob, ParticleSystem *psys) { @@ -214,7 +222,7 @@ void BKE_editstrands_particles_from_bmesh(Object *ob, ParticleSystem *psys) } -/* === mesh conversion === */ +/* === Mesh Conversion === */ BMesh *BKE_editstrands_mesh_to_bmesh(Object *ob, Mesh *me) { @@ -258,3 +266,21 @@ void BKE_editstrands_mesh_from_bmesh(Object *ob) * avoid ending up with an invalid derived mesh then */ BKE_object_free_derived_caches(ob); } + +/* === Draw Cache === */ +void (*BKE_editstrands_batch_cache_dirty_cb)(BMEditStrands *es, int mode) = NULL; +void (*BKE_editstrands_batch_cache_free_cb)(BMEditStrands *es) = NULL; + +void BKE_editstrands_batch_cache_dirty(BMEditStrands *es, int mode) +{ + if (es->batch_cache) { + BKE_editstrands_batch_cache_dirty_cb(es, mode); + } +} + +void BKE_editstrands_batch_cache_free(BMEditStrands *es) +{ + if (es->batch_cache) { + BKE_editstrands_batch_cache_free_cb(es); + } +} diff --git a/source/blender/blenkernel/intern/mesh_sample.c b/source/blender/blenkernel/intern/mesh_sample.c index 82efd568c21..554df6625e2 100644 --- a/source/blender/blenkernel/intern/mesh_sample.c +++ b/source/blender/blenkernel/intern/mesh_sample.c @@ -700,7 +700,7 @@ bool BKE_mesh_sample_from_particle(MeshSample *sample, ParticleSystem *psys, Der } /* test both triangles of the face */ - interp_weights_quad_v3(w, co1, co2, co3, NULL, vec); + interp_weights_tri_v3(w, co1, co2, co3, vec); if (w[0] <= 1.0f && w[1] <= 1.0f && w[2] <= 1.0f) { sample->orig_verts[0] = mface->v1; sample->orig_verts[1] = mface->v2; @@ -710,7 +710,7 @@ bool BKE_mesh_sample_from_particle(MeshSample *sample, ParticleSystem *psys, Der return true; } else if (mface->v4) { - interp_weights_quad_v3(w, co3, co4, co1, NULL, vec); + interp_weights_tri_v3(w, co3, co4, co1, vec); sample->orig_verts[0] = mface->v3; sample->orig_verts[1] = mface->v4; sample->orig_verts[2] = mface->v1; diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 4b760f68705..920b6140e2b 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -60,6 +60,7 @@ set(SRC intern/draw_cache_impl_lattice.c intern/draw_cache_impl_mesh.c intern/draw_cache_impl_particles.c + intern/draw_cache_impl_strands.c intern/draw_common.c intern/draw_manager.c intern/draw_manager_text.c @@ -69,6 +70,7 @@ set(SRC modes/edit_lattice_mode.c modes/edit_mesh_mode.c modes/edit_metaball_mode.c + modes/edit_strands_mode.c modes/edit_surface_mode.c modes/edit_text_mode.c modes/object_mode.c diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 46ed858603d..2f01a5fd966 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -1046,7 +1046,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl } if (ob->type == OB_MESH) { - if (ob != draw_ctx->scene->obedit) { + if (ob != draw_ctx->scene->obedit && !(ob->mode & OB_MODE_HAIR_EDIT)) { material_hash = stl->g_data->hair_material_hash; for (ModifierData *md = ob->modifiers.first; md; md = md->next) { diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index c0338de3d54..c6a5a85b4e8 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -2584,3 +2584,28 @@ Gwn_Batch *DRW_cache_particles_get_prim(int type) return NULL; } + +/* -------------------------------------------------------------------- */ + +/** \name Strands + * \{ */ + +Gwn_Batch *DRW_cache_editstrands_get_tips(struct BMEditStrands *es) +{ + return DRW_editstrands_batch_cache_get_tips(es); +} + +Gwn_Batch *DRW_cache_editstrands_get_roots(struct BMEditStrands *es) +{ + return DRW_editstrands_batch_cache_get_roots(es); +} + +Gwn_Batch *DRW_cache_editstrands_get_points(struct BMEditStrands *es) +{ + return DRW_editstrands_batch_cache_get_points(es); +} + +Gwn_Batch *DRW_cache_editstrands_get_wires(struct BMEditStrands *es) +{ + return DRW_editstrands_batch_cache_get_wires(es); +} diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h index ac7062b3cc8..03ef1eae2eb 100644 --- a/source/blender/draw/intern/draw_cache.h +++ b/source/blender/draw/intern/draw_cache.h @@ -30,6 +30,7 @@ struct Gwn_Batch; struct GPUMaterial; struct Object; struct ModifierData; +struct BMEditStrands; void DRW_shape_cache_free(void); @@ -156,4 +157,10 @@ 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); +/* Strands */ +struct Gwn_Batch *DRW_cache_editstrands_get_tips(struct BMEditStrands *es); +struct Gwn_Batch *DRW_cache_editstrands_get_roots(struct BMEditStrands *es); +struct Gwn_Batch *DRW_cache_editstrands_get_points(struct BMEditStrands *es); +struct Gwn_Batch *DRW_cache_editstrands_get_wires(struct BMEditStrands *es); + #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 f8feeb37b82..148839f9748 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -32,6 +32,7 @@ struct ListBase; struct CurveCache; struct ParticleSystem; struct ModifierData; +struct BMEditStrands; struct Curve; struct Lattice; @@ -50,6 +51,9 @@ void DRW_lattice_batch_cache_free(struct Lattice *lt); void DRW_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode); void DRW_particle_batch_cache_free(struct ParticleSystem *psys); +void DRW_editstrands_batch_cache_dirty(struct BMEditStrands *es, int mode); +void DRW_editstrands_batch_cache_free(struct BMEditStrands *es); + /* Curve */ struct Gwn_Batch *DRW_curve_batch_cache_get_wire_edge(struct Curve *cu, struct CurveCache *ob_curve_cache); struct Gwn_Batch *DRW_curve_batch_cache_get_normal_edge( @@ -102,4 +106,10 @@ void DRW_mesh_cache_sculpt_coords_ensure(struct Mesh *me); struct Gwn_Batch *DRW_particles_batch_cache_get_hair(struct ParticleSystem *psys, struct ModifierData *md); struct Gwn_Batch *DRW_particles_batch_cache_get_dots(struct ParticleSystem *psys); +/* Strands */ +struct Gwn_Batch *DRW_editstrands_batch_cache_get_wires(struct BMEditStrands *es); +struct Gwn_Batch *DRW_editstrands_batch_cache_get_tips(struct BMEditStrands *es); +struct Gwn_Batch *DRW_editstrands_batch_cache_get_roots(struct BMEditStrands *es); +struct Gwn_Batch *DRW_editstrands_batch_cache_get_points(struct BMEditStrands *es); + #endif /* __DRAW_CACHE_IMPL_H__ */ diff --git a/source/blender/draw/intern/draw_cache_impl_strands.c b/source/blender/draw/intern/draw_cache_impl_strands.c new file mode 100644 index 00000000000..685f72410da --- /dev/null +++ b/source/blender/draw/intern/draw_cache_impl_strands.c @@ -0,0 +1,322 @@ +/* + * ***** 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. + * + * Contributor(s): Blender Foundation, Mike Erwin, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file draw_cache_impl_strands.c + * \ingroup draw + * + * \brief Strands API for render engines + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math_vector.h" +#include "BLI_ghash.h" + +#include "BKE_editstrands.h" + +#include "GPU_batch.h" + +#include "draw_cache_impl.h" /* own include */ + +/* ---------------------------------------------------------------------- */ +/* Strands Gwn_Batch Cache */ + +typedef enum VertexDrawFlags +{ + STRANDS_VERTEX_SELECT = 1, +} VertexDrawFlags; + +typedef struct StrandsBatchCache { + Gwn_VertBuf *pos; + Gwn_IndexBuf *segments; + Gwn_IndexBuf *tips_idx; + Gwn_IndexBuf *roots_idx; + + Gwn_Batch *wires; + Gwn_Batch *tips; + Gwn_Batch *roots; + Gwn_Batch *points; + + int segment_count; + int point_count; + + /* settings to determine if cache is invalid */ + bool is_dirty; +} StrandsBatchCache; + +/* Gwn_Batch cache management. */ + +static void editstrands_batch_cache_clear(BMEditStrands *es); + +static bool editstrands_batch_cache_valid(BMEditStrands *es) +{ + StrandsBatchCache *cache = es->batch_cache; + + if (cache == NULL) { + return false; + } + + if (cache->is_dirty == false) { + return true; + } + else { + return false; + } + + return true; +} + +static void editstrands_batch_cache_init(BMEditStrands *es) +{ + StrandsBatchCache *cache = es->batch_cache; + + if (!cache) { + cache = es->batch_cache = MEM_callocN(sizeof(*cache), __func__); + } + else { + memset(cache, 0, sizeof(*cache)); + } + + cache->is_dirty = false; +} + +static StrandsBatchCache *editstrands_batch_cache_get(BMEditStrands *es) +{ + if (!editstrands_batch_cache_valid(es)) { + editstrands_batch_cache_clear(es); + editstrands_batch_cache_init(es); + } + return es->batch_cache; +} + +void DRW_editstrands_batch_cache_dirty(BMEditStrands *es, int mode) +{ + StrandsBatchCache *cache = es->batch_cache; + if (cache == NULL) { + return; + } + switch (mode) { + case BKE_STRANDS_BATCH_DIRTY_ALL: + cache->is_dirty = true; + break; + default: + BLI_assert(0); + } +} + +static void editstrands_batch_cache_clear(BMEditStrands *es) +{ + StrandsBatchCache *cache = es->batch_cache; + if (!cache) { + return; + } + + GWN_BATCH_DISCARD_SAFE(cache->wires); + GWN_BATCH_DISCARD_SAFE(cache->points); + GWN_BATCH_DISCARD_SAFE(cache->tips); + GWN_BATCH_DISCARD_SAFE(cache->roots); + + GWN_VERTBUF_DISCARD_SAFE(cache->pos); + GWN_INDEXBUF_DISCARD_SAFE(cache->segments); +} + +void DRW_editstrands_batch_cache_free(BMEditStrands *es) +{ + editstrands_batch_cache_clear(es); + MEM_SAFE_FREE(es->batch_cache); +} + +static void editstrands_batch_cache_ensure_pos(BMEditStrands *es, StrandsBatchCache *cache) +{ + if (cache->pos) { + return; + } + + static Gwn_VertFormat format = { 0 }; + static unsigned pos_id, flag_id; + + GWN_VERTBUF_DISCARD_SAFE(cache->pos); + + /* initialize vertex format */ + if (format.attrib_ct == 0) { + pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + flag_id = GWN_vertformat_attr_add(&format, "flags", GWN_COMP_U8, 1, GWN_FETCH_INT); + } + + BMesh *bm = es->base.bm; + BMVert *vert; + BMIter iter; + int curr_point; + + cache->pos = GWN_vertbuf_create_with_format(&format); + GWN_vertbuf_data_alloc(cache->pos, bm->totvert); + + BM_ITER_MESH_INDEX(vert, &iter, bm, BM_VERTS_OF_MESH, curr_point) { + GWN_vertbuf_attr_set(cache->pos, pos_id, curr_point, vert->co); + + uint8_t flag = 0; + if (BM_elem_flag_test(vert, BM_ELEM_SELECT)) + flag |= STRANDS_VERTEX_SELECT; + GWN_vertbuf_attr_set(cache->pos, flag_id, curr_point, &flag); + } +} + +static void editstrands_batch_cache_ensure_segments(BMEditStrands *es, StrandsBatchCache *cache) +{ + if (cache->segments) { + return; + } + + GWN_INDEXBUF_DISCARD_SAFE(cache->segments); + + BMesh *bm = es->base.bm; + BMEdge *edge; + BMIter iter; + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_LINES, bm->totedge, bm->totvert); + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + BM_ITER_MESH(edge, &iter, bm, BM_EDGES_OF_MESH) { + GWN_indexbuf_add_line_verts(&elb, BM_elem_index_get(edge->v1), BM_elem_index_get(edge->v2)); + } + + cache->segments = GWN_indexbuf_build(&elb); +} + +static void editstrands_batch_cache_ensure_tips_idx(BMEditStrands *es, StrandsBatchCache *cache) +{ + if (cache->tips_idx) { + return; + } + + GWN_INDEXBUF_DISCARD_SAFE(cache->tips_idx); + + BMesh *bm = es->base.bm; + int totstrands = BM_strands_count(bm); + BMVert *root, *vert; + BMIter iter, iter_strand; + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_POINTS, totstrands, bm->totvert); + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + BM_ITER_STRANDS(root, &iter, bm, BM_STRANDS_OF_MESH) { + BM_ITER_STRANDS_ELEM(vert, &iter_strand, root, BM_VERTS_OF_STRAND) + { + if (BM_strands_vert_is_tip(vert)) { + GWN_indexbuf_add_point_vert(&elb, BM_elem_index_get(vert)); + break; + } + } + } + + cache->tips_idx = GWN_indexbuf_build(&elb); +} + +static void editstrands_batch_cache_ensure_roots_idx(BMEditStrands *es, StrandsBatchCache *cache) +{ + if (cache->roots_idx) { + return; + } + + GWN_INDEXBUF_DISCARD_SAFE(cache->roots_idx); + + BMesh *bm = es->base.bm; + int totstrands = BM_strands_count(bm); + BMVert *root, *vert; + BMIter iter, iter_strand; + + Gwn_IndexBufBuilder elb; + GWN_indexbuf_init(&elb, GWN_PRIM_POINTS, totstrands, bm->totvert); + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + BM_ITER_STRANDS(root, &iter, bm, BM_STRANDS_OF_MESH) { + BM_ITER_STRANDS_ELEM(vert, &iter_strand, root, BM_VERTS_OF_STRAND) + { + if (BM_strands_vert_is_root(vert)) { + GWN_indexbuf_add_point_vert(&elb, BM_elem_index_get(vert)); + break; + } + } + } + + cache->roots_idx = GWN_indexbuf_build(&elb); +} + +Gwn_Batch *DRW_editstrands_batch_cache_get_wires(BMEditStrands *es) +{ + StrandsBatchCache *cache = editstrands_batch_cache_get(es); + + if (cache->wires == NULL) { + editstrands_batch_cache_ensure_pos(es, cache); + editstrands_batch_cache_ensure_segments(es, cache); + cache->wires = GWN_batch_create(GWN_PRIM_LINES, cache->pos, cache->segments); + } + + return cache->wires; +} + +Gwn_Batch *DRW_editstrands_batch_cache_get_tips(BMEditStrands *es) +{ + StrandsBatchCache *cache = editstrands_batch_cache_get(es); + + if (cache->tips == NULL) { + editstrands_batch_cache_ensure_pos(es, cache); + editstrands_batch_cache_ensure_tips_idx(es, cache); + cache->tips = GWN_batch_create(GWN_PRIM_POINTS, cache->pos, cache->tips_idx); + } + + return cache->tips; +} + +Gwn_Batch *DRW_editstrands_batch_cache_get_roots(BMEditStrands *es) +{ + StrandsBatchCache *cache = editstrands_batch_cache_get(es); + + if (cache->roots == NULL) { + editstrands_batch_cache_ensure_pos(es, cache); + editstrands_batch_cache_ensure_roots_idx(es, cache); + cache->roots = GWN_batch_create(GWN_PRIM_POINTS, cache->pos, cache->roots_idx); + } + + return cache->roots; +} + +Gwn_Batch *DRW_editstrands_batch_cache_get_points(BMEditStrands *es) +{ + StrandsBatchCache *cache = editstrands_batch_cache_get(es); + + if (cache->points == NULL) { + editstrands_batch_cache_ensure_pos(es, cache); + cache->points = GWN_batch_create(GWN_PRIM_POINTS, cache->pos, NULL); + } + + return cache->points; +} diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 70e9d985e6c..42a11ebe3e1 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -2820,6 +2820,9 @@ static void DRW_engines_enable_from_mode(int mode) case CTX_MODE_PARTICLE: use_drw_engine(&draw_engine_particle_type); break; + case CTX_MODE_HAIR: + use_drw_engine(&draw_engine_edit_strands_type); + break; case CTX_MODE_OBJECT: break; default: @@ -3512,6 +3515,7 @@ void DRW_engines_register(void) DRW_engine_register(&draw_engine_edit_lattice_type); DRW_engine_register(&draw_engine_edit_mesh_type); DRW_engine_register(&draw_engine_edit_metaball_type); + DRW_engine_register(&draw_engine_edit_strands_type); DRW_engine_register(&draw_engine_edit_surface_type); DRW_engine_register(&draw_engine_edit_text_type); DRW_engine_register(&draw_engine_paint_texture_type); @@ -3535,6 +3539,9 @@ void DRW_engines_register(void) /* BKE: particle.c */ extern void *BKE_particle_batch_cache_dirty_cb; extern void *BKE_particle_batch_cache_free_cb; + /* BKE: editstrands.c */ + extern void *BKE_editstrands_batch_cache_dirty_cb; + extern void *BKE_editstrands_batch_cache_free_cb; BKE_curve_batch_cache_dirty_cb = DRW_curve_batch_cache_dirty; BKE_curve_batch_cache_free_cb = DRW_curve_batch_cache_free; @@ -3547,6 +3554,9 @@ void DRW_engines_register(void) BKE_particle_batch_cache_dirty_cb = DRW_particle_batch_cache_dirty; BKE_particle_batch_cache_free_cb = DRW_particle_batch_cache_free; + + BKE_editstrands_batch_cache_dirty_cb = DRW_editstrands_batch_cache_dirty; + BKE_editstrands_batch_cache_free_cb = DRW_editstrands_batch_cache_free; } } diff --git a/source/blender/draw/modes/draw_mode_engines.h b/source/blender/draw/modes/draw_mode_engines.h index 23fedbba5a5..4a0ff1e6b15 100644 --- a/source/blender/draw/modes/draw_mode_engines.h +++ b/source/blender/draw/modes/draw_mode_engines.h @@ -32,6 +32,7 @@ extern DrawEngineType draw_engine_edit_curve_type; extern DrawEngineType draw_engine_edit_lattice_type; extern DrawEngineType draw_engine_edit_mesh_type; extern DrawEngineType draw_engine_edit_metaball_type; +extern DrawEngineType draw_engine_edit_strands_type; extern DrawEngineType draw_engine_edit_surface_type; extern DrawEngineType draw_engine_edit_text_type; extern DrawEngineType draw_engine_paint_texture_type; @@ -41,4 +42,4 @@ extern DrawEngineType draw_engine_particle_type; extern DrawEngineType draw_engine_pose_type; extern DrawEngineType draw_engine_sculpt_type; -#endif /* __DRAW_MODE_ENGINES_H__ */
\ No newline at end of file +#endif /* __DRAW_MODE_ENGINES_H__ */ diff --git a/source/blender/draw/modes/edit_strands_mode.c b/source/blender/draw/modes/edit_strands_mode.c new file mode 100644 index 00000000000..9ebedc8efa8 --- /dev/null +++ b/source/blender/draw/modes/edit_strands_mode.c @@ -0,0 +1,243 @@ +/* + * Copyright 2016, Blender Foundation. + * + * 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. + * + * Contributor(s): Blender Institute + * + */ + +/** \file blender/draw/modes/particle_mode.c + * \ingroup draw + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "DNA_view3d_types.h" + +#include "BKE_editstrands.h" + +/* If builtin shaders are needed */ +#include "GPU_shader.h" + +#include "draw_common.h" + +#include "draw_mode_engines.h" + +extern GlobalsUboStorage ts; + +/* *********** LISTS *********** */ +/* All lists are per viewport specific datas. + * They are all free when viewport changes engines + * or is free itself. Use PARTICLE_engine_init() to + * initialize most of them and PARTICLE_cache_init() + * for PARTICLE_PassList */ + +typedef struct EDIT_STRANDS_PassList { + /* Declare all passes here and init them in + * PARTICLE_cache_init(). + * Only contains (DRWPass *) */ + struct DRWPass *wires; + struct DRWPass *tips; + struct DRWPass *roots; + struct DRWPass *points; +} EDIT_STRANDS_PassList; + +typedef struct EDIT_STRANDS_StorageList { + /* Contains any other memory block that the engine needs. + * 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 EDIT_STRANDS_PrivateData *g_data; +} EDIT_STRANDS_StorageList; + +typedef struct EDIT_STRANDS_Data { + /* Struct returned by DRW_viewport_engine_data_get. + * If you don't use one of these, just make it a (void *) */ + // void *fbl; + void *engine_type; /* Required */ + DRWViewportEmptyList *fbl; + DRWViewportEmptyList *txl; + EDIT_STRANDS_PassList *psl; + EDIT_STRANDS_StorageList *stl; +} EDIT_STRANDS_Data; + +/* *********** STATIC *********** */ + +typedef struct EDIT_STRANDS_PrivateData { + /* resulting curve as 'wire' for fast editmode drawing */ + DRWShadingGroup *wires_shgrp; + DRWShadingGroup *tips_shgrp; + DRWShadingGroup *roots_shgrp; + DRWShadingGroup *points_shgrp; +} EDIT_STRANDS_PrivateData; /* Transient data */ + +/* *********** FUNCTIONS *********** */ + +/* Here init all passes and shading groups + * Assume that all Passes are NULL */ +static void EDIT_STRANDS_cache_init(void *vedata) +{ + EDIT_STRANDS_PassList *psl = ((EDIT_STRANDS_Data *)vedata)->psl; + EDIT_STRANDS_StorageList *stl = ((EDIT_STRANDS_Data *)vedata)->stl; + + if (!stl->g_data) { + /* Alloc transient pointers */ + stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); + } + + GPUShader *point_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA); + GPUShader *wire_shader = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR); + + { + /* Strand wires */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->wires = DRW_pass_create("Strand Wire Verts Pass", state); + + stl->g_data->wires_shgrp = DRW_shgroup_create(wire_shader, psl->wires); + DRW_shgroup_uniform_vec4(stl->g_data->wires_shgrp, "color", ts.colorWireEdit, 1); + } + + { + /* Tip vertices */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->tips = DRW_pass_create("Strand Tip Verts Pass", state); + + stl->g_data->tips_shgrp = DRW_shgroup_create(point_shader, psl->tips); + DRW_shgroup_uniform_vec4(stl->g_data->tips_shgrp, "color", ts.colorVertex, 1); + DRW_shgroup_uniform_float(stl->g_data->tips_shgrp, "size", &ts.sizeVertex, 1); + } + + { + /* Root vertices */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->roots = DRW_pass_create("Strand Root Verts Pass", state); + + stl->g_data->roots_shgrp = DRW_shgroup_create(point_shader, psl->roots); + DRW_shgroup_uniform_vec4(stl->g_data->roots_shgrp, "color", ts.colorVertex, 1); + DRW_shgroup_uniform_float(stl->g_data->roots_shgrp, "size", &ts.sizeVertex, 1); + } + + { + /* Interior vertices */ + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND; + psl->points = DRW_pass_create("Strand Interior Verts Pass", state); + + stl->g_data->points_shgrp = DRW_shgroup_create(point_shader, psl->points); + DRW_shgroup_uniform_vec4(stl->g_data->points_shgrp, "color", ts.colorVertex, 1); + DRW_shgroup_uniform_float(stl->g_data->points_shgrp, "size", &ts.sizeVertex, 1); + } +} + +static void edit_strands_add_ob_to_pass( + Scene *scene, Object *ob, BMEditStrands *edit, + DRWShadingGroup *tips_shgrp, + DRWShadingGroup *roots_shgrp, + DRWShadingGroup *points_shgrp, + DRWShadingGroup *wires_shgrp) +{ + HairEditSettings *tsettings = &scene->toolsettings->hair_edit; + + { + struct Gwn_Batch *geom = DRW_cache_editstrands_get_wires(edit); + DRW_shgroup_call_add(wires_shgrp, geom, ob->obmat); + } + + switch (tsettings->select_mode) + { + case HAIR_SELECT_TIP: + { + struct Gwn_Batch *geom = DRW_cache_editstrands_get_tips(edit); + DRW_shgroup_call_add(tips_shgrp, geom, ob->obmat); + break; + } + + case HAIR_SELECT_STRAND: + { +#if 0 + struct Gwn_Batch *geom = DRW_cache_editstrands_get_roots(edit); + DRW_shgroup_call_add(roots_shgrp, geom, ob->obmat); +#else + UNUSED_VARS(roots_shgrp); +#endif + break; + } + + case HAIR_SELECT_VERTEX: + { + struct Gwn_Batch *geom = DRW_cache_editstrands_get_points(edit); + DRW_shgroup_call_add(points_shgrp, geom, ob->obmat); + break; + } + } +} + +/* Add geometry to shadingGroups. Execute for each objects */ +static void EDIT_STRANDS_cache_populate(void *vedata, Object *ob) +{ + BMEditStrands *edit = BKE_editstrands_from_object(ob); + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + + if (!edit || ob == scene->obedit) + return; + + EDIT_STRANDS_StorageList *stl = ((EDIT_STRANDS_Data *)vedata)->stl; + + edit_strands_add_ob_to_pass( + scene, ob, edit, stl->g_data->tips_shgrp, stl->g_data->roots_shgrp, + stl->g_data->points_shgrp, stl->g_data->wires_shgrp); +} + +/* Optional: Post-cache_populate callback */ +static void EDIT_STRANDS_cache_finish(void *vedata) +{ + EDIT_STRANDS_PassList *psl = ((EDIT_STRANDS_Data *)vedata)->psl; + EDIT_STRANDS_StorageList *stl = ((EDIT_STRANDS_Data *)vedata)->stl; + + /* Do something here! dependant on the objects gathered */ + UNUSED_VARS(psl, stl); +} + +/* Draw time ! Control rendering pipeline from here */ +static void EDIT_STRANDS_draw_scene(void *vedata) +{ + EDIT_STRANDS_PassList *psl = ((EDIT_STRANDS_Data *)vedata)->psl; + + DRW_draw_pass(psl->wires); + DRW_draw_pass(psl->points); + DRW_draw_pass(psl->roots); + DRW_draw_pass(psl->tips); + + /* If you changed framebuffer, double check you rebind + * the default one with its textures attached before finishing */ +} + +static const DrawEngineDataSize STRANDS_data_size = DRW_VIEWPORT_DATA_SIZE(EDIT_STRANDS_Data); + +DrawEngineType draw_engine_edit_strands_type = { + NULL, NULL, + N_("EditStrandsMode"), + &STRANDS_data_size, + NULL, + NULL, + &EDIT_STRANDS_cache_init, + &EDIT_STRANDS_cache_populate, + &EDIT_STRANDS_cache_finish, + NULL, /* draw_background but not needed by mode engines */ + &EDIT_STRANDS_draw_scene +}; diff --git a/source/blender/editors/hair/hair_cursor.c b/source/blender/editors/hair/hair_cursor.c index a3905db2f80..06c39727670 100644 --- a/source/blender/editors/hair/hair_cursor.c +++ b/source/blender/editors/hair/hair_cursor.c @@ -86,6 +86,8 @@ static void hair_draw_cursor(bContext *C, int x, int y, void *UNUSED(customdata) immUniformColor3fvAlpha(col, col[3]*0.5f); } imm_draw_circle_wire(pos, x, y, final_radius, 40); + + immUnbindProgram(); } void hair_edit_cursor_start(bContext *C, int (*poll)(bContext *C)) diff --git a/source/blender/editors/hair/hair_edit.c b/source/blender/editors/hair/hair_edit.c index b211df74654..269ca5833fa 100644 --- a/source/blender/editors/hair/hair_edit.c +++ b/source/blender/editors/hair/hair_edit.c @@ -66,7 +66,7 @@ #include "hair_intern.h" #include "paint_intern.h" -#define USE_PARTICLES 0 +#define USE_PARTICLES 1 int hair_edit_poll(bContext *C) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index fc22f9c0088..0337b1a376c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -2096,8 +2096,8 @@ static void StrandVertsToTransData(TransInfo *t, TransData *td, static void createTransStrandVerts(TransInfo *t) { - Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->scene_layer; + Object *ob = OBACT_NEW; BMEditStrands *edit = BKE_editstrands_from_object(ob); BMesh *bm = edit->base.bm; TransData *tob = NULL; @@ -2262,8 +2262,8 @@ cleanup: void flushTransStrands(TransInfo *t) { - Scene *scene = t->scene; - Object *ob = OBACT; + SceneLayer *sl = t->scene_layer; + Object *ob = OBACT_NEW; BMEditStrands *edit = BKE_editstrands_from_object(ob); BMEditStrandsLocations origlocs = t->custom.type.data; @@ -6697,9 +6697,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) { /* do nothing */ } - else if ((t->scene->basact) && - (ob = t->scene->basact->object) && - (ob->mode & OB_MODE_HAIR_EDIT) && + else if ((ob->mode & OB_MODE_HAIR_EDIT) && BKE_editstrands_from_object(ob)) { /* do nothing */ |