[Bf-blender-cvs] [3a438c675f5] strand_editmode: Hair fiber (child hair) drawing during edit mode, with heavy GPU leveraging.

Lukas Tönne noreply at git.blender.org
Tue Aug 1 09:10:18 CEST 2017


Commit: 3a438c675f590d13a95929f9da87c2fd4a95faa7
Author: Lukas Tönne
Date:   Sat Jul 29 08:41:33 2017 +0100
Branches: strand_editmode
https://developer.blender.org/rB3a438c675f590d13a95929f9da87c2fd4a95faa7

Hair fiber (child hair) drawing during edit mode, with heavy GPU leveraging.

Hair drawing requires fairly large vertex buffers. Vertices also need to be interpolated
and displaced according to the control (parent) hairs and hair-style features like curling
and clumping.

Instead of doing this in advance on the CPU and uploading a large vertex buffer every frame,
this work can be done on the GPU for realtime display, because interpolation and displacement
are highly parallelizable. The vertex buffers then only need to be uploaded once (as long
as strand lengths remain the same). The vertex format can also be very lightweight, requiring
only a curve parameter and index (half the size needed for full positions).

For interpolating a buffer texture is used in the shader, which contains all information
about the control curves (parents) from which to interpolate final vertex positions.

===================================================================

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/BKE_editstrands.h
A	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/CMakeLists.txt
M	source/blender/blenkernel/intern/editstrands.c
A	source/blender/blenkernel/intern/hair.c
M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/intern/draw_cache.c
M	source/blender/draw/intern/draw_cache.h
M	source/blender/draw/intern/draw_cache_impl.h
M	source/blender/draw/intern/draw_cache_impl_strands.c
M	source/blender/draw/intern/draw_common.h
M	source/blender/draw/modes/edit_strands_mode.c
M	source/blender/draw/modes/shaders/edit_strands_vert.glsl
A	source/blender/draw/modes/shaders/hair_frag.glsl
A	source/blender/draw/modes/shaders/hair_vert.glsl
M	source/blender/editors/hair/hair_object_particles.c
M	source/blender/gpu/GPU_texture.h
M	source/blender/makesdna/DNA_scene_types.h
M	source/blender/makesrna/intern/rna_sculpt_paint.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 4846cf151d4..8056b14dc70 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -54,6 +54,9 @@ class VIEW3D_HT_header(Header):
                 row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
             elif mode == 'HAIR_EDIT':
                 row.prop(toolsettings.hair_edit, "select_mode", text="", expand=True)
+                row.prop(toolsettings.hair_edit, "hair_draw_mode", text="", expand=True)
+                if toolsettings.hair_edit.hair_draw_mode == 'FIBERS':
+                    row.prop(toolsettings.hair_edit, "hair_draw_size", text="Size")
 
             # Occlude geometry
             if ((view.viewport_shade not in {'BOUNDBOX', 'WIREFRAME'} and (mode == 'PARTICLE_EDIT' or (mode == 'EDIT' and obj.type == 'MESH'))) or
diff --git a/source/blender/blenkernel/BKE_editstrands.h b/source/blender/blenkernel/BKE_editstrands.h
index 96706e8ebd2..9199668fb9e 100644
--- a/source/blender/blenkernel/BKE_editstrands.h
+++ b/source/blender/blenkernel/BKE_editstrands.h
@@ -52,25 +52,44 @@ typedef struct BMEditStrands {
 	/* Scalp mesh for fixing root vertices */
 	struct DerivedMesh *root_dm;
 	
+	/* Hair fibers (optional) */
+	struct HairFiber *hair_fibers;
+	int hair_totfibers;
+	unsigned int hair_seed;
+	
 	int flag;
 	
-	unsigned int vertex_glbuf;
-	unsigned int elem_glbuf;
-	unsigned int dot_glbuf;
+	unsigned int vertex_glbuf; // legacy gpu code
+	unsigned int elem_glbuf; // legacy gpu code
+	unsigned int dot_glbuf; // legacy gpu code
 	void *batch_cache;
+	void *texture;
 } BMEditStrands;
 
 /* BMEditStrands->flag */
 typedef enum BMEditStrandsFlag {
-	BM_STRANDS_DIRTY_SEGLEN     = 1,
+	BM_STRANDS_DIRTY_SEGLEN     = (1 << 0),
+	BM_STRANDS_DIRTY_ROOTS      = (1 << 1),
 } BMEditStrandsFlag;
 
 struct BMEditStrands *BKE_editstrands_create(struct BMesh *bm, struct DerivedMesh *root_dm);
 struct BMEditStrands *BKE_editstrands_copy(struct BMEditStrands *es);
+struct BMEditStrands *BKE_editstrands_from_object_particles(struct Object *ob, struct ParticleSystem **r_psys);
 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);
 
