[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [27149] trunk/blender: Few small hair dynamics goodies:

Janne Karhu jhkarh at gmail.com
Fri Feb 26 04:24:25 CET 2010


Revision: 27149
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=27149
Author:   jhk
Date:     2010-02-26 04:24:21 +0100 (Fri, 26 Feb 2010)

Log Message:
-----------
Few small hair dynamics goodies:
* Effectors now work with hair dynamics.
* Hair dynamics has a new "Collider Friction" parameter that works similarly to internal friction except now all collision objects effect the hair velocity. Useful for quick'n'dirty interaction with objects as the calculations are really fast, but doesn't really take away the need for proper hair-object collisions.

Modified Paths:
--------------
    trunk/blender/release/scripts/ui/properties_particle.py
    trunk/blender/source/blender/blenkernel/intern/implicit.c
    trunk/blender/source/blender/makesdna/DNA_cloth_types.h
    trunk/blender/source/blender/makesrna/intern/rna_cloth.c

Modified: trunk/blender/release/scripts/ui/properties_particle.py
===================================================================
--- trunk/blender/release/scripts/ui/properties_particle.py	2010-02-26 02:37:31 UTC (rev 27148)
+++ trunk/blender/release/scripts/ui/properties_particle.py	2010-02-26 03:24:21 UTC (rev 27149)
@@ -231,6 +231,7 @@
         sub.prop(cloth, "mass")
         sub.prop(cloth, "bending_stiffness", text="Bending")
         sub.prop(cloth, "internal_friction", slider=True)
+        sub.prop(cloth, "collider_friction", slider=True)
 
         col = split.column()
 

Modified: trunk/blender/source/blender/blenkernel/intern/implicit.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/implicit.c	2010-02-26 02:37:31 UTC (rev 27148)
+++ trunk/blender/source/blender/blenkernel/intern/implicit.c	2010-02-26 03:24:21 UTC (rev 27149)
@@ -1408,19 +1408,29 @@
 	float velocity[3];
 	float density;
 } HairGridVert;
+#define HAIR_GRID_INDEX(vec, min, max, axis) (int)( (vec[axis] - min[axis]) / (max[axis] - min[axis]) * 9.99f );
 /* Smoothing of hair velocities:
  * adapted from
 		Volumetric Methods for Simulation and Rendering of Hair
 		by Lena Petrovic, Mark Henne and John Anderson
  *		Pixar Technical Memo #06-08, Pixar Animation Studios
  */
-static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX, lfVector *lV, int numverts)
+static void hair_velocity_smoothing(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, int numverts)
 {
-	/* TODO: this is an initial implementation and should be made much better in due time */
+	/* TODO: This is an initial implementation and should be made much better in due time.
+	 * What should at least be implemented is a grid size parameter and a smoothing kernel
+	 * for bigger grids.
+	 */
 
 	/* 10x10x10 grid gives nice initial results */
 	HairGridVert grid[10][10][10];
+	HairGridVert colg[10][10][10];
+	ListBase *colliders = get_collider_cache(clmd->scene, NULL);
+	ColliderCache *col = NULL;
 	float gmin[3], gmax[3], density;
+	/* 2.0f is an experimental value that seems to give good results */
+	float smoothfac = 2.0f * clmd->sim_parms->velocity_smooth;
+	float collfac = 2.0f * clmd->sim_parms->collider_friction;
 	int	v = 0;
 	int	i = 0;
 	int	j = 0;
@@ -1439,15 +1449,20 @@
 				grid[i][j][k].velocity[1] = 0.0f;
 				grid[i][j][k].velocity[2] = 0.0f;
 				grid[i][j][k].density = 0.0f;
+
+				colg[i][j][k].velocity[0] = 0.0f;
+				colg[i][j][k].velocity[1] = 0.0f;
+				colg[i][j][k].velocity[2] = 0.0f;
+				colg[i][j][k].density = 0.0f;
 			}
 		}
 	}
 
 	/* gather velocities & density */
