Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2017-07-22 14:35:40 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2017-07-22 14:35:40 +0300
commit679113fbd5ecef72850b572535534ffde1f03f11 (patch)
tree38ab7d04759ddf86a999938504a0346dfdd9e51a /source/blender
parent65d2374c806ecf42ccf106cd28380e7a7071f789 (diff)
Basic drawing code for hair edit mode in the new 2.8 draw engine system.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_editstrands.h14
-rw-r--r--source/blender/blenkernel/intern/editstrands.c34
-rw-r--r--source/blender/blenkernel/intern/mesh_sample.c4
-rw-r--r--source/blender/draw/CMakeLists.txt2
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c2
-rw-r--r--source/blender/draw/intern/draw_cache.c25
-rw-r--r--source/blender/draw/intern/draw_cache.h7
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h10
-rw-r--r--source/blender/draw/intern/draw_cache_impl_strands.c322
-rw-r--r--source/blender/draw/intern/draw_manager.c10
-rw-r--r--source/blender/draw/modes/draw_mode_engines.h3
-rw-r--r--source/blender/draw/modes/edit_strands_mode.c243
-rw-r--r--source/blender/editors/hair/hair_cursor.c2
-rw-r--r--source/blender/editors/hair/hair_edit.c2
-rw-r--r--source/blender/editors/transform/transform_conversions.c12
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 */