[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23116] branches/blender2.5/blender: Hair dynamics with cloth simulation

Janne Karhu jhkarh at utu.fi
Fri Sep 11 00:32:33 CEST 2009


Revision: 23116
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23116
Author:   jhk
Date:     2009-09-11 00:32:33 +0200 (Fri, 11 Sep 2009)

Log Message:
-----------
Hair dynamics with cloth simulation
- Hair dynamics have their own panel in particle settings with the settings from cloth panel that apply to hair.
- Basic internal friction force to quickly emulate self collisions and volume preservation. (Still very early code, but gives some idea of what's possible).
- Softbody simulation is no longer used for hair.
	* Old files with sb dynamics should just load the hair without dynamics so new dynamics can be applied.
	* Invasion of particles exceptions in sb code is finally over.
- Collisions with other objects are disabled for now and will be worked out in the future.

Other changes/fixes:
- Particle mode editing flag wasn't saved properly.
- Some old files with edited hair didn't load correctly.
- Disabled delete & specials menu in particle mode for non-hair editing.
- Fixed yet one more cloth & softbody pointcache update issue.
- Disconnect/connect hair now uses only the deformed mesh so it works correctly also for subsurfed emitters.
- Hair editing now updates correctly with a moving emitter.

Modified Paths:
--------------
    branches/blender2.5/blender/release/ui/buttons_particle.py
    branches/blender2.5/blender/source/blender/blenkernel/BKE_cloth.h
    branches/blender2.5/blender/source/blender/blenkernel/BKE_particle.h
    branches/blender2.5/blender/source/blender/blenkernel/intern/cloth.c
    branches/blender2.5/blender/source/blender/blenkernel/intern/implicit.c
    branches/blender2.5/blender/source/blender/blenkernel/intern/object.c
    branches/blender2.5/blender/source/blender/blenkernel/intern/particle.c
    branches/blender2.5/blender/source/blender/blenkernel/intern/particle_system.c
    branches/blender2.5/blender/source/blender/blenkernel/intern/pointcache.c
    branches/blender2.5/blender/source/blender/blenkernel/intern/softbody.c
    branches/blender2.5/blender/source/blender/blenloader/intern/readfile.c
    branches/blender2.5/blender/source/blender/blenloader/intern/writefile.c
    branches/blender2.5/blender/source/blender/editors/physics/editparticle.c
    branches/blender2.5/blender/source/blender/editors/space_buttons/buttons_ops.c
    branches/blender2.5/blender/source/blender/editors/space_view3d/drawobject.c
    branches/blender2.5/blender/source/blender/makesdna/DNA_cloth_types.h
    branches/blender2.5/blender/source/blender/makesdna/DNA_object_force.h
    branches/blender2.5/blender/source/blender/makesdna/DNA_particle_types.h
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_cloth.c
    branches/blender2.5/blender/source/blender/makesrna/intern/rna_particle.c

Modified: branches/blender2.5/blender/release/ui/buttons_particle.py
===================================================================
--- branches/blender2.5/blender/release/ui/buttons_particle.py	2009-09-10 20:41:18 UTC (rev 23115)
+++ branches/blender2.5/blender/release/ui/buttons_particle.py	2009-09-10 22:32:33 UTC (rev 23116)
@@ -154,8 +154,10 @@
 					if psys.edited==True:
 						if psys.global_hair:
 							layout.itemO("particle.connect_hair")
+							layout.itemL(text="Hair is disconnected.")
 						else:
 							layout.itemO("particle.disconnect_hair")
+							layout.itemL(text="")
 				elif part.type=='REACTOR':
 					split.enabled = particle_panel_enabled(psys)
 					split.itemR(psys, "reactor_target_object")
@@ -212,6 +214,53 @@
 			elif part.distribution=='GRID':
 				row.itemR(part, "grid_resolution")
 
+class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel):
+	__label__ = "Hair dynamics"
+	__default_closed__ = True
+	
+	def poll(self, context):
+		psys = context.particle_system
+		if psys==None:	return False
+		if psys.settings==None:  return False
+		return psys.settings.type == 'HAIR'
+		
+	def draw_header(self, context):
+		#cloth = context.cloth.collision_settings
+		
+		#self.layout.active = cloth_panel_enabled(context.cloth)
+		#self.layout.itemR(cloth, "enable_collision", text="")
+		psys = context.particle_system
+		self.layout.itemR(psys, "hair_dynamics", text="")
+		
+	def draw(self, context):
+		layout = self.layout
+
+		psys = context.particle_system
+		part = psys.settings
+		cloth = psys.cloth.settings
+		
+		layout.enabled = psys.hair_dynamics
+		
+		split = layout.split()
+			
+		col = split.column()
+		col.itemL(text="Quality:")
+		col.itemR(cloth, "quality", text="Steps",slider=True)
+		col.itemL(text="Gravity:")
+		col.itemR(cloth, "gravity", text="")
+		
+		col = split.column()
+		col.itemL(text="Material:")
+		sub = col.column(align=True)
+		sub.itemR(cloth, "pin_stiffness", text="Stiffness")
+		sub.itemR(cloth, "mass")
+		col.itemL(text="Damping:")
+		sub = col.column(align=True)
+		sub.itemR(cloth, "spring_damping", text="Spring")
+		sub.itemR(cloth, "air_damping", text="Air")
+		
+		layout.itemR(cloth, "internal_friction", slider="True")
+				
 class PARTICLE_PT_cache(ParticleButtonsPanel):
 	__label__ = "Cache"
 	__default_closed__ = True
