Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanne Karhu <jhkarh@gmail.com>2010-02-26 06:24:21 +0300
committerJanne Karhu <jhkarh@gmail.com>2010-02-26 06:24:21 +0300
commitcf4ba30f79991e9804a6fb2b8c746b50e5cf1878 (patch)
treee1c5426dba141c4693157e7d605c19aae12c825d /source/blender
parent59e2fdbf31380fc8bf8c0543344233bd2bee7133 (diff)
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.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/intern/implicit.c121
-rw-r--r--source/blender/makesdna/DNA_cloth_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c6
3 files changed, 113 insertions, 17 deletions
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index a60fbae0f2d..6912a65886a 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1408,19 +1408,29 @@ typedef struct HairGridVert {
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 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX,
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 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX,
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 @@ static void hair_velocity_smoothing(float smoothfac, lfVector *lF, lfVector *lX,
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 );
-
- /* 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]);
+ 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);
+
+ 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 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF,
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 @@ static void cloth_calc_force(ClothModifierData *clmd, float frame, lfVector *lF,
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);
}
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 06ace29dbfe..8e04107afe0 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -66,6 +66,8 @@ typedef struct ClothSimSettings
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 @@ typedef struct ClothSimSettings
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;
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 961e0708adc..4ecb93eb1d6 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -225,6 +225,12 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
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);