[Bf-blender-cvs] [b44af40eec6] hair_guides: New HairExportCache struct to unify pre-computation of hair data for OpenGL, render, and eventual data export.

Lukas Tönne noreply at git.blender.org
Sat May 12 10:44:32 CEST 2018


Commit: b44af40eec6cd6d602b50b28719d8556f38abcc7
Author: Lukas Tönne
Date:   Sat May 12 09:41:58 2018 +0100
Branches: hair_guides
https://developer.blender.org/rBb44af40eec6cd6d602b50b28719d8556f38abcc7

New HairExportCache struct to unify pre-computation of hair data for OpenGL, render, and eventual data export.

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

M	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/intern/hair.c
M	source/blender/blenkernel/intern/hair_draw.c
M	source/blender/draw/intern/draw_cache_impl_hair.c

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

diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 3c5ba7803a4..b2034cd4507 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -110,6 +110,26 @@ struct HairDrawSettings* BKE_hair_draw_settings_new(void);
 struct HairDrawSettings* BKE_hair_draw_settings_copy(struct HairDrawSettings *draw_settings);
 void BKE_hair_draw_settings_free(struct HairDrawSettings *draw_settings);
 
+/* === Export === */
+
+/* Intermediate data for export */
+typedef struct HairExportCache
+{
+	int totguidecurves;
+	int totguideverts;
+
+	int totfibercurves;
+	int totfiberverts;
+	int *fiber_numverts;            /* Number of vertices in each fiber */
+
+	const struct HairFollicle *follicles;
+	struct HairGuideCurve *guide_curves;
+	struct HairGuideVertex *guide_verts;
+} HairExportCache;
+
+struct HairExportCache* BKE_hair_export_cache_new(const struct HairSystem *hsys, int subdiv);
+void BKE_hair_export_cache_free(struct HairExportCache *cache);
+
 /* === Draw Cache === */
 
 enum {
@@ -120,18 +140,33 @@ enum {
 void BKE_hair_batch_cache_dirty(struct HairSystem* hsys, int mode);
 void BKE_hair_batch_cache_free(struct HairSystem* hsys);
 
-int* BKE_hair_get_fiber_lengths(const struct HairSystem* hsys, int subdiv);
 void BKE_hair_get_texture_buffer_size(
-        const struct HairSystem* hsys,
-        int subdiv,
+        const struct HairExportCache *cache,
         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 HairSystem* hsys,
+        const struct HairExportCache *cache,
         struct DerivedMesh *scalp,
-        int subdiv,
         void *texbuffer);
 
+/* === Render API === */
+
+/* Calculate required size for render buffers. */
+void BKE_hair_render_get_buffer_size(
+        const struct HairExportCache* cache,
+        int *r_totcurves,
+        int *r_totverts);
+
+/* Create render data in existing buffers.
+ * Buffers must be large enough according to BKE_hair_get_render_buffer_size.
+ */
+void BKE_hair_render_fill_buffers(
+        const struct HairExportCache* cache,
+        int vertco_stride,
+        int *r_curvestart,
+        int *r_curvelen,
+        float *r_vertco);
+
 #endif
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index 32794412826..f9e89a5e132 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -419,3 +419,139 @@ void BKE_hair_bind_follicles(HairSystem *hsys, DerivedMesh *scalp)
 	MEM_freeN(strandloc);
 }
 
+/* === Export === */
+
+BLI_INLINE int hair_get_strand_subdiv_numverts(int numstrands, int numverts, int subdiv)
+{
+	return ((numverts - numstrands) << subdiv) + numstrands;
+}
+
+BLI_INLINE int hair_get_strand_subdiv_length(int orig_length, int subdiv)
+{
+	return ((orig_length - 1) << subdiv) + 1;
+}
+
+static int hair_strand_subdivide(const HairGuideCurve* curve, const HairGuideVertex* verts, int subdiv, HairGuideVertex *r_verts)
+{
+	{
+		/* Move vertex positions from the dense array to their initial configuration for subdivision. */
+		const int step = (1 << subdiv);
+		HairGuideVertex *dst = r_verts;
+		for (int i = 0; i < curve->numverts; ++i) {
+			copy_v3_v3(dst->co, verts[i].co);
+			dst += step;
+		}
+	}
+	
+	/* Subdivide */
+	for (int d = 0; d < subdiv; ++d) {
+		const int num_edges = (curve->numverts - 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(r_verts[index + hstep].co, r_verts[index].co, r_verts[index + step].co);
+				mul_v3_fl(r_verts[index + hstep].co, 0.5f);
+			}
+		}
+		
+		/* Move original points */
+		{
+			int index = step;
+			for (int k = 1; k < num_edges; ++k, index += step) {
+				add_v3_v3v3(r_verts[index].co, r_verts[index - hstep].co, r_verts[index + hstep].co);
+				mul_v3_fl(r_verts[index].co, 0.5f);
+			}
+		}
+	}
+	
+	const int num_verts = ((curve->numverts - 1) << subdiv) + 1;
+	return num_verts;
+}
+
+HairExportCache* BKE_hair_export_cache_new(const HairSystem *hsys, int subdiv)
+{
+	HairExportCache *cache = MEM_callocN(sizeof(HairExportCache), "hair export cache");
+
+	const int totguidecurves = cache->totguidecurves = hsys->guides.totcurves;
+	cache->guide_curves = MEM_mallocN(sizeof(HairGuideCurve) * totguidecurves, "hair export guide curves");
+
+	/* Cache subdivided curves for repeated lookup */
+	int totguideverts = 0;
+	for (int i = 0; i < totguidecurves; ++i) {
+		const HairGuideCurve *curve_orig = &hsys->guides.curves[i];
+		HairGuideCurve *curve = &cache->guide_curves[i];
+		
+		memcpy(&curve->mesh_sample, &curve_orig->mesh_sample, sizeof(MeshSample));
+		curve->numverts = hair_get_strand_subdiv_length(curve_orig->numverts, subdiv);
+		curve->vertstart = totguideverts;
+		
+		totguideverts  += curve->numverts;
+	}
+	
+	cache->totguideverts = totguideverts;
+	cache->guide_verts = MEM_mallocN(sizeof(HairGuideVertex) * totguideverts, "hair export guide verts");
+	
+	for (int i = 0; i < totguidecurves; ++i) {
+		const HairGuideCurve *curve_orig = &hsys->guides.curves[i];
+		const HairGuideVertex *verts_orig = &hsys->guides.verts[curve_orig->vertstart];
+		const HairGuideCurve *curve = &cache->guide_curves[i];
+		HairGuideVertex *verts = &cache->guide_verts[curve->vertstart];
+		
+		hair_strand_subdivide(curve_orig, verts_orig, subdiv, verts);
+	}
+	
+	if (hsys->pattern)
+	{
+		const int totfibercurves = cache->totfibercurves = hsys->pattern->num_follicles;
+		
+		cache->follicles = hsys->pattern->follicles;
+		
+		cache->fiber_numverts = MEM_mallocN(sizeof(int) * totfibercurves, "fiber numverts");
+		
+		// Calculate the length of the fiber from the weighted average of its guide strands
+		cache->totfiberverts = 0;
+		HairFollicle *follicle = hsys->pattern->follicles;
+		for (int i = 0; i < totfibercurves; ++i, ++follicle) {
+			float fiblen = 0.0f;
+			
+			for (int k = 0; k < 4; ++k) {
+				const int si = follicle->parent_index[k];
+				const float sw = follicle->parent_weight[k];
+				if (si == HAIR_STRAND_INDEX_NONE || sw == 0.0f) {
+					break;
+				}
+				BLI_assert(si < totguidecurves);
+				
+				fiblen += (float)cache->guide_curves[si].numverts * sw;
+			}
+			
+			// Use rounded number of segments
+			const int numverts = (int)(fiblen + 0.5f);
+			cache->fiber_numverts[i] = numverts;
+			cache->totfiberverts += numverts;
+		}
+	}
+	
+	return cache;
+}
+
+void BKE_hair_export_cache_free(HairExportCache *cache)
+{
+	if (cache->fiber_numverts)
+	{
+		MEM_freeN(cache->fiber_numverts);
+	}
+	if (cache->guide_curves)
+	{
+		MEM_freeN(cache->guide_curves);
+	}
+	if (cache->guide_verts)
+	{
+		MEM_freeN(cache->guide_verts);
+	}
+	MEM_freeN(cache);
+}
diff --git a/source/blender/blenkernel/intern/hair_draw.c b/source/blender/blenkernel/intern/hair_draw.c
index da90ff7aa4a..a17522b0aef 100644
--- a/source/blender/blenkernel/intern/hair_draw.c
+++ b/source/blender/blenkernel/intern/hair_draw.c
@@ -67,57 +67,6 @@ void BKE_hair_draw_settings_free(HairDrawSettings *draw_settings)
 
 /* === Draw Cache === */
 