+/* === Hair Fibers === */
+
+bool BKE_editstrands_hair_ensure(struct BMEditStrands *es);
+void BKE_editstrands_hair_free(struct BMEditStrands *es);
+
+int* BKE_editstrands_hair_get_fiber_lengths(struct BMEditStrands *es);
+void BKE_editstrands_hair_get_texture_buffer(struct BMEditStrands *es, void **texbuffer, int *r_size,
+                                             int *strand_map_start,
+                                             int *strand_vertex_start,
+                                             int *fiber_start);
+
 /* === Constraints === */
 
 /* Stores vertex locations for temporary reference:
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
new file mode 100644
index 00000000000..4169a3b6f16
--- /dev/null
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -0,0 +1,76 @@
+/*
+ * ***** 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) Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Lukas Toenne
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_HAIR_H__
+#define __BKE_HAIR_H__
+
+/** \file blender/blenkernel/BKE_hair.h
+ *  \ingroup bke
+ */
+
+#include "BLI_utildefines.h"
+
+static const unsigned int STRAND_INDEX_NONE = 0xFFFFFFFF;
+
+typedef struct HairFiber {
+	/* Sample on the scalp mesh for the root vertex */
+	MeshSample root;
+	/* Indices of control strands for interpolation */
+	unsigned int parent_index[4];
+	/* Weights of control strands for interpolation */
+	float parent_weight[4];
+	/* Parametric distance to the primary control strand */
+	float root_distance[2];
+} HairFiber;
+
+bool BKE_hair_fiber_get_location(const struct HairFiber *fiber, struct DerivedMesh *root_dm, float loc[3]);
+bool BKE_hair_fiber_get_vectors(const struct HairFiber *fiber, struct DerivedMesh *root_dm,
+                                   float loc[3], float nor[3], float tang[3]);
+bool BKE_hair_fiber_get_matrix(const struct HairFiber *fiber, struct DerivedMesh *root_dm, float mat[4][4]);
+
+typedef struct StrandsView {
+	int (*get_num_strands)(const struct StrandsView* strands);
+	int (*get_num_verts)(const struct StrandsView* strands);
+	
+	void (*get_strand_lengths)(const struct StrandsView* strands, int *r_lengths);
+	void (*get_strand_roots)(const struct StrandsView* strands, struct MeshSample *r_roots);
+	void (*get_strand_vertices)(const struct StrandsView* strands, float (*positions)[3]);
+} StrandsView;
+
+struct HairFiber* BKE_hair_fibers_create(const struct StrandsView *strands,
+                                         struct DerivedMesh *scalp, unsigned int amount,
+                                         unsigned int seed);
+
+int* BKE_hair_get_fiber_lengths(const struct HairFiber *fibers, int totfibers,
+                                 const struct StrandsView *strands);
+
+void BKE_hair_get_texture_buffer(const struct StrandsView *strands, struct DerivedMesh *scalp,
+                                 const struct HairFiber *fibers, int totfibers,
+                                 void **r_texbuffer, int *r_size, int *r_strand_map_start,
+                                 int *r_strand_vertex_start, int *r_fiber_start);
+
+#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 8d0dedd9f72..675b4fa48da 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -112,6 +112,7 @@ set(SRC
 	intern/freestyle.c
 	intern/gpencil.c
 	intern/group.c
+	intern/hair.c
 	intern/icons.c
 	intern/idcode.c
 	intern/idprop.c