@@ -223,14 +272,14 @@
 		phystype = psys.settings.physics_type
 		if phystype == 'NO' or phystype == 'KEYED':
 			return False
-		return psys.settings.type in ('EMITTER', 'REACTOR')
+		return psys.settings.type in ('EMITTER', 'REACTOR') or (psys.settings.type == 'HAIR' and psys.hair_dynamics)
 
 	def draw(self, context):
 		layout = self.layout
 
 		psys = context.particle_system
 		
-		point_cache_ui(self, psys.point_cache, particle_panel_enabled(psys), 1, 0)
+		point_cache_ui(self, psys.point_cache, particle_panel_enabled(psys), not psys.hair_dynamics, 0)
 
 class PARTICLE_PT_initial(ParticleButtonsPanel):
 	__label__ = "Velocity"
@@ -897,6 +946,7 @@
 		#row.itemR(psys, "vertex_group_field_negate", text="")
 		
 bpy.types.register(PARTICLE_PT_particles)
+bpy.types.register(PARTICLE_PT_hair_dynamics)
 bpy.types.register(PARTICLE_PT_cache)
 bpy.types.register(PARTICLE_PT_emission)
 bpy.types.register(PARTICLE_PT_initial)

Modified: branches/blender2.5/blender/source/blender/blenkernel/BKE_cloth.h
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/BKE_cloth.h	2009-09-10 20:41:18 UTC (rev 23115)
+++ branches/blender2.5/blender/source/blender/blenkernel/BKE_cloth.h	2009-09-10 22:32:33 UTC (rev 23116)
@@ -176,7 +176,8 @@
 	CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), 	// we have goals enabled
 	CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled
 	CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */
-	CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12)	/* edit cache in editmode */
+	CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12),	/* edit cache in editmode */
+	CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13) /* don't allow spring compression */
 } CLOTH_SIMSETTINGS_FLAGS;
 
 /* COLLISION FLAGS */

Modified: branches/blender2.5/blender/source/blender/blenkernel/BKE_particle.h
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/BKE_particle.h	2009-09-10 20:41:18 UTC (rev 23115)
+++ branches/blender2.5/blender/source/blender/blenkernel/BKE_particle.h	2009-09-10 22:32:33 UTC (rev 23116)
@@ -208,7 +208,7 @@
 void psys_free_settings(struct ParticleSettings *part);
 void free_child_path_cache(struct ParticleSystem *psys);
 void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
-void free_hair(struct ParticleSystem *psys, int softbody);
+void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics);
 void free_keyed_keys(struct ParticleSystem *psys);
 void psys_free_particles(struct ParticleSystem *psys);
 void psys_free(struct Object * ob, struct ParticleSystem * psys);

Modified: branches/blender2.5/blender/source/blender/blenkernel/intern/cloth.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/intern/cloth.c	2009-09-10 20:41:18 UTC (rev 23115)
+++ branches/blender2.5/blender/source/blender/blenkernel/intern/cloth.c	2009-09-10 22:32:33 UTC (rev 23116)
@@ -496,9 +496,11 @@
 	if(!do_init_cloth(ob, clmd, result, framenr))
 		return result;
 
-	if(framenr == startframe && cache->flag & PTCACHE_REDO_NEEDED) {
+	if(framenr == startframe) {
 		BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+		do_init_cloth(ob, clmd, result, framenr);
 		cache->simframe= framenr;
+		cache->flag |= PTCACHE_SIMULATION_VALID;
 		cache->flag &= ~PTCACHE_REDO_NEEDED;
 		return result;
 	}
@@ -530,37 +532,26 @@
 		return result;
 	}
 