-static int hair_get_strand_subdiv_numverts(int numstrands, int numverts, int subdiv)
-{
-	return ((numverts - numstrands) << subdiv) + numstrands;
-}
-
-BLI_INLINE int hair_get_strand_subdiv_length(int orig_length, int subdiv)
-{
-	return ((orig_length - 1) << subdiv) + 1;
-}
-
-int* BKE_hair_get_fiber_lengths(const HairSystem *hsys, int subdiv)
-{
-	if (!hsys->pattern) {
-		return NULL;
-	}
-	
-	const int totfibers = hsys->pattern->num_follicles;
-	int *fiber_length = MEM_mallocN(sizeof(int) * totfibers, "fiber length");
-	
-	const int num_strands = hsys->guides.totcurves;
-	/* Cache subdivided lengths for repeated lookup */
-	int *lengths = MEM_mallocN(sizeof(int) * num_strands, "strand length");
-	for (int i = 0; i < hsys->guides.totcurves; ++i) {
-		lengths[i] = hair_get_strand_subdiv_length(hsys->guides.curves[i].numverts, subdiv);
-	}
-	
-	// Calculate the length of the fiber from the weighted average of its guide strands
-	HairFollicle *follicle = hsys->pattern->follicles;
-	for (int i = 0; i < totfibers; ++i, ++follicle) {
-		float fiblen = 0.0f;
-		
-		for (int k = 0; k < 4; ++k) {
-			int si = follicle->parent_index[k];
-			float sw = follicle->parent_weight[k];
-			if (si == HAIR_STRAND_INDEX_NONE || sw == 0.0f) {
-				break;
-			}
-			BLI_assert(si < num_strands);
-			
-			fiblen += (float)lengths[si] * sw;
-		}
-		
-		// use rounded number of segments
-		fiber_length[i] = (int)(fiblen + 0.5f);
-	}
-	
-	MEM_freeN(lengths);
-	
-	return fiber_length;
-}
-
 typedef struct HairFiberTextureBuffer {
 	unsigned int parent_index[4];
 	float parent_weight[4];
@@ -157,11 +106,11 @@ 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_vectors(const float (*positions)[3], int num_verts, float rootmat[3][3],
+static void hair_strand_calc_vectors(const HairGuideVertex* verts, 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]);
+		copy_v3_v3(strand[i].co, verts[i].co);
 	}
 	
 	// Calculate tangent and normal vectors
@@ -190,134 +139,68 @@ static void hair_strand_calc_vectors(const float (*positions)[3], int num_verts,
 	}
 }
 
-static int hair_strand_subdivide(const HairSystem *hsys, const HairGuideCurve* curve, int subdiv, float (*verts)[3])
-{
-	{
-		/* Move vertex positions from the dense array to their initial configuration for subdivision. */
-		const int step = (1 << subdiv);
-		float (*dst)[3] = verts;
-		int vertend = curve->vertstart + curve->numverts;
-		for (int i = curve->vertstart; i < vertend; ++i) {
-			copy_v3_v3(*dst, hsys->guides.verts[i].co);
-			dst += step;
-		}
-	}
-	
-	/* Subdivide */
-	for (int d = 0; d < subdiv; ++d) {
-		const int num_edges = (curve->numverts - 1) << d;
-		const int hstep = 1 << (subdiv - d - 1);
-		const int step = 1 << (subdiv - 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list