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);
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs