Commit: 42a02c61e863a187da9b35887fbb0e2cb40aa19c
Author: Lukas Tönne
Date:   Thu Aug 28 14:55:55 2014 +0200
Branches: hair_immediate_fixes
https://developer.blender.org/rB42a02c61e863a187da9b35887fbb0e2cb40aa19c

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 30fc3a9..7124271 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -292,6 +292,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 488ca18..db77190 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1469,7 +1469,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];
@@ -1505,6 +1506,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,
@@ -1515,9 +1532,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);
@@ -1540,6 +1555,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;
@@ -1725,6 +1760,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);
@@ -1734,6 +1774,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);
@@ -1839,8 +1880,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);

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

Reply via email to