[Bf-blender-cvs] [9feec51214d] strand_editmode: Subdivision of hair fibers for smoother shading.

Lukas Tönne noreply at git.blender.org
Thu Aug 3 21:30:24 CEST 2017


Commit: 9feec51214d811537f7fb9fe0af579117ee007f7
Author: Lukas Tönne
Date:   Thu Aug 3 20:27:33 2017 +0100
Branches: strand_editmode
https://developer.blender.org/rB9feec51214d811537f7fb9fe0af579117ee007f7

Subdivision of hair fibers for smoother shading.

Subdivision works on the parent strands for efficiency. The fibers lengths
are based on the final subdivided length of parents, so no changes to the
shader are required.

This would be nicer with a tesselation shader, but this feature is not
available in Blender 2.8.

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

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/blenkernel/BKE_editstrands.h
M	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/intern/editstrands.c
M	source/blender/blenkernel/intern/hair.c
M	source/blender/blenkernel/intern/scene.c
M	source/blender/draw/engines/eevee/eevee_materials.c
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/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 8056b14dc70..8a438cf9802 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -57,6 +57,7 @@ class VIEW3D_HT_header(Header):
                 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")
+                    row.prop(toolsettings.hair_edit, "hair_draw_subdivision", text="Subdivide")
 
             # 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 e5858160f65..1e0ed8cf3c4 100644
--- a/source/blender/blenkernel/BKE_editstrands.h
+++ b/source/blender/blenkernel/BKE_editstrands.h
@@ -84,12 +84,10 @@ void BKE_editstrands_free(struct BMEditStrands *es);
 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_size(struct BMEditStrands *es, int *r_size,
-                                                  int *r_strand_map_start,
-                                                  int *r_strand_vertex_start,
-                                                  int *r_fiber_start);
-void BKE_editstrands_hair_get_texture_buffer(struct BMEditStrands *es, void *texbuffer);
+int* BKE_editstrands_hair_get_fiber_lengths(struct BMEditStrands *es, int subdiv);
+void BKE_editstrands_hair_get_texture_buffer_size(struct BMEditStrands *es, int subdiv, int *r_size,
+                                                  int *r_strand_map_start, int *r_strand_vertex_start, int *r_fiber_start);
+void BKE_editstrands_hair_get_texture_buffer(struct BMEditStrands *es, int subdiv, void *texbuffer);
 
 /* === Constraints === */
 
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 5eafc14e66f..367741fb4fe 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -66,13 +66,13 @@ struct HairFiber* BKE_hair_fibers_create(const struct StrandsView *strands,
                                          unsigned int seed);
 
 int* BKE_hair_get_fiber_lengths(const struct HairFiber *fibers, int totfibers,
-                                 const struct StrandsView *strands);
+                                 const struct StrandsView *strands, int subdiv);
 
-void BKE_hair_get_texture_buffer_size(const struct StrandsView *strands, int totfibers,
+void BKE_hair_get_texture_buffer_size(const struct StrandsView *strands, int totfibers, int subdiv,
                                       int *r_size, int *r_strand_map_start,
                                       int *r_strand_vertex_start, int *r_fiber_start);
 void BKE_hair_get_texture_buffer(const struct StrandsView *strands, struct DerivedMesh *scalp,
-                                 const struct HairFiber *fibers, int totfibers,
+                                 const struct HairFiber *fibers, int totfibers, int subdiv,
                                  void *texbuffer);
 
 #endif
diff --git a/source/blender/blenkernel/intern/editstrands.c b/source/blender/blenkernel/intern/editstrands.c
index 0fe286a5d3a..8cfc0bb606c 100644
--- a/source/blender/blenkernel/intern/editstrands.c
+++ b/source/blender/blenkernel/intern/editstrands.c
@@ -233,26 +233,24 @@ void BKE_editstrands_hair_free(BMEditStrands *es)
 	}
 }
 
-int* BKE_editstrands_hair_get_fiber_lengths(BMEditStrands *es)
+int* BKE_editstrands_hair_get_fiber_lengths(BMEditStrands *es, int subdiv)
 {
 	EditStrandsView strands = editstrands_get_view(es);
-	return BKE_hair_get_fiber_lengths(es->hair_fibers, es->hair_totfibers, &strands.base);
+	return BKE_hair_get_fiber_lengths(es->hair_fibers, es->hair_totfibers, &strands.base, subdiv);
 }
 
-void BKE_editstrands_hair_get_texture_buffer_size(BMEditStrands *es, int *r_size,
-                                                  int *r_strand_map_start,
-                                                  int *r_strand_vertex_start,
-                                                  int *r_fiber_start)
+void BKE_editstrands_hair_get_texture_buffer_size(BMEditStrands *es, int subdiv, int *r_size,
+                                                  int *r_strand_map_start, int *r_strand_vertex_start, int *r_fiber_start)
 {
 	EditStrandsView strands = editstrands_get_view(es);
-	BKE_hair_get_texture_buffer_size(&strands.base, es->hair_totfibers,
-	                                 r_size, r_strand_map_start, r_strand_vertex_start, r_fiber_start);
+	BKE_hair_get_texture_buffer_size(&strands.base, es->hair_totfibers, subdiv, r_size,
+	                                 r_strand_map_start, r_strand_vertex_start, r_fiber_start);
 }
 