-	for(v = 0; v < numverts; v++) {
-		i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f );
-		j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f );
-		k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f );
+	if(smoothfac > 0.0f) for(v = 0; v < numverts; v++) {
+		i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0);
+		j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1);
+		k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2);
 
 		grid[i][j][k].velocity[0] += lV[v][0];
 		grid[i][j][k].velocity[1] += lV[v][1];
@@ -1455,6 +1470,36 @@
 		grid[i][j][k].density += 1.0f;
 	}
 
+	/* gather colliders */
+	if(colliders && collfac > 0.0f) for(col = colliders->first; col; col = col->next)
+	{
+		MVert *loc0 = col->collmd->x;
+		MVert *loc1 = col->collmd->xnew;
+		float vel[3];
+
+		for(v=0; v<col->collmd->numverts; v++, loc0++, loc1++) {
+			i = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 0);
+
+			if(i>=0 && i<10) {
+				j = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 1);
+
+				if(j>=0 && j<10) {
+					k = HAIR_GRID_INDEX(loc1->co, gmin, gmax, 2);
+
+					if(k>=0 && k<10) {
+						VECSUB(vel, loc1->co, loc0->co);
+
+						colg[i][j][k].velocity[0] += vel[0];
+						colg[i][j][k].velocity[1] += vel[1];
+						colg[i][j][k].velocity[2] += vel[2];
+						colg[i][j][k].density += 1.0;
+					}
+				}
+			}
+		}
+	}
+	
+
 	/* divide velocity with density */
 	for(i = 0; i < 10; i++) {
 		for(j = 0; j < 10; j++) {
@@ -1465,21 +1510,35 @@
 					grid[i][j][k].velocity[1] /= density;
 					grid[i][j][k].velocity[2] /= density;
 				}
+
+				density = colg[i][j][k].density;
+				if(density > 0.0f) {
+					colg[i][j][k].velocity[0] /= density;
+					colg[i][j][k].velocity[1] /= density;
+					colg[i][j][k].velocity[2] /= density;
+				}
 			}
 		}
 	}
 
 	/* calculate forces */
 	for(v = 0; v < numverts; v++) {
-		i = (int)( (lX[v][0] - gmin[0]) / (gmax[0] - gmin[0]) * 9.99f );
-		j = (int)( (lX[v][1] - gmin[1]) / (gmax[1] - gmin[1]) * 9.99f );
-		k = (int)( (lX[v][2] - gmin[2]) / (gmax[2] - gmin[2]) * 9.99f );
+		i = HAIR_GRID_INDEX(lX[v], gmin, gmax, 0);
+		j = HAIR_GRID_INDEX(lX[v], gmin, gmax, 1);
+		k = HAIR_GRID_INDEX(lX[v], gmin, gmax, 2);
 
-		/* 2.0f is an experimental value that seems to give good results */
-		lF[v][0] += 2.0f * smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]);
-		lF[v][1] += 2.0f * smoothfac * (grid[i][j][k].velocity[1] - lV[v][1]);
-		lF[v][2] += 2.0f * smoothfac * (grid[i][j][k].velocity[2] - lV[v][2]);
+		lF[v][0] += smoothfac * (grid[i][j][k].velocity[0] - lV[v][0]);
+		lF[v][1] += smoothfac * (grid[i][j][k].velocity[1] - lV[v][1]);
+		lF[v][2] += smoothfac * (grid[i][j][k].velocity[2] - lV[v][2]);
+
+		if(colg[i][j][k].density > 0.0f) {
+			lF[v][0] += collfac * (colg[i][j][k].velocity[0] - lV[v][0]);
+			lF[v][1] += collfac * (colg[i][j][k].velocity[1] - lV[v][1]);
+			lF[v][2] += collfac * (colg[i][j][k].velocity[2] - lV[v][2]);
+		}
 	}
