[Bf-blender-cvs] [73babd2] hair_system: Added a HairRenderIterator for consistently generating draw and render data from a hair system.

Lukas Tönne noreply at git.blender.org
Tue Aug 12 20:16:56 CEST 2014


Commit: 73babd265b11e79dd88d65c93c8466c800dd0fd8
Author: Lukas Tönne
Date:   Tue Aug 12 20:15:44 2014 +0200
Branches: hair_system
https://developer.blender.org/rB73babd265b11e79dd88d65c93c8466c800dd0fd8

Added a HairRenderIterator for consistently generating draw and render
data from a hair system.

This replaces the current draw data generation and greatly simplifies
stepping through hair data, so that different render engines can easily
implement hair rendering consistently without caching large amounts of
data and with consistent results.

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

M	source/blender/blenkernel/BKE_hair.h
M	source/blender/blenkernel/intern/hair.c
M	source/blender/editors/space_view3d/drawhair.c

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

diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
index 9d7e4d7..b734558 100644
--- a/source/blender/blenkernel/BKE_hair.h
+++ b/source/blender/blenkernel/BKE_hair.h
@@ -55,4 +55,34 @@ void BKE_hair_calculate_rest(struct HairSystem *hsys);
 
 void BKE_hair_debug_data_free(struct HairDebugData *debug_data);
 
+/* cached per-hair data */
+typedef struct HairPointRenderCache {
+	float frame[3][3];
+} HairPointRenderCache;
+
+typedef struct HairRenderIterator {
+	struct HairSystem *hsys;
+	struct HairPointRenderCache *hair_cache; /* array of maxpoints elements to avoid recalculating per child hair */
+	int maxpoints;
+	int steps_per_point;
+	
+	/* hair curve data */
+	struct HairCurve *hair;
+	int i;
+	
+	/* hair point data */
+	struct HairPoint *point;
+	int k;
+	
+	int step, totsteps;
+} HairRenderIterator;
+
+void BKE_hair_render_iter_init(struct HairRenderIterator *iter, struct HairSystem *hsys);
+void BKE_hair_render_iter_end(struct HairRenderIterator *iter);
+void BKE_hair_render_iter_init_hair(struct HairRenderIterator *iter);
+bool BKE_hair_render_iter_valid_hair(struct HairRenderIterator *iter);
+bool BKE_hair_render_iter_valid_step(struct HairRenderIterator *iter);
+void BKE_hair_render_iter_next(struct HairRenderIterator *iter);
+void BKE_hair_render_iter_get(struct HairRenderIterator *iter, float co[3], float *radius);
+
 #endif
diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c
index f2126cd..1607d17 100644
--- a/source/blender/blenkernel/intern/hair.c
+++ b/source/blender/blenkernel/intern/hair.c
@@ -231,3 +231,84 @@ void BKE_hair_debug_data_free(HairDebugData *debug_data)
 		MEM_freeN(debug_data);
 	}
 }
+
+static int hair_maxpoints(HairSystem *hsys)
+{
+	HairCurve *hair;
+	int i;
+	int maxpoints = 0;
+	for (i = 0, hair = hsys->curves; i < hsys->totcurves; ++i, ++hair) {
+		if (hair->totpoints > maxpoints)
+			maxpoints = hair->totpoints;
+	}
+	return maxpoints;
+}
+
+void BKE_hair_render_iter_init(HairRenderIterator *iter, HairSystem *hsys)
+{
+	iter->hsys = hsys;
+	iter->maxpoints = hair_maxpoints(hsys);
+	iter->hair_cache = MEM_mallocN(sizeof(HairPointRenderCache) * iter->maxpoints, "hair render cache data");
+	iter->steps_per_point = 1; // XXX TODO!
+	
+	iter->hair = hsys->curves;
+	iter->i = 0;
+}
+
+void BKE_hair_render_iter_init_hair(HairRenderIterator *iter)
+{
+	iter->point = iter->hair->points;
+	iter->k = 0;
+	
+	iter->step = 0;
+	iter->totsteps = (iter->hair->totpoints - 1) * iter->steps_per_point + 1;
+}
+
+void BKE_hair_render_iter_end(HairRenderIterator *iter)
+{
+	if (iter->hair_cache)
+		MEM_freeN(iter->hair_cache);
+}
+
+bool BKE_hair_render_iter_valid_hair(HairRenderIterator *iter)
+{
+	return iter->i < iter->hsys->totcurves;
+}
+
+bool BKE_hair_render_iter_valid_step(HairRenderIterator *iter)
+{
+	return iter->step < iter->totsteps;
+}
+
+void BKE_hair_render_iter_next(HairRenderIterator *iter)
+{
+	++iter->step;
+	
+	if (iter->step >= iter->totsteps) {
+		++iter->hair;
+		++iter->i;
+	}
+	else if (iter->step % iter->steps_per_point == 0) {
+		++iter->point;
+		++iter->k;
+	}
+}
+
+void BKE_hair_render_iter_get(HairRenderIterator *iter, float co[3], float *radius)
+{
+	if (iter->step < iter->totsteps - 1) {
+		int i = iter->step % iter->steps_per_point;
+		float t = (float)i / (float)iter->steps_per_point;
+		float mt = 1.0f - t;
+		HairPoint *pt0 = iter->point, *pt1 = pt0 + 1;
+		
+		interp_v3_v3v3(co, pt0->co, pt1->co, t);
+		*radius = pt0->radius * mt + pt1->radius * t;
+	}
+	else {
+		HairPoint *pt0 = iter->point;
+		
+		copy_v3_v3(co, pt0->co);
+		*radius = pt0->radius;
+	}
+}
diff --git a/source/blender/editors/space_view3d/drawhair.c b/source/blender/editors/space_view3d/drawhair.c
index 031e5f7..e0b0ea5 100644
--- a/source/blender/editors/space_view3d/drawhair.c
+++ b/source/blender/editors/space_view3d/drawhair.c
@@ -110,20 +110,6 @@ static void get_hair_root_frame(HairCurve *hair, float frame[3][3])
 	}
 }
 