-void BKE_editstrands_hair_get_texture_buffer(BMEditStrands *es, void *texbuffer)
+void BKE_editstrands_hair_get_texture_buffer(BMEditStrands *es, int subdiv, void *texbuffer)
 {
 	EditStrandsView strands = editstrands_get_view(es);
-	BKE_hair_get_texture_buffer(&strands.base, es->root_dm, es->hair_fibers, es->hair_totfibers, texbuffer);
+	BKE_hair_get_texture_buffer(&strands.base, es->root_dm, es->hair_fibers, es->hair_totfibers, subdiv, texbuffer);
 }
 
 /* === Constraints === */
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 59677a25bc1..ee02d92c193 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -256,13 +256,26 @@ HairFiber* BKE_hair_fibers_create(const StrandsView *strands,
 	return fibers;
 }
 
-int* BKE_hair_get_fiber_lengths(const HairFiber *fibers, int totfibers, const StrandsView *strands)
+static int hair_get_strand_subdiv_numverts(int numstrands, int numverts, int subdiv)
+{
+	return ((numverts - numstrands) << subdiv) + numstrands;
+}
+
+static void hair_get_strand_subdiv_lengths(int *lengths, const int *orig_lengths, int num_strands, int subdiv)
+{
+	for (int i = 0; i < num_strands; ++i) {
+		lengths[i] = ((orig_lengths[i] - 1) << subdiv) + 1;
+	}
+}
+
+int* BKE_hair_get_fiber_lengths(const HairFiber *fibers, int totfibers, const StrandsView *strands, int subdiv)
 {
 	int *fiber_length = MEM_mallocN(sizeof(int) * totfibers, "fiber length");
 
 	const int num_strands = strands->get_num_strands(strands);
-	int *strand_length = MEM_mallocN(sizeof(int) * num_strands, "strand length");
-	strands->get_strand_lengths(strands, strand_length);
+	int *lengths = MEM_mallocN(sizeof(int) * num_strands, "strand length");
+	strands->get_strand_lengths(strands, lengths);
+	hair_get_strand_subdiv_lengths(lengths, lengths, num_strands, subdiv);
 	
 	for (int i = 0; i < totfibers; ++i) {
 		
@@ -276,14 +289,14 @@ int* BKE_hair_get_fiber_lengths(const HairFiber *fibers, int totfibers, const St
 			}
 			BLI_assert(si < num_strands);
 			
-			fiblen += (float)strand_length[si] * sw;
+			fiblen += (float)lengths[si] * sw;
 		}
 		
 		// use rounded number of segments
 		fiber_length[i] = (int)(fiblen + 0.5f);
 	}
 	
-	MEM_freeN(strand_length);
+	MEM_freeN(lengths);
 	
 	return fiber_length;
 }
@@ -328,8 +341,8 @@ static void hair_strand_transport_frame(const float co1[3], const float co2[3],
 	copy_v3_v3(prev_nor, r_nor);
 }
 
-static void hair_strand_calc_verts(const float (*positions)[3], int num_verts, float rootmat[3][3],
-                                   HairStrandVertexTextureBuffer *strand)
+static void hair_strand_calc_vectors(const float (*positions)[3], int num_verts, float rootmat[3][3],
+                                     HairStrandVertexTextureBuffer *strand)
 {
 	for (int i = 0; i < num_verts; ++i) {
 		copy_v3_v3(strand[i].co, positions[i]);
@@ -360,6 +373,50 @@ static void hair_strand_calc_verts(const float (*positions)[3], int num_verts, f
 	}
 }
 
+static int hair_strand_subdivide(float (*verts)[3], const float (*verts_orig)[3], int numverts_orig, int subdiv)
+{
+	{
+		/* Move vertex positions from the dense array to their initial configuration for subdivision. */
+		const int step = (1 << subdiv);
+		const float (*src)[3] = verts_orig;
+		float (*dst)[3] = verts;
+		for (int i = 0; i < numverts_orig; ++i) {
+			copy_v3_v3(*dst, *src);
+			
+			++src;
+			dst += step;
+		}
+	}
+	
+	/* Subdivide */
+	for (int d = 0; d < subdiv; ++d) {
+		const int num_edges = (numverts_orig - 1) << d;
+		const int hstep = 1 << (subdiv - d - 1);
+		const int step = 1 << (subdiv - d);
+		
+		/* Calculate edge points */
+		{
+			int index = 0;
+			for (int k = 0; k < num_edges; ++k, index += step) {
+				add_v3_v3v3(verts[index + hstep], verts[index], verts[index + step]);
+				mul_v3_fl(verts[index + hstep], 0.5f);
+			}
+		}
+		
+		/* Move original points */
+		{
+			int index = step;
+			for (int k = 1; k < num_edges; ++k, index += step) {
+				add_v3_v3v3(verts[index], verts[index - hstep], verts[index + hstep]);
+				mul_v3_fl(verts[index], 0.5f);
+			}
+		}
+	}
+	
+	const int num_verts = ((numverts_orig - 1) << subdiv) + 1;
+	return num_verts;
+}
+
 static void hair_get_fiber_buffer(const HairFiber *fibers, int totfibers, DerivedMesh *scalp,
                                   HairFiberTextureBuffer *fiber_buf)
 {
@@ -374,60 +431,85 @@ static void hair_get_fiber_buffer(const HairFiber *fibers, int totfibers, Derive
 	}
 }
 
-void BKE_hair_get_texture_buffer_size(const StrandsView *strands, int totfibers,
+void BKE_hair_get_texture_buffer_size(const StrandsView *strands, int totfibers, int subdiv,
                                       int *r_size, int *r_strand_map_start,
                                       int *r_strand_vertex_start, int *r_fiber_start)
 {
 	const int totstrands = strands->get_num_strands(strands);
 	const int totverts = strands->get_num_verts(strands);
+	const int totverts_subdiv = hair_get_strand_subdiv_numverts(totstrands, totverts, subdiv);
 	*r_strand_map_start = 0;
 	*r_str

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list