@@ -247,6 +248,7 @@ set(SRC
 	BKE_global.h
 	BKE_gpencil.h
 	BKE_group.h
+	BKE_hair.h
 	BKE_icons.h
 	BKE_idcode.h
 	BKE_idprop.h
diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c
index d1494d2a997..16e47aabf91 100644
--- a/source/blender/blenkernel/intern/editstrands.c
+++ b/source/blender/blenkernel/intern/editstrands.c
@@ -48,6 +48,7 @@
 #include "BKE_DerivedMesh.h"
 #include "BKE_editstrands.h"
 #include "BKE_effect.h"
+#include "BKE_hair.h"
 #include "BKE_mesh_sample.h"
 #include "BKE_object.h"
 #include "BKE_particle.h"
@@ -83,6 +84,25 @@ BMEditStrands *BKE_editstrands_copy(BMEditStrands *es)
 }
 
 /**
+ * \brief Return the BMEditStrands for a given object's particle systems
+ */
+BMEditStrands *BKE_editstrands_from_object_particles(Object *ob, ParticleSystem **r_psys)
+{
+	ParticleSystem *psys = psys_get_current(ob);
+	if (psys && psys->hairedit) {
+		if (r_psys) {
+			*r_psys = psys;
+		}
+		return psys->hairedit;
+	}
+	
+	if (r_psys) {
+		*r_psys = NULL;
+	}
+	return NULL;
+}
+
+/**
  * \brief Return the BMEditStrands for a given object
  */
 BMEditStrands *BKE_editstrands_from_object(Object *ob)
@@ -93,13 +113,7 @@ BMEditStrands *BKE_editstrands_from_object(Object *ob)
 			return me->edit_strands;
 	}
 	
-	{
-		ParticleSystem *psys = psys_get_current(ob);
-		if (psys && psys->hairedit)
-			return psys->hairedit;
-	}
-	
-	return NULL;
+	return BKE_editstrands_from_object_particles(ob, NULL);
 }
 
 void BKE_editstrands_update_linked_customdata(BMEditStrands *UNUSED(es))
@@ -110,6 +124,7 @@ void BKE_editstrands_update_linked_customdata(BMEditStrands *UNUSED(es))
 void BKE_editstrands_free(BMEditStrands *es)
 {
 	BKE_editstrands_batch_cache_free(es);
+	BKE_editstrands_hair_free(es);
 	
 	if (es->base.bm)
 		BM_mesh_free(es->base.bm);
@@ -117,6 +132,123 @@ void BKE_editstrands_free(BMEditStrands *es)
 		es->root_dm->release(es->root_dm);
 }
 
+/* === Hair fibers === */
+
+typedef struct EditStrandsView {
+	StrandsView base;
+	BMEditStrands *edit;
+} EditStrandsView;
+
+static int get_num_strands(const StrandsView *strands_)
+{
+	const EditStrandsView *strands = (EditStrandsView *)strands_;
+	BMesh *bm = strands->edit->base.bm;
+	return BM_strands_count(bm);
+}
+
+static int get_num_verts(const StrandsView *strands_)
+{
+	const EditStrandsView *strands = (EditStrandsView *)strands_;
+	BMesh *bm = strands->edit->base.bm;
+	return bm->totvert;
+}
+
+static void get_strand_lengths(const StrandsView* strands_, int *r_lengths)
+{
+	const EditStrandsView *strands = (EditStrandsView *)strands_;
+	BMesh *bm = strands->edit->base.bm;
+	BMVert *v;
+	BMIter iter;
+	int i;
+	
+	int *length = r_lengths;
+	BM_ITER_STRANDS_INDEX(v, &iter, bm, BM_STRANDS_OF_MESH, i) {
+		*length = BM_strands_keys_count(v);
+		++length;
+	}
+}
+
+static void get_strand_roots(const StrandsView* strands_, struct MeshSample *r_roots)
+{
+	const EditStrandsView *strands = (EditStrandsView *)strands_;
+	BMesh *bm = strands->edit->base.bm;
+	BMVert *v;
+	BMIter iter;
+	int i;
+	
+	MeshSample *root = r_roots;
+	BM_ITER_STRANDS_INDEX(v, &iter, bm, BM_STRANDS_OF_MESH, i) {
+		BM_elem_meshsample_data_named_get(&bm->vdata, v, CD_MSURFACE_SAMPLE, CD_HAIR_ROOT_LOCATION, root);
+		++root;
+	}
+}
+
+static void get_strand_vertices(const StrandsView* strands_, float (*verts)[3])
+{
+	const EditStrandsView *strands = (EditStrandsView *)strands_;
+	BMesh *bm = strands->edit->base.bm;
+	BMVert *vert;
+	

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list