+
+	free_collider_cache(&colliders);
 }
 static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M)
 {
@@ -1508,8 +1567,8 @@
 
 	init_lfvector(lF, gravity, numverts);
 	
-	if(clmd->sim_parms->velocity_smooth > 0.0f)
-		hair_velocity_smoothing(clmd->sim_parms->velocity_smooth, lF, lX, lV, numverts);
+	if(clmd->sim_parms->velocity_smooth > 0.0f || clmd->sim_parms->collider_friction > 0.0f)
+		hair_velocity_smoothing(clmd, lF, lX, lV, numverts);
 
 	/* multiply lF with mass matrix
 	// force = mass * acceleration (in this case: gravity)
@@ -1579,6 +1638,36 @@
 				VECADDS(lF[mfaces[i].v4], lF[mfaces[i].v4], tmp, factor);
 			}
 		}
+
+		/* Hair has only edges */
+		if(cloth->numfaces == 0) {
+			ClothSpring *spring;
+			float edgevec[3]={0,0,0}; //edge vector
+			float edgeunnormal[3]={0,0,0}; // not-normalized-edge normal
+			float tmp[3]={0,0,0};
+			float factor = 0.01;
+
+			search = cloth->springs;
+			while(search) {
+				spring = search->link;
+				
+				if(spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) {
+					VECSUB(edgevec, (float*)lX[spring->ij], (float*)lX[spring->kl]);
+
+					project_v3_v3v3(tmp, winvec[spring->ij], edgevec);
+					VECSUB(edgeunnormal, winvec[spring->ij], tmp);
+					/* hair doesn't stretch too much so we can use restlen pretty safely */
+					VECADDS(lF[spring->ij], lF[spring->ij], edgeunnormal, spring->restlen * factor);
+
+					project_v3_v3v3(tmp, winvec[spring->kl], edgevec);
+					VECSUB(edgeunnormal, winvec[spring->kl], tmp);
+					VECADDS(lF[spring->kl], lF[spring->kl], edgeunnormal, spring->restlen * factor);
+				}
+
+				search = search->next;
+			}
+		}
+
 		del_lfvector(winvec);
 	}
 		

Modified: trunk/blender/source/blender/makesdna/DNA_cloth_types.h
===================================================================
--- trunk/blender/source/blender/makesdna/DNA_cloth_types.h	2010-02-26 02:37:31 UTC (rev 27148)
+++ trunk/blender/source/blender/makesdna/DNA_cloth_types.h	2010-02-26 03:24:21 UTC (rev 27149)
@@ -66,6 +66,8 @@
 	float	goalspring;
 	float	goalfrict;
 	float	velocity_smooth; /* smoothing of velocities for hair */
+	float	collider_friction; /* friction with colliders */
+
 	int 	stepsPerFrame;	/* Number of time steps per frame.		*/
 	int	flags;		/* flags, see CSIMSETT_FLAGS enum above.	*/
 	int	preroll;	/* How many frames of simulation to do before we start.	*/
@@ -76,7 +78,6 @@
 	short	vgroup_struct;  /* vertex group for scaling structural stiffness */
 	short	presets; /* used for presets on GUI */
  	short 	reset;
-	int		pad;
 
 	struct EffectorWeights *effector_weights;
 } ClothSimSettings;

Modified: trunk/blender/source/blender/makesrna/intern/rna_cloth.c
===================================================================
--- trunk/blender/source/blender/makesrna/intern/rna_cloth.c	2010-02-26 02:37:31 UTC (rev 27148)
+++ trunk/blender/source/blender/makesrna/intern/rna_cloth.c	2010-02-26 03:24:21 UTC (rev 27149)
@@ -225,6 +225,12 @@
 	RNA_def_property_ui_text(prop, "Internal Friction", "");
 	RNA_def_property_update(prop, 0, "rna_cloth_update");
 
+	prop= RNA_def_property(srna, "collider_friction", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "collider_friction");
+	RNA_def_property_range(prop, 0.0f, 1.0f);
+	RNA_def_property_ui_text(prop, "Collider Friction", "");
+	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
 	/* mass */
 
 	prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);





More information about the Bf-blender-cvs mailing list