-	if(framenr == startframe) {
-		implicit_set_positions(clmd);
+	/* if on second frame, write cache for first frame */
+	if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
+		BKE_ptcache_write_cache(&pid, startframe);
 
-		cache->simframe= framenr;
-		cache->flag |= PTCACHE_SIMULATION_VALID;
+	clmd->sim_parms->timescale *= framenr - cache->simframe;
 
-		/* don't write cache on first frame, but on second frame write
-		 * cache for frame 1 and 2 */
-	}
-	else {
-		/* if on second frame, write cache for first frame */
-		if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
-			BKE_ptcache_write_cache(&pid, startframe);
+	/* do simulation */
+	cache->flag |= PTCACHE_SIMULATION_VALID;
+	cache->simframe= framenr;
 
-		clmd->sim_parms->timescale *= framenr - cache->simframe;
-
-		/* do simulation */
-		cache->flag |= PTCACHE_SIMULATION_VALID;
-		cache->simframe= framenr;
-
-		if(!do_step_cloth(ob, clmd, result, framenr)) {
-			cache->flag &= ~PTCACHE_SIMULATION_VALID;
-			cache->simframe= 0;
-			cache->last_exact= 0;
-		}
-		else
-			BKE_ptcache_write_cache(&pid, framenr);
-
-		cloth_to_object (ob, clmd, result);
+	if(!do_step_cloth(ob, clmd, result, framenr)) {
+		cache->flag &= ~PTCACHE_SIMULATION_VALID;
+		cache->simframe= 0;
+		cache->last_exact= 0;
 	}
+	else
+		BKE_ptcache_write_cache(&pid, framenr);
 
+	cloth_to_object (ob, clmd, result);
+
 	return result;
 }
 

Modified: branches/blender2.5/blender/source/blender/blenkernel/intern/implicit.c
===================================================================
--- branches/blender2.5/blender/source/blender/blenkernel/intern/implicit.c	2009-09-10 20:41:18 UTC (rev 23115)
+++ branches/blender2.5/blender/source/blender/blenkernel/intern/implicit.c	2009-09-10 22:32:33 UTC (rev 23116)
@@ -1183,7 +1183,8 @@
 	//return  ( (I-outerprod(dir,dir))*Min(1.0f,rest/length) - I) * -k;
 	mul_fvectorT_fvector(to, dir, dir);
 	sub_fmatrix_fmatrix(to, I, to);
-	mul_fmatrix_S(to, (((L/length)> 1.0f) ? (1.0f): (L/length))); 
+
+	mul_fmatrix_S(to, (L/length)); 
 	sub_fmatrix_fmatrix(to, to, I);
 	mul_fmatrix_S(to, -k);
 }
@@ -1218,6 +1219,8 @@
 	float nulldfdx[3][3]={ {0,0,0}, {0,0,0}, {0,0,0}};
 	
 	float scaling = 0.0;
+
+	int no_compress = clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
 	
 	VECCOPY(s->f, nullf);
 	cp_fmatrix(s->dfdx, nulldfdx);
@@ -1254,7 +1257,7 @@
 	// calculate force of structural + shear springs
 	if((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR))
 	{
-		if(length > L) // only on elonglation
+		if(length > L || no_compress)
 		{
 			s->flags |= CLOTH_SPRING_FLAG_NEEDED;
 			
@@ -1393,6 +1396,84 @@
 	return (INPR(wind, vertexnormal));
 }
 
+typedef struct HairGridVert {
+	float velocity[3];
+	float density;
+} HairGridVert;
+/* 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)
+{
+	/* TODO: this is an initial implementation and should be made much better in due time */
+
+	/* 10x10x10 grid gives nice initial results */
+	HairGridVert grid[10][10][10];
+	float gmin[3], gmax[3], density;
+	int	v = 0;
+	int	i = 0;
+	int	j = 0;
+	int	k = 0;
+	lfVector temp;
+
+	INIT_MINMAX(gmin, gmax);
+
+	for(i = 0; i < numverts; i++)
+		DO_MINMAX(lX[i], gmin, gmax);
+
+	/* initialize grid */
+	for(i = 0; i < 10; i++) {
+		for(j = 0; j < 10; j++) {
+			for(k = 0; k < 10; k++) {
+				grid[i][j][k].velocity[0] = 0.0f;
+				grid[i][j][k].velocity[1] = 0.0f;
+				grid[i][j][k].velocity[2] = 0.0f;
+				grid[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 );
+
+		grid[i][j][k].velocity[0] += lV[v][0];
+		grid[i][j][k].velocity[1] += lV[v][1];
+		grid[i][j][k].velocity[2] += lV[v][2];
+		grid[i][j][k].density += 1.0f;
+	}
+
+	/* divide velocity with density */
+	for(i = 0; i < 10; i++) {
+		for(j = 0; j < 10; j++) {
+			for(k = 0; k < 10; k++) {
+				density = grid[i][j][k].density;
+				if(density > 0.0f) {
+					grid[i][j][k].velocity[0] /= density;
+					grid[i][j][k].velocity[1] /= density;
+					grid[i][j][k].velocity[2] /= density;
+				}
+			}

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list