[Bf-blender-cvs] [ba8b8ec] master: Implemented internal hair pressure to prevent hair from collapsing in on itself.

Lukas Tönne noreply at git.blender.org
Tue Jan 20 09:49:11 CET 2015


Commit: ba8b8ec99870e61ba7496b3c55795e5acf9bd573
Author: Lukas Tönne
Date:   Thu Aug 28 14:55:55 2014 +0200
Branches: master
https://developer.blender.org/rBba8b8ec99870e61ba7496b3c55795e5acf9bd573

Implemented internal hair pressure to prevent hair from collapsing in
on itself.

This uses the same voxel structure as the hair smoothing algorithm.
A slightly different method was suggested in the original paper
(Volumetric Methods for Simulation and Rendering of Hair), but this is
based on directing hair based on a target density, which is another
way of implementing global goals. Our own approach is to define a
pressure threshold above which the hair is repelled in the density
gradient direction to simulate internal pressure from collisions.

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

M	release/scripts/startup/bl_ui/properties_particle.py
M	source/blender/blenkernel/intern/implicit.c
M	source/blender/makesdna/DNA_cloth_types.h
M	source/blender/makesrna/intern/rna_cloth.c

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

diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index d0b079c..d6f1095 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -316,6 +316,8 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
         sub.prop(cloth, "bending_stiffness", text="Bending")
         sub.prop(cloth, "internal_friction", slider=True)
         sub.prop(cloth, "collider_friction", slider=True)
+        sub.prop(cloth, "pressure", slider=True)
+        sub.prop(cloth, "pressure_threshold", slider=True)
 
         col = split.column()
         col.label(text="Damping:")
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 5ab1359..952140a 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1275,7 +1275,8 @@ BLI_INLINE int hair_grid_interp_weights(int res, const float gmin[3], const floa
 	return offset;
 }
 
-BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const float gmin[3], const float scale[3], const float vec[3], float *density, float velocity[3])
+BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const float gmin[3], const float scale[3], const float vec[3],
+                                      float *density, float velocity[3], float density_gradient[3])
 {
 	HairGridVert data[8];
 	float uvw[3], muvw[3];
@@ -1311,6 +1312,22 @@ BLI_INLINE void hair_grid_interpolate(const HairGridVert *grid, int res, const f
 			                         uvw[1]*( muvw[0]*data[6].velocity[k] + uvw[0]*data[7].velocity[k] ) );
 		}
 	}