-static int max_hair_points(HairSystem *hsys)
-{
-	HairCurve *hair;
-	int i;
-	
-	int max_points = 0;
-	for (i = 0, hair = hsys->curves; i < hsys->totcurves; ++i, ++hair) {
-		if (hair->totpoints > max_points)
-			max_points = hair->totpoints;
-	}
-	
-	return max_points;
-}
-
 typedef struct HairRenderData {
 	float u, v;
 } HairRenderData;
@@ -149,25 +135,26 @@ static HairRenderData *gen_render_hairs(HairParams *params, unsigned int seed)
 
 static void draw_hair_render(HairSystem *hsys)
 {
-	int num_render_hairs = hsys->params.num_render_hairs;
 	HairRenderData *render_data;
 	
 	static unsigned int vertex_glbuf = 0;
 	static unsigned int elem_glbuf = 0;
 	
-	int maxpoints = max_hair_points(hsys);
-	int maxsteps = maxpoints; // TODO include interpolation
-	int maxverts = num_render_hairs * maxsteps;
-	int maxelems = num_render_hairs * 2 * (maxsteps-1);
+	int maxsteps, maxverts, maxelems;
 	
 	float (*vertex_data)[3];
 	unsigned int *elem_data;
 	
-	struct HAIR_FrameIterator *iter = HAIR_frame_iter_new();
-	int i;
+	HairRenderIterator iter;
 	
-	if (maxelems < 1)
+	BKE_hair_render_iter_init(&iter, hsys);
+	maxsteps = iter.maxpoints * iter.steps_per_point;
+	maxverts = maxsteps;
+	maxelems = 2 * (maxsteps - 1);
+	if (maxelems < 1) {
+		BKE_hair_render_iter_end(&iter);
 		return;
+	}
 	
 	/* TODO handle seeds properly here ... */
 	render_data = gen_render_hairs(&hsys->params, 12345);
@@ -197,49 +184,36 @@ static void draw_hair_render(HairSystem *hsys)
 	
 //	glEnable(GL_LIGHTING);
 	
-	for (i = 0; i < hsys->totcurves; ++i) {
-		HairCurve *hair = hsys->curves + i;
-		int totsteps = hair->totpoints; // TODO include interpolation
-		/*int totverts = num_render_hairs * totsteps;*/ /* unused */
-		int totelems = num_render_hairs * 2 * (totsteps-1);
+	while (BKE_hair_render_iter_valid_hair(&iter)) {
+		int totelems;
 		unsigned int vertex_offset = 0;
 		unsigned int elem_offset = 0;
-		unsigned int start_vertex = 0;
 		float initial_frame[3][3];
 		
-		get_hair_root_frame(hair, initial_frame);
+		get_hair_root_frame(iter.hair, initial_frame);
 		
 #ifdef USE_BUFFERS
 		vertex_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
 		elem_data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
 #endif
+		BKE_hair_render_iter_init_hair(&iter);
+		totelems = 2 * (iter.totsteps-1);
 		
-		for (HAIR_frame_iter_init(iter, hair, hair->avg_rest_length, hsys->params.curl_smoothing, initial_frame); HAIR_frame_iter_valid(iter); HAIR_frame_iter_next(iter)) {
-			int point_index = HAIR_frame_iter_index(iter);
-			HairPoint *point = hair->points + point_index;
-			float radius = point->radius;
-			int a;
-			float co[3], nor[3], tan[3], cotan[3];
+		for (; BKE_hair_render_iter_valid_step(&iter); BKE_hair_render_iter_next(&iter)) {
+			float radius;
+			float co[3];
 			
-			HAIR_frame_iter_get(iter, nor, tan, cotan);
+			BKE_hair_render_iter_get(&iter, co, &radius);
 			
-			copy_v3_v3(co, point->co);
+			copy_v3_v3(vertex_data[vertex_offset], co);
 			
-			for (a = 0; a < num_render_hairs; ++a) {
-				copy_v3_v3(vertex_data[vertex_offset], co);
-				madd_v3_v3fl(vertex_data[vertex_offset], tan, render_data[a].u * radius);
-				madd_v3_v3fl(vertex_data[vertex_offset], cotan, render_data[a].v * radius);
-				
-				if (HAIR_frame_iter_index(iter) < hair->totpoints - 1) {
-					elem_data[elem_offset] = start_vertex + a;
-					elem_data[elem_offset + 1] = start_vertex + a + num_render_hairs;
-				}
-				
-				vertex_offset += 1;
-				elem_offset += 2;
+			if (iter.step < iter.totsteps - 1) {
+				elem_data[elem_offset] = vertex_offset;
+				elem_data[elem_offset + 1] = vertex_offset + 1;
 			}
 			
-			start_vertex += num_render_hairs;
+			vertex_offset += 1;
+			elem_offset += 2;
 		}
 		
 #ifdef USE_BUFFERS
@@ -273,7 +247,7 @@ static void draw_hair_render(HairSystem *hsys)
 	MEM_freeN(elem_data);
 #endif
 	
-	HAIR_frame_iter_free(iter);
+	BKE_hair_render_iter_end(&iter);
 	
 	MEM_freeN(render_data);




More information about the Bf-blender-cvs mailing list