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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to