+	if (density_gradient) {
+		density_gradient[0] = muvw[1] * muvw[2] * ( data[0].density - data[1].density ) +
+		                       uvw[1] * muvw[2] * ( data[2].density - data[3].density ) +
+		                      muvw[1] *  uvw[2] * ( data[4].density - data[5].density ) +
+		                       uvw[1] *  uvw[2] * ( data[6].density - data[7].density );
+		
+		density_gradient[1] = muvw[2] * muvw[0] * ( data[0].density - data[2].density ) +
+		                       uvw[2] * muvw[0] * ( data[4].density - data[6].density ) +
+		                      muvw[2] *  uvw[0] * ( data[1].density - data[3].density ) +
+		                       uvw[2] *  uvw[0] * ( data[5].density - data[7].density );
+		
+		density_gradient[2] = muvw[2] * muvw[0] * ( data[0].density - data[4].density ) +
+		                       uvw[2] * muvw[0] * ( data[1].density - data[5].density ) +
+		                      muvw[2] *  uvw[0] * ( data[2].density - data[6].density ) +
+		                       uvw[2] *  uvw[0] * ( data[3].density - data[7].density );
+	}
 }
 
 static void hair_velocity_smoothing(const HairGridVert *hairgrid, const float gmin[3], const float scale[3], float smoothfac,
@@ -1321,9 +1338,7 @@ static void hair_velocity_smoothing(const HairGridVert *hairgrid, const float gm
 	for (v = 0; v < numverts; v++) {
 		float density, velocity[3];
 		
-		hair_grid_interpolate(hairgrid, hair_grid_res, gmin, scale, lX[v], &density, velocity);
-		if (len_v3(velocity) > 10.0f)
-			printf("a bit too much\n");
+		hair_grid_interpolate(hairgrid, hair_grid_res, gmin, scale, lX[v], &density, velocity, NULL);
 		
 		sub_v3_v3(velocity, lV[v]);
 		madd_v3_v3fl(lF[v], velocity, smoothfac);
@@ -1346,6 +1361,26 @@ static void hair_velocity_collision(const HairGridVert *collgrid, const float gm
 	}
 }
 
+static void hair_pressure_force(const HairGridVert *hairgrid, const float gmin[3], const float scale[3], float pressurefac, float minpressure,
+                                lfVector *lF, lfVector *lX, unsigned int numverts)
+{
+	int v;
+	
+	/* calculate forces */
+	for (v = 0; v < numverts; v++) {
+		float density, gradient[3], gradlen;
+		
+		hair_grid_interpolate(hairgrid, hair_grid_res, gmin, scale, lX[v], &density, NULL, gradient);
+		
+		gradlen = normalize_v3(gradient) - minpressure;
+		if (gradlen < 0.0f)
+			continue;
+		mul_v3_fl(gradient, gradlen);
+		
+		madd_v3_v3fl(lF[v], gradient, pressurefac);
+	}
+}
+
 static void hair_volume_get_boundbox(lfVector *lX, unsigned int numverts, float gmin[3], float gmax[3])
 {
 	int i;
@@ -1531,6 +1566,11 @@ static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *
 	/* 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;
+	float pressfac = clmd->sim_parms->pressure;
+	float minpress = clmd->sim_parms->pressure_threshold;
+	
+	if (smoothfac <= 0.0f && collfac <= 0.0f && pressfac <= 0.0f)
+		return;
 	
 	hair_volume_get_boundbox(lX, numverts, gmin, gmax);
 	hair_grid_get_scale(hair_grid_res, gmin, gmax, scale);
@@ -1540,6 +1580,7 @@ static void hair_volume_forces(ClothModifierData *clmd, lfVector *lF, lfVector *
 	
 	hair_velocity_smoothing(hairgrid, gmin, scale, smoothfac, lF, lX, lV, numverts);
 	hair_velocity_collision(collgrid, gmin, scale, collfac, lF, lX, lV, numverts);
+	hair_pressure_force(hairgrid, gmin, scale, pressfac, minpress, lF, lX, numverts);
 	
 	MEM_freeN(hairgrid);
 	MEM_freeN(collgrid);
@@ -1645,8 +1686,7 @@ static void cloth_calc_force(ClothModifierData *clmd, float UNUSED(frame), lfVec
 
 	init_lfvector(lF, gravity, numverts);
 	
-	if (clmd->sim_parms->velocity_smooth > 0.0f || clmd->sim_parms->collider_friction > 0.0f)
-		hair_volume_forces(clmd, lF, lX, lV, numverts);
+	hair_volume_forces(clmd, lF, lX, lV, numverts);
 
 	/* multiply lF with mass matrix
 	 * force = mass * acceleration (in this case: gravity)
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 6c7d500..a9e066e 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -69,6 +69,8 @@ typedef struct ClothSimSettings {
 	float	goalspring;
 	float	goalfrict;
 	float	velocity_smooth; /* smoothing of velocities for hair */
+	float	pressure;			/* pressure factor from hair density */
+	float	pressure_threshold;	/* minimum density for hair pressure */
 	float	collider_friction; /* friction with colliders */
 	float	vel_damping; /* damp the velocity to speed up getting to the resting position */
 	float	shrink_min;  /* min amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index cecc39c..9ab6791 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -325,6 +325,18 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Collider Friction", "");
 	RNA_def_property_update(prop, 0, "rna_cloth_update");
 
+	prop = RNA_def_property(srna, "pressure", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "pressure");
+	RNA_def_property_range(prop, 0.0f, 1000.0f);
+	RNA_def_property_ui_text(prop, "Internal Pressure", "Generate outward force based on hair density");
+	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+	prop = RNA_def_property(srna, "pressure_threshold", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "pressure_threshold");
+	RNA_def_property_range(prop, 0.0f, 1000.0f);
+	RNA_def_property_ui_text(prop, "Internal Pressure Threshold", "No pressure force is generated below this pressure value");
+	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