[Bf-blender-cvs] [41c7818] hair_system: Pasta visualization code for new hair system.

Antony Riakiotakis noreply at git.blender.org
Wed Aug 6 14:34:38 CEST 2014


Commit: 41c7818b1890f5693932b881697439d003962c0f
Author: Antony Riakiotakis
Date:   Tue Aug 5 22:54:11 2014 +0200
Branches: hair_system
https://developer.blender.org/rB41c7818b1890f5693932b881697439d003962c0f

Pasta visualization code for new hair system.

Allows custom subdivision and radius but currently it's hardcoded.
Interpolation of cylinder axis at points is done based on the half angle
between current and previous segment.

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

M	source/blender/editors/space_view3d/drawhair.c

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

diff --git a/source/blender/editors/space_view3d/drawhair.c b/source/blender/editors/space_view3d/drawhair.c
index fbb9b86..6dd28cc 100644
--- a/source/blender/editors/space_view3d/drawhair.c
+++ b/source/blender/editors/space_view3d/drawhair.c
@@ -107,6 +107,7 @@ bool draw_hair_system(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar, Ba
 //#define SHOW_ROOTS
 //#define SHOW_FRAMES
 //#define SHOW_SMOOTHING
+#define SHOW_CYLINDERS
 #define SHOW_CONTACTS
 
 static void draw_hair_debug_roots(HairSystem *hsys, struct DerivedMesh *dm)
@@ -269,6 +270,176 @@ static void draw_hair_debug_contacts(HAIR_SolverContact *contacts, int totcontac
 #endif
 }
 
+/* debug preview of hairs as cylinders. warning, computation here hurts a lot! */
+static void draw_hair_debug_cylinders(HairSystem *hsys, int totpoints)
+{
+#ifdef SHOW_CYLINDERS
+	HairCurve *hair;
+	HairPoint *point, *next_point;
+	int k, i, s;
+	float upvec[] = {0.0f, 0.0f, 1.0f};
+	float sidevec[] = {1.0f, 0.0f, 0.0f};
+
+	float diameter = 0.05f;
+	/* number of cylinder subdivisions */
+	int subdiv = 8;
+
+	/* vertex array variables */
+	float (*vert_data)[3];
+	unsigned int *elem_data;
+	unsigned int offset = 0;
+	unsigned int elem_offset = 0;
+
+	/* twice the subdivisions for top and bottom plus twive all for the normals */
+	int tot_verts = totpoints * 4 * subdiv;
+	int tot_elems = totpoints * 6 * subdiv;
+
+	static unsigned int hairbuf = 0;
+	static unsigned int hairelem = 0;
+
+	/* set up OpenGL code */
+	if (!hairbuf) {
+		glGenBuffers(1, &hairbuf);
+		glGenBuffers(1, &hairelem);
+	}
+	glBindBuffer(GL_ARRAY_BUFFER, hairbuf);
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, hairelem);
+	glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3 * tot_verts, NULL, GL_DYNAMIC_DRAW);
+	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int) * tot_elems, NULL, GL_DYNAMIC_DRAW);
+
+	glEnableClientState(GL_VERTEX_ARRAY);
+	glEnableClientState(GL_NORMAL_ARRAY);
+
+	glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), NULL);
+	glNormalPointer(GL_FLOAT, 6 * sizeof(float), (GLubyte *)NULL + 3 * sizeof(float));
+
+	vert_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+	elem_data = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
+
+	/* generate the data and copy to the display buffers */
+	for (hair = hsys->curves, i = 0; i < hsys->totcurves; ++hair, ++i) {
+		float normal[3];
+		float dir[3];
+		float tangent[3];
+		unsigned int cur_offset = offset / 2;
+
+		if (hair->totpoints == 1)
+			continue;
+		point = hair->points;
+		next_point = hair->points + 1;
+
+		sub_v3_v3v3(dir, next_point->co, point->co);
+		normalize_v3_v3(normal, dir);
+
+		/* calculate a tangent by cross product between z vector and normal */
+		if (fabs(dot_v3v3(normal, upvec)) < 0.99f) {
+			cross_v3_v3v3(tangent, normal, upvec);
+		}
+		else
+			cross_v3_v3v3(tangent, normal, sidevec);
+
+		for (k = 0; k < hair->totpoints - 1; ++point, ++next_point, ++k) {
+			float pivot_axis[3];
+			float new_normal[3];
+			float cosine;
+			/* first step is to compute a tangent vector to the surface and rotate around the normal */
+			sub_v3_v3v3(dir, next_point->co, point->co);
+			normalize_v3_v3(new_normal, dir);
+			cosine = dot_v3v3(new_normal, normal);
+
+			cur_offset = offset / 2;
+
+			/* if needed rotate the previous original tangent to the new frame by using cross product between current
+			 * and previous segment */
+			if (fabs(cosine) < 0.999f) {
+				float rot_quat[4];
+				float halfcosine;
+				float halfsine;
+				/* substitute by cosine of half angle because we are doing smooth-like interpolation */
+				cosine = sqrt3f(0.5 + cosine * 0.5);
+
+				/* half angle cosines needed for quaternion rotation */
+				halfcosine = sqrt3f(0.5 + cosine * 0.5);
+				halfsine = sqrt3f(0.5 - cosine * 0.5);
+
+				cross_v3_v3v3(pivot_axis, new_normal, normal);
+				normalize_v3(pivot_axis);
+
+				rot_quat[0] = halfcosine;
+				rot_quat[1] = halfsine * pivot_axis[0];
+				rot_quat[2] = halfsine * pivot_axis[1];
+				rot_quat[3] = halfsine * pivot_axis[2];
+
+				mul_qt_v3(rot_quat, tangent);
+			}
+
+			copy_v3_v3(normal, new_normal);
+
+			/* and repeat */
+			copy_v3_v3(vert_data[offset], tangent);
+			mul_v3_fl(vert_data[offset], diameter);
+			add_v3_v3(vert_data[offset++], point->co);
+			copy_v3_v3(vert_data[offset++], tangent);
+
+			/* create quaternion to rotate tangent around normal */
+			for (s = 1; s < subdiv; s++) {
+				float v_nor[3];
+				float rot_quat[4];
+				float half_angle = (M_PI * s) / subdiv;
+				float sine = sin(half_angle);
+
+				copy_v3_v3(v_nor, tangent);
+
+				rot_quat[0] = cos(half_angle);
+				rot_quat[1] = sine * normal[0];
+				rot_quat[2] = sine * normal[1];
+				rot_quat[3] = sine * normal[2];
+
+				mul_qt_v3(rot_quat, v_nor);
+				copy_v3_v3(vert_data[offset], v_nor);
+				mul_v3_fl(vert_data[offset], diameter);
+				add_v3_v3(vert_data[offset++], point->co);
+				copy_v3_v3(vert_data[offset++], v_nor);
+			}
+
+			for (s = 0; s < subdiv; s++) {
+				elem_data[elem_offset++] = cur_offset + s;
+				elem_data[elem_offset++] = cur_offset + s + subdiv;
+				elem_data[elem_offset++] = cur_offset + (s + 1) % subdiv;
+
+				elem_data[elem_offset++] = cur_offset + s + subdiv;
+				elem_data[elem_offset++] = cur_offset + (s + 1) % subdiv;
+				elem_data[elem_offset++] = cur_offset + (s + 1) % subdiv + subdiv;
+			}
+		}
+
+		/* finally add the last point */
+		for (s = 0; s < subdiv; s++) {
+			add_v3_v3v3(vert_data[offset], vert_data[offset - 2 * subdiv], dir);
+			offset++;
+			copy_v3_v3(vert_data[offset], vert_data[offset - 2 * subdiv]);
+			offset++;
+		}
+
+	}
+
+	glUnmapBuffer(GL_ARRAY_BUFFER);
+	glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
+
+	glEnable(GL_LIGHTING);
+	/* draw */
+	glShadeModel(GL_SMOOTH);
+	glDrawElements(GL_TRIANGLES, elem_offset, GL_UNSIGNED_INT, NULL);
+	glDisable(GL_LIGHTING);
+
+	glDisableClientState(GL_VERTEX_ARRAY);
+	glDisableClientState(GL_NORMAL_ARRAY);
+
+	glBindBuffer(GL_ARRAY_BUFFER, 0);
+	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+#endif
+}
+
 void draw_hair_debug_info(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar, Base *base, HairModifierData *hmd)
 {
 	RegionView3D *rv3d = ar->regiondata;
@@ -276,6 +447,7 @@ void draw_hair_debug_info(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar
 	HairSystem *hsys = hmd->hairsys;
 	HairCurve *hair;
 	int i;
+	int tot_points = 0;
 	
 	glLoadMatrixf(rv3d->viewmat);
 	glMultMatrixf(ob->obmat);
@@ -285,7 +457,9 @@ void draw_hair_debug_info(Scene *UNUSED(scene), View3D *UNUSED(v3d), ARegion *ar
 	for (hair = hsys->curves, i = 0; i < hsys->totcurves; ++hair, ++i) {
 		draw_hair_curve_debug_frames(hsys, hair);
 		draw_hair_curve_debug_smoothing(hsys, hair);
+		tot_points += (hair->totpoints > 1) ? hair->totpoints - 1 : 0;
 	}
 	
+	draw_hair_debug_cylinders(hsys, tot_points);
 	draw_hair_debug_contacts(hmd->debug_contacts, hmd->debug_totcontacts);
 }




More information about the Bf-blender-cvs mailing list