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>2009-09-11 02:32:33 +0400
committerJanne Karhu <jhkarh@gmail.com>2009-09-11 02:32:33 +0400
commite9587a89faf33aa0c1383b59f006be4cc7443a5a (patch)
treebfa5264b90b75a58912448eb3d589b188cbd0472 /source/blender/blenkernel
parentfcc5884c252ae10b07a6f8c5e1c5990e9aa4e7c5 (diff)
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.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_cloth.h3
-rw-r--r--source/blender/blenkernel/BKE_particle.h2
-rw-r--r--source/blender/blenkernel/intern/cloth.c45
-rw-r--r--source/blender/blenkernel/intern/implicit.c88
-rw-r--r--source/blender/blenkernel/intern/object.c7
-rw-r--r--source/blender/blenkernel/intern/particle.c209
-rw-r--r--source/blender/blenkernel/intern/particle_system.c305
-rw-r--r--source/blender/blenkernel/intern/pointcache.c33
-rw-r--r--source/blender/blenkernel/intern/softbody.c307
9 files changed, 484 insertions, 515 deletions
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index bc4585106e6..e5b3adbd0c0 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -176,7 +176,8 @@ typedef enum
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 */
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 15896477a6a..c22778f5a30 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -208,7 +208,7 @@ void psys_free_boid_rules(struct ListBase *list);
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);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 8be8df8e63b..d25c329f49f 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -496,9 +496,11 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
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,36 +532,25 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
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;
}
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index fc5213d5532..0bce71b57eb 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1183,7 +1183,8 @@ DO_INLINE void dfdx_spring(float to[3][3], float dir[3],float length,float L,fl
//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 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
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 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s,
// 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 @@ float calculateVertexWindForce(float wind[3], float vertexnormal[3])
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;
+ }
+ }
+ }
+ }
+
+ /* 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]);
+ }
+}
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)
{
/* Collect forces and derivatives: F,dFdX,dFdV */
@@ -1416,6 +1497,9 @@ 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);
+
/* multiply lF with mass matrix
// force = mass * acceleration (in this case: gravity)
*/
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index f10226f6f6b..a0004aaae49 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1113,9 +1113,10 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
}
}
- if(psys->soft) {
- psysn->soft= copy_softbody(psys->soft);
- psysn->soft->particles = psysn;
+ if(psys->clmd) {
+ ClothModifierData *nclmd = modifier_new(eModifierType_Cloth);
+ modifier_copyData((ModifierData*)psys->clmd, (ModifierData*)nclmd);
+ psys->hair_in_dm = psys->hair_out_dm = NULL;
}
BLI_duplicatelist(&psysn->targets, &psys->targets);
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 0ba2f357a1f..3b2125a7973 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -366,7 +366,7 @@ void psys_free_settings(ParticleSettings *part)
boid_free_settings(part->boids);
}
-void free_hair(ParticleSystem *psys, int softbody)
+void free_hair(Object *ob, ParticleSystem *psys, int dynamics)
{
PARTICLE_P;
@@ -382,10 +382,28 @@ void free_hair(ParticleSystem *psys, int softbody)
psys->flag &= ~PSYS_HAIR_DONE;
- if(softbody && psys->soft) {
- sbFree(psys->soft);
- psys->soft = NULL;
+ if(psys->clmd) {
+ if(dynamics) {
+ BKE_ptcache_free_list(&psys->ptcaches);
+ psys->clmd->point_cache = psys->pointcache = NULL;
+ psys->clmd->ptcaches.first = psys->clmd->ptcaches.first = NULL;
+
+ modifier_free((ModifierData*)psys->clmd);
+
+ psys->clmd = NULL;
+ }
+ else {
+ cloth_free_modifier(ob, psys->clmd);
+ }
}
+
+ if(psys->hair_in_dm)
+ psys->hair_in_dm->release(psys->hair_in_dm);
+ psys->hair_in_dm = NULL;
+
+ if(psys->hair_out_dm)
+ psys->hair_out_dm->release(psys->hair_out_dm);
+ psys->hair_out_dm = NULL;
}
void free_keyed_keys(ParticleSystem *psys)
{
@@ -468,6 +486,8 @@ void psys_free(Object *ob, ParticleSystem * psys)
psys_free_path_cache(psys, NULL);
+ free_hair(ob, psys, 1);
+
psys_free_particles(psys);
if(psys->edit && psys->free_edit)
@@ -976,11 +996,11 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic
typedef struct ParticleInterpolationData {
HairKey *hkey[2];
+ DerivedMesh *dm;
+ MVert *mvert[2];
+
int keyed;
ParticleKey *kkey[2];
-
- SoftBody *soft;
- BodyPoint *bp[2];
PointCache *cache;
@@ -1049,12 +1069,12 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic
pind->birthtime = key->time;
pind->dietime = (key + pa->totkey - 1)->time;
- }
- //if(pind->soft) {
- // pind->bp[0] = pind->soft->bpoint + pa->bpi;
- // pind->bp[1] = pind->soft->bpoint + pa->bpi + 1;
- //}
+ if(pind->dm) {
+ pind->mvert[0] = CDDM_get_vert(pind->dm, pa->hair_index);
+ pind->mvert[1] = pind->mvert[0] + 1;
+ }
+ }
}
static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey)
{
@@ -1069,9 +1089,10 @@ static void hair_to_particle(ParticleKey *key, HairKey *hkey)
VECCOPY(key->co, hkey->co);
key->time = hkey->time;
}
-static void bp_to_particle(ParticleKey *key, BodyPoint *bp, HairKey *hkey)
+
+static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey)
{
- VECCOPY(key->co, bp->pos);
+ VECCOPY(key->co, mvert->co);
key->time = hkey->time;
}
@@ -1145,7 +1166,7 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
while(pind->hkey[1]->time < real_t) {
pind->hkey[1]++;
- pind->bp[1]++;
+ pind->mvert[1]++;
}
pind->hkey[0] = pind->hkey[1] - 1;
@@ -1156,10 +1177,10 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
edit_to_particle(keys + 1, pind->ekey[0]);
edit_to_particle(keys + 2, pind->ekey[1]);
}
- else if(pind->soft) {
- pind->bp[0] = pind->bp[1] - 1;
- bp_to_particle(keys + 1, pind->bp[0], pind->hkey[0]);
- bp_to_particle(keys + 2, pind->bp[1], pind->hkey[1]);
+ else if(pind->dm) {
+ pind->mvert[0] = pind->mvert[1] - 1;
+ mvert_to_particle(keys + 1, pind->mvert[0], pind->hkey[0]);
+ mvert_to_particle(keys + 2, pind->mvert[1], pind->hkey[1]);
}
else if(pind->keyed) {
memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey));
@@ -1181,11 +1202,11 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
else
edit_to_particle(keys, pind->ekey[0]);
}
- else if(pind->soft) {
+ else if(pind->dm) {
if(pind->hkey[0] != pa->hair)
- bp_to_particle(keys, pind->bp[0] - 1, pind->hkey[0] - 1);
+ mvert_to_particle(keys, pind->mvert[0] - 1, pind->hkey[0] - 1);
else
- bp_to_particle(keys, pind->bp[0], pind->hkey[0]);
+ mvert_to_particle(keys, pind->mvert[0], pind->hkey[0]);
}
else {
if(pind->hkey[0] != pa->hair)
@@ -1200,11 +1221,11 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData
else
edit_to_particle(keys + 3, pind->ekey[1]);
}
- else if(pind->soft) {
+ else if(pind->dm) {
if(pind->hkey[1] != pa->hair + pa->totkey - 1)
- bp_to_particle(keys + 3, pind->bp[1] + 1, pind->hkey[1] + 1);
+ mvert_to_particle(keys + 3, pind->mvert[1] + 1, pind->hkey[1] + 1);
else
- bp_to_particle(keys + 3, pind->bp[1], pind->hkey[1]);
+ mvert_to_particle(keys + 3, pind->mvert[1], pind->hkey[1]);
}
else {
if(pind->hkey[1] != pa->hair + pa->totkey - 1)
@@ -2110,7 +2131,11 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup)
{
float *vg=0;
- if(psys->vgroup[vgroup]){
+ if(vgroup < 0) {
+ /* hair dynamics pinning vgroup */
+
+ }
+ else if(psys->vgroup[vgroup]){
MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
if(dvert){
int totvert=dm->getNumVerts(dm), i;
@@ -2639,12 +2664,11 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
ParticleSettings *part = psys->part;
ParticleEditSettings *pset = &scene->toolsettings->particle;
+
+ DerivedMesh *hair_dm = psys->hair_out_dm;
ParticleData *pa = psys->particles;
ParticleKey result;
-
- SoftBody *soft = NULL;
- BodyPoint *bp[2] = {NULL, NULL};
Material *ma;
ParticleInterpolationData pind;
@@ -2663,7 +2687,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
int keyed, baked;
/* we don't have anything valid to create paths from so let's quit here */
- if(!(psys->flag & PSYS_HAIR_DONE) && !(psys->flag & PSYS_KEYED) && !(psys->pointcache->flag & PTCACHE_BAKED))
+ if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0)
return;
if(psys_in_edit_mode(scene, psys))
@@ -2673,24 +2697,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
BLI_srandom(psys->seed);
keyed = psys->flag & PSYS_KEYED;
- baked = psys->pointcache->flag & PTCACHE_BAKED;
+ baked = !hair_dm && psys->pointcache->flag & PTCACHE_BAKED;
/* clear out old and create new empty path cache */
psys_free_path_cache(psys, psys->edit);
cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1);
- if(psys->soft && psys->softflag & OB_SB_ENABLE) {
- soft = psys->soft;
- if(!soft->bpoint)
- soft= NULL;
- }
-
psys->lattice = psys_get_lattice(scene, ob, psys);
ma= give_current_material(ob, psys->part->omat);
if(ma && (psys->part->draw & PART_DRAW_MAT_COL))
VECCOPY(col, &ma->r)
- if(psys->part->from!=PART_FROM_PARTICLE) {
+ if(psys->part->from!=PART_FROM_PARTICLE && !(psys->flag & PSYS_GLOBAL_HAIR)) {
if(!(psys->part->flag & PART_CHILD_EFFECT))
vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR);
@@ -2700,11 +2718,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
/*---first main loop: create all actual particles' paths---*/
for(i=0; i<totpart; i++, pa++){
- if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) {
- if(soft)
- bp[0] += pa->totkey; /* TODO use of initialized value? */
+ if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST)
continue;
- }
if(!psys->totchild) {
BLI_srandom(psys->seed + i);
@@ -2715,9 +2730,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
pind.keyed = keyed;
pind.cache = baked ? psys->pointcache : NULL;
- pind.soft = soft;
pind.epoint = NULL;
pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
+ pind.dm = hair_dm;
memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
@@ -2759,10 +2774,12 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
- /* keyed, baked and softbody are allready in global space */
- if(!keyed && !baked && !soft && !(psys->flag & PSYS_GLOBAL_HAIR)) {
+ /* dynamic hair is in object space */
+ /* keyed and baked are allready in global space */
+ if(hair_dm)
+ Mat4MulVecfl(ob->obmat, result.co);
+ else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR))
Mat4MulVecfl(hairmat, result.co);
- }
VECCOPY(ca->co, result.co);
VECCOPY(ca->col, col);
@@ -2778,64 +2795,66 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector);
for(k=0, ca=cache[i]; k<=steps; k++, ca++) {
+ if(!(psys->flag & PSYS_GLOBAL_HAIR)) {
/* apply effectors */
- if(!(psys->part->flag & PART_CHILD_EFFECT) && k)
- do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec);
+ if(!(psys->part->flag & PART_CHILD_EFFECT) && k)
+ do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec);
- /* apply guide curves to path data */
- if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0)
- /* ca is safe to cast, since only co and vel are used */
- do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors);
+ /* apply guide curves to path data */
+ if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0)
+ /* ca is safe to cast, since only co and vel are used */
+ do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors);
- /* apply lattice */
- if(psys->lattice)
- calc_latt_deform(psys->lattice, ca->co, 1.0f);
+ /* apply lattice */
+ if(psys->lattice)
+ calc_latt_deform(psys->lattice, ca->co, 1.0f);
- /* figure out rotation */
-
- if(k) {
- float cosangle, angle, tangent[3], normal[3], q[4];
-
- if(k == 1) {
- /* calculate initial tangent for incremental rotations */
- VECSUB(tangent, ca->co, (ca - 1)->co);
- VECCOPY(prev_tangent, tangent);
- Normalize(prev_tangent);
-
- /* First rotation is based on emitting face orientation. */
- /* This is way better than having flipping rotations resulting */
- /* from using a global axis as a rotation pole (vec_to_quat()). */
- /* It's not an ideal solution though since it disregards the */
- /* initial tangent, but taking that in to account will allow */
- /* the possibility of flipping again. -jahka */
- Mat3ToQuat_is_ok(rotmat, (ca-1)->rot);
- }
- else {
- VECSUB(tangent, ca->co, (ca - 1)->co);
- Normalize(tangent);
-
- cosangle= Inpf(tangent, prev_tangent);
-
- /* note we do the comparison on cosangle instead of
- * angle, since floating point accuracy makes it give
- * different results across platforms */
- if(cosangle > 0.999999f) {
- QUATCOPY((ca - 1)->rot, (ca - 2)->rot);
+ /* figure out rotation */
+
+ if(k) {
+ float cosangle, angle, tangent[3], normal[3], q[4];
+
+ if(k == 1) {
+ /* calculate initial tangent for incremental rotations */
+ VECSUB(tangent, ca->co, (ca - 1)->co);
+ VECCOPY(prev_tangent, tangent);
+ Normalize(prev_tangent);
+
+ /* First rotation is based on emitting face orientation. */
+ /* This is way better than having flipping rotations resulting */
+ /* from using a global axis as a rotation pole (vec_to_quat()). */
+ /* It's not an ideal solution though since it disregards the */
+ /* initial tangent, but taking that in to account will allow */
+ /* the possibility of flipping again. -jahka */
+ Mat3ToQuat_is_ok(rotmat, (ca-1)->rot);
}
else {
- angle= saacos(cosangle);
- Crossf(normal, prev_tangent, tangent);
- VecRotToQuat(normal, angle, q);
- QuatMul((ca - 1)->rot, q, (ca - 2)->rot);
+ VECSUB(tangent, ca->co, (ca - 1)->co);
+ Normalize(tangent);
+
+ cosangle= Inpf(tangent, prev_tangent);
+
+ /* note we do the comparison on cosangle instead of
+ * angle, since floating point accuracy makes it give
+ * different results across platforms */
+ if(cosangle > 0.999999f) {
+ QUATCOPY((ca - 1)->rot, (ca - 2)->rot);
+ }
+ else {
+ angle= saacos(cosangle);
+ Crossf(normal, prev_tangent, tangent);
+ VecRotToQuat(normal, angle, q);
+ QuatMul((ca - 1)->rot, q, (ca - 2)->rot);
+ }
+
+ VECCOPY(prev_tangent, tangent);
}
- VECCOPY(prev_tangent, tangent);
+ if(k == steps)
+ QUATCOPY(ca->rot, (ca - 1)->rot);
}
- if(k == steps)
- QUATCOPY(ca->rot, (ca - 1)->rot);
}
-
/* set velocity */
@@ -2913,9 +2932,9 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
pind.keyed = 0;
pind.cache = NULL;
- pind.soft = NULL;
pind.epoint = point;
pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0;
+ pind.dm = NULL;
memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
@@ -3783,8 +3802,8 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
pa = psys->particles + p;
pind.keyed = keyed;
pind.cache = cached ? psys->pointcache : NULL;
- pind.soft = NULL;
pind.epoint = NULL;
+ pind.dm = psys->hair_out_dm;
init_particle_interpolation(ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 1931b89af38..88b85bcfa29 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -73,7 +73,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
#include "BKE_material.h"
-#include "BKE_softbody.h"
+#include "BKE_cloth.h"
#include "BKE_depsgraph.h"
#include "BKE_lattice.h"
#include "BKE_pointcache.h"
@@ -126,7 +126,7 @@ void psys_reset(ParticleSystem *psys, int mode)
PARTICLE_P;
if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) {
- if(mode == PSYS_RESET_ALL || !(part->type == PART_HAIR && (psys->edit && psys->edit->edited))) {
+ if(mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) {
psys_free_particles(psys);
psys->totpart= 0;
@@ -3432,6 +3432,190 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa
/************************************************/
/* Hair */
/************************************************/
+/* check if path cache or children need updating and do it if needed */
+static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
+{
+ ParticleSettings *part=psys->part;
+ ParticleEditSettings *pset=&scene->toolsettings->particle;
+ int distr=0,alloc=0,skip=0;
+
+ if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
+ alloc=1;
+
+ if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)))
+ distr=1;
+
+ if(distr){
+ if(alloc)
+ realloc_particles(ob,psys,psys->totpart);
+
+ if(get_psys_tot_child(scene, psys)) {
+ /* don't generate children while computing the hair keys */
+ if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
+ distribute_particles(scene, ob, psys, PART_FROM_CHILD);
+
+ if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
+ psys_find_parents(ob,psmd,psys);
+ }
+ }
+ }
+
+ if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0)
+ skip = 1; /* only hair, keyed and baked stuff can have paths */
+ else if(part->ren_as != PART_DRAW_PATH)
+ skip = 1; /* particle visualization must be set as path */
+ else if(!psys->renderdata) {
+ if(part->draw_as != PART_DRAW_REND)
+ skip = 1; /* draw visualization */
+ else if(psys->pointcache->flag & PTCACHE_BAKING)
+ skip = 1; /* no need to cache paths while baking dynamics */
+ else if(psys_in_edit_mode(scene, psys)) {
+ if((pset->flag & PE_DRAW_PART)==0)
+ skip = 1;
+ else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
+ skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */
+ }
+ }
+
+ if(!skip) {
+ psys_cache_paths(scene, ob, psys, cfra);
+
+ /* for render, child particle paths are computed on the fly */
+ if(part->childtype) {
+ if(!psys->totchild)
+ skip = 1;
+ else if((psys->part->type == PART_HAIR && psys->flag & PSYS_HAIR_DONE)==0)
+ skip = 1;
+
+ if(!skip)
+ psys_cache_child_paths(scene, ob, psys, cfra, 0);
+ }
+ }
+ else if(psys->pathcache)
+ psys_free_path_cache(psys, NULL);
+}
+
+static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd)
+{
+ DerivedMesh *dm = psys->hair_in_dm;
+ MVert *mvert = NULL;
+ MEdge *medge = NULL;
+ MDeformVert *dvert = NULL;
+ HairKey *key;
+ PARTICLE_P;
+ int totpoint = 0;
+ int totedge;
+ int k;
+ float hairmat[4][4];
+
+ if(!psys->clmd) {
+ psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth);
+ psys->clmd->sim_parms->goalspring = 0.0f;
+ psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS;
+ psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF;
+ }
+
+ /* create a dm from hair vertices */
+ LOOP_PARTICLES
+ totpoint += pa->totkey;
+
+ totedge = totpoint - psys->totpart;
+
+ if(dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) {
+ dm->release(dm);
+ dm = psys->hair_in_dm = NULL;
+ }
+
+ if(!dm) {
+ dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0);
+ DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
+ }
+
+ mvert = CDDM_get_verts(dm);
+ medge = CDDM_get_edges(dm);
+ dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
+
+ psys->clmd->sim_parms->vgroup_mass = 1;
+
+ /* make vgroup for pin roots etc.. */
+ psys->particles->hair_index = 0;
+ LOOP_PARTICLES {
+ if(p)
+ pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey;
+
+ psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat);
+
+ for(k=0, key=pa->hair; k<pa->totkey; k++,key++) {
+ VECCOPY(mvert->co, key->co);
+ Mat4MulVecfl(hairmat, mvert->co);
+ mvert++;
+
+ if(k) {
+ medge->v1 = pa->hair_index + k - 1;
+ medge->v2 = pa->hair_index + k;
+ medge++;
+ }
+
+ if(dvert) {
+ if(!dvert->totweight) {
+ dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight");
+ dvert->totweight = 1;
+ }
+
+ /* no special reason for the 0.5 */
+ /* just seems like a nice value from experiments */
+ dvert->dw->weight = k ? 0.5f : 1.0f;
+ dvert++;
+ }
+ }
+ }
+
+ if(psys->hair_out_dm)
+ psys->hair_out_dm->release(psys->hair_out_dm);
+
+ psys->clmd->point_cache = psys->pointcache;
+
+ psys->hair_out_dm = clothModifier_do(psys->clmd, scene, ob, dm, 0, 0);
+}
+static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
+{
+ ParticleSettings *part = psys->part;
+ PARTICLE_P;
+ float disp = (float)get_current_display_percentage(psys)/100.0f;
+
+ BLI_srandom(psys->seed);
+
+ LOOP_PARTICLES {
+ if(BLI_frand() > disp)
+ pa->flag |= PARS_NO_DISP;
+ else
+ pa->flag &= ~PARS_NO_DISP;
+ }
+
+ if(psys->recalc & PSYS_RECALC_RESET) {
+ /* need this for changing subsurf levels */
+ psys_calc_dmcache(ob, psmd->dm, psys);
+
+ if(psys->clmd)
+ cloth_free_modifier(ob, psys->clmd);
+ }
+
+ if(psys->effectors.first)
+ psys_end_effectors(psys);
+
+ /* dynamics with cloth simulation */
+ if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS)
+ do_hair_dynamics(scene, ob, psys, psmd);
+
+ psys_init_effectors(scene, ob, part->eff_group, psys);
+ if(psys->effectors.first)
+ precalc_effectors(scene, ob,psys,psmd,cfra);
+
+ psys_update_path_cache(scene, ob,psmd,psys,cfra);
+
+ psys->flag |= PSYS_HAIR_UPDATED;
+}
+
static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){
HairKey *key, *root;
PARTICLE_P;
@@ -3692,79 +3876,6 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
BLI_kdtree_free(tree);
}
-/* check if path cache or children need updating and do it if needed */
-static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
-{
- ParticleSettings *part=psys->part;
- ParticleEditSettings *pset=&scene->toolsettings->particle;
- int distr=0,alloc=0;
-
- if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
- alloc=1;
-
- if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT)))
- distr=1;
-
- if(distr){
- if(alloc)
- realloc_particles(ob,psys,psys->totpart);
-
- if(get_psys_tot_child(scene, psys)) {
- /* don't generate children while computing the hair keys */
- if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
- distribute_particles(scene, ob, psys, PART_FROM_CHILD);
-
- if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
- psys_find_parents(ob,psmd,psys);
- }
- }
- }
-
- if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR
- || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){
-
- psys_cache_paths(scene, ob, psys, cfra);
-
- /* for render, child particle paths are computed on the fly */
- if(part->childtype) {
- if(((psys->totchild!=0)) || (psys_in_edit_mode(scene, psys) && (pset->flag&PE_DRAW_PART)))
- if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE))
- psys_cache_child_paths(scene, ob, psys, cfra, 0);
- }
- }
- else if(psys->pathcache)
- psys_free_path_cache(psys, NULL);
-}
-
-static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
-{
- ParticleSettings *part = psys->part;
- PARTICLE_P;
- float disp = (float)get_current_display_percentage(psys)/100.0f;
-
- BLI_srandom(psys->seed);
-
- LOOP_PARTICLES {
- if(BLI_frand() > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
-
- if(psys->recalc & PSYS_RECALC_RESET)
- /* need this for changing subsurf levels */
- psys_calc_dmcache(ob, psmd->dm, psys);
-
- if(psys->effectors.first)
- psys_end_effectors(psys);
-
- psys_init_effectors(scene, ob, part->eff_group, psys);
- if(psys->effectors.first)
- precalc_effectors(scene, ob,psys,psmd,cfra);
-
- psys_update_path_cache(scene, ob,psmd,psys,cfra);
-}
-
/* updates cached particles' alive & other flags etc..*/
static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
{
@@ -3889,14 +4000,12 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys)
BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
}
else {
- free_hair(psys, 1);
+ free_hair(ob, psys, 1);
CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime));
CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime));
}
- psys->softflag= 0;
-
psys_reset(psys, PSYS_RESET_ALL);
}
void psys_check_boid_data(ParticleSystem *psys)
@@ -4082,7 +4191,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
framedelta= framenr - cache->simframe;
/* set suitable cache range automatically */
- if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0)
+ if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0 && !(psys->flag & PSYS_HAIR_DYNAMICS))
psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe);
BKE_ptcache_id_from_particles(&pid, ob, psys);
@@ -4307,39 +4416,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
}
}
-static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys)
-{
- SoftBody *sb;
- short softflag;
-
- if(!(psys->softflag & OB_SB_ENABLE))
- return;
-
- /* let's replace the object's own softbody with the particle softbody */
- /* a temporary solution before cloth simulation is implemented, jahka */
-
- /* save these */
- sb= ob->soft;
- softflag= ob->softflag;
-
- /* swich to new ones */
- ob->soft= psys->soft;
- ob->softflag= psys->softflag;
-
- /* do softbody */
- sbObjectStep(scene, ob, (float)scene->r.cfra, NULL, psys_count_keys(psys));
-
- /* return things back to normal */
- psys->soft= ob->soft;
- psys->softflag= ob->softflag;
-
- ob->soft= sb;
- ob->softflag= softflag;
-}
-
static int hair_needs_recalc(ParticleSystem *psys)
{
- if((!psys->edit || !psys->edit->edited) &&
+ if(!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) &&
((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) {
return 1;
}
@@ -4380,7 +4459,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
float hcfra=0.0f;
int i;
- free_hair(psys, 0);
+ free_hair(ob, psys, 0);
/* first step is negative so particles get killed and reset */
psys->cfra= 1.0f;
@@ -4394,10 +4473,6 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag |= PSYS_HAIR_DONE;
}
- /* handle softbody hair */
- if(psys->part->type==PART_HAIR && psys->soft)
- psys_to_softbody(scene, ob, psys);
-
/* the main particle system step */
system_step(scene, ob, psys, psmd, cfra);
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 5a14277d63b..f351f8a4335 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -382,8 +382,6 @@ static int ptcache_totpoint_cloth(void *cloth_v)
/* Creating ID's */
void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
{
- ParticleSystemModifierData *psmd;
-
memset(pid, 0, sizeof(PTCacheID));
pid->ob= ob;
@@ -406,12 +404,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb)
pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY);
pid->info_types= 0;
- if(sb->particles) {
- psmd= psys_get_modifier(ob, sb->particles);
- // pid->stack_index= modifiers_indexInObject(ob, (ModifierData*)psmd); XXX TODO - get other index DG
- }
- else
- pid->stack_index = pid->cache->index;
+ pid->stack_index = pid->cache->index;
}
void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys)
@@ -426,7 +419,8 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p
pid->cache_ptr= &psys->pointcache;
pid->ptcaches= &psys->ptcaches;
- pid->flag |= PTCACHE_VEL_PER_SEC;
+ if(psys->part->type != PART_HAIR)
+ pid->flag |= PTCACHE_VEL_PER_SEC;
pid->write_elem= ptcache_write_particle;
pid->write_stream = NULL;
@@ -816,12 +810,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob)
pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
BKE_ptcache_id_from_particles(pid, ob, psys);
BLI_addtail(lb, pid);
-
- if(psys->soft) {
- pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID");
- BKE_ptcache_id_from_softbody(pid, ob, psys->soft);
- BLI_addtail(lb, pid);
- }
}
}
@@ -1828,9 +1816,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
else if(mode == PTCACHE_RESET_OUTDATED) {
reset = 1;
- if(cache->flag & PTCACHE_OUTDATED)
- if(!(cache->flag & PTCACHE_BAKED))
- clear= 1;
+ if(cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) {
+ clear= 1;
+ cache->flag &= ~PTCACHE_OUTDATED;
+ }
}
if(reset) {
@@ -1873,10 +1862,10 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
}
for(psys=ob->particlesystem.first; psys; psys=psys->next) {
- /* Baked softbody hair has to be checked first, because we don't want to reset */
- /* particles or softbody in that case -jahka */
- if(psys->soft) {
- BKE_ptcache_id_from_softbody(&pid, ob, psys->soft);
+ /* Baked cloth hair has to be checked first, because we don't want to reset */
+ /* particles or cloth in that case -jahka */
+ if(psys->clmd) {
+ BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd);
if(mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED)))
reset |= BKE_ptcache_id_reset(scene, &pid, mode);
else
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index fdbfe154fae..450a64d72eb 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -58,7 +58,6 @@ variables on the UI for now
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h" /* here is the softbody struct */
-#include "DNA_particle_types.h"
#include "DNA_key_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -76,7 +75,6 @@ variables on the UI for now
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
@@ -494,32 +492,21 @@ static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *h
while (base) {
/*Only proceed for mesh object in same layer */
if(base->object->type==OB_MESH && (base->lay & vertexowner->lay)) {
- int particles=0;
ob= base->object;
if((vertexowner) && (ob == vertexowner)) {
- if(vertexowner->soft->particles){
- particles=1;
- }
- else {
- /* if vertexowner is given we don't want to check collision with owner object */
- base = base->next;
- continue;
- }
+ /* if vertexowner is given we don't want to check collision with owner object */
+ base = base->next;
+ continue;
}
/*+++ only with deflecting set */
if(ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == 0) {
DerivedMesh *dm= NULL;
- if(particles) {
- dm = psys_get_modifier(ob,psys_get_current(ob))->dm;
- }
- else {
- if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */
- dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
- else
- dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
- }
+ if(ob->softflag & OB_SB_COLLFINAL) /* so maybe someone wants overkill to collide with subsurfed */
+ dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+ else
+ dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
if(dm){
ccd_Mesh *ccdmesh = ccd_mesh_make(ob, dm);
@@ -3571,107 +3558,6 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob)
}
}
-
-static void springs_from_particles(Object *ob)
-{
- ParticleSystem *psys;
- ParticleSystemModifierData *psmd=0;
- ParticleData *pa=0;
- HairKey *key=0;
- SoftBody *sb;
- BodyPoint *bp;
- BodySpring *bs;
- int a,k;
- float hairmat[4][4];
-
- if(ob && ob->soft && ob->soft->particles) {
- psys= ob->soft->particles;
- sb= ob->soft;
- psmd = psys_get_modifier(ob, psys);
-
- bp= sb->bpoint;
- for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
- for(k=0, key=pa->hair; k<pa->totkey; k++, bp++, key++) {
- VECCOPY(bp->origS, key->co);
-
- psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
-
- Mat4MulVecfl(hairmat, bp->origS);
- }
- }
-
- for(a=0, bs=sb->bspring; a<sb->totspring; a++, bs++)
- bs->len= VecLenf(sb->bpoint[bs->v1].origS, sb->bpoint[bs->v2].origS);
- }
-}
-
-static void particles_to_softbody(Scene *scene, Object *ob)
-{
- SoftBody *sb;
- BodyPoint *bp;
- BodySpring *bs;
- ParticleData *pa;
- HairKey *key;
- ParticleSystem *psys= ob->soft->particles;
- float goalfac;
- int a, k, curpoint;
- int totpoint= psys_count_keys(psys);
- int totedge= totpoint-psys->totpart;
-
- /* renew ends with ob->soft with points and edges, also checks & makes ob->soft */
- renew_softbody(scene, ob, totpoint, totedge);
-
- /* find first BodyPoint index for each particle */
- if(psys->totpart > 0) {
-// psys->particles->bpi = 0;
-// for(a=1, pa=psys->particles+1; a<psys->totpart; a++, pa++)
-// pa->bpi = (pa-1)->bpi + (pa-1)->totkey;
- }
-
- /* we always make body points */
- sb= ob->soft;
- bp= sb->bpoint;
- bs= sb->bspring;
- goalfac= ABS(sb->maxgoal - sb->mingoal);
-
- if((ob->softflag & OB_SB_GOAL)) {
- for(a=0, pa=psys->particles; a<psys->totpart; a++, pa++) {
- for(k=0, key=pa->hair; k<pa->totkey; k++,bp++,key++) {
- if(k) {
- bp->goal= key->weight;
- bp->goal= sb->mingoal + bp->goal*goalfac;
- bp->goal= (float)pow(bp->goal, 4.0f);
- }
- else{
- /* hair roots are allways fixed fully to goal */
- bp->goal= 1.0f;
- }
- }
- }
- }
-
- bp= sb->bpoint;
- curpoint=0;
- for(a=0, pa=psys->particles; a<psys->totpart; a++, curpoint++, pa++) {
- for(k=0; k<pa->totkey-1; k++,bs++,curpoint++) {
- bs->v1=curpoint;
- bs->v2=curpoint+1;
- bs->strength= 1.0;
- bs->order=1;
- }
- }
-
- build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */
- /* insert *other second order* springs if desired */
- if(sb->secondspring > 0.0000001f) {
- add_2nd_order_springs(ob,sb->secondspring*10.0); /* exploits the the first run of build_bps_springlist(ob);*/
- build_bps_springlist(ob); /* yes we need to do it again*/
- }
- springs_from_particles(ob); /* write the 'rest'-lenght of the springs */
- if(ob->softflag & OB_SB_SELF)
- calculate_collision_balls(ob);
-}
-
/* copies softbody result back in object */
static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, int local)
{
@@ -3795,44 +3681,16 @@ void sbSetInterruptCallBack(int (*f)(void))
static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts)
{
- ParticleSystemModifierData *psmd= NULL;
- ParticleData *pa= NULL;
- HairKey *key= NULL;
BodyPoint *bp;
- float hairmat[4][4];
int a;
- /* update the vertex locations */
- if(sb->particles && sb->particles->totpart>0) {
- psmd= psys_get_modifier(ob,sb->particles);
-
- pa= sb->particles->particles;
- key= pa->hair;
-
- psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
- }
-
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
/* store where goals are now */
VECCOPY(bp->origS, bp->origE);
/* copy the position of the goals at desired end time */
- if(sb->particles) {
- if(key == pa->hair + pa->totkey) {
- pa++;
- key = pa->hair;
-
- psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
- }
- VECCOPY(bp->origE, key->co);
- Mat4MulVecfl(hairmat,bp->origE);
-
- key++;
- }
- else{
- VECCOPY(bp->origE, vertexCos[a]);
- /* vertexCos came from local world, go global */
- Mat4MulVecfl(ob->obmat, bp->origE);
- }
+ VECCOPY(bp->origE, vertexCos[a]);
+ /* vertexCos came from local world, go global */
+ Mat4MulVecfl(ob->obmat, bp->origE);
/* just to be save give bp->origT a defined value
will be calulated in interpolate_exciter()*/
VECCOPY(bp->origT, bp->origE);
@@ -3841,37 +3699,12 @@ static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCo
static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts)
{
- ParticleSystemModifierData *psmd= NULL;
- HairKey *key= NULL;
- ParticleData *pa= NULL;
BodyPoint *bp;
- float hairmat[4][4];
int a;
- if(sb->particles && sb->particles->totpart>0) {
- psmd= psys_get_modifier(ob, sb->particles);
- pa= sb->particles->particles;
- key= pa->hair;
-
- psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
- }
-
for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) {
- if(sb->particles) {
- if(key == pa->hair + pa->totkey) {
- pa++;
- key = pa->hair;
-
- psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat);
- }
- VECCOPY(bp->pos, key->co);
- Mat4MulVecfl(hairmat, bp->pos);
- key++;
- }
- else {
- VECCOPY(bp->pos, vertexCos[a]);
- Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
- }
+ VECCOPY(bp->pos, vertexCos[a]);
+ Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/
VECCOPY(bp->origS, bp->pos);
VECCOPY(bp->origE, bp->pos);
VECCOPY(bp->origT, bp->pos);
@@ -3900,20 +3733,18 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int
sb_new_scratch(sb); /* make a new */
sb->scratch->needstobuildcollider=1;
- if((sb->particles)==0) {
- /* copy some info to scratch */
- switch(ob->type) {
- case OB_MESH:
- if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
- break;
- case OB_LATTICE:
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- default:
- break;
- }
+ /* copy some info to scratch */
+ switch(ob->type) {
+ case OB_MESH:
+ if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob);
+ break;
+ case OB_LATTICE:
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ break;
+ default:
+ break;
}
}
@@ -4049,8 +3880,6 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
/* simulates one step. framenr is in frames */
void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
{
- ParticleSystemModifierData *psmd=0;
- ParticleData *pa=0;
SoftBody *sb= ob->soft;
PointCache *cache;
PTCacheID pid;
@@ -4091,25 +3920,20 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
if(sb->bpoint == NULL ||
((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) {
- if(sb->particles){
- particles_to_softbody(scene, ob);
- }
- else {
- switch(ob->type) {
- case OB_MESH:
- mesh_to_softbody(scene, ob);
- break;
- case OB_LATTICE:
- lattice_to_softbody(scene, ob);
- break;
- case OB_CURVE:
- case OB_SURF:
- curve_surf_to_softbody(scene, ob);
- break;
- default:
- renew_softbody(scene, ob, numVerts, 0);
- break;
- }
+ switch(ob->type) {
+ case OB_MESH:
+ mesh_to_softbody(scene, ob);
+ break;
+ case OB_LATTICE:
+ lattice_to_softbody(scene, ob);
+ break;
+ case OB_CURVE:
+ case OB_SURF:
+ curve_surf_to_softbody(scene, ob);
+ break;
+ default:
+ renew_softbody(scene, ob, numVerts, 0);
+ break;
}
softbody_update_positions(ob, sb, vertexCos, numVerts);
@@ -4127,8 +3951,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
softbody_update_positions(ob, sb, vertexCos, numVerts);
softbody_step(scene, ob, sb, dtime);
- if(sb->particles==0)
- softbody_to_object(ob, vertexCos, numVerts, 0);
+ softbody_to_object(ob, vertexCos, numVerts, 0);
return;
}
@@ -4136,14 +3959,14 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
/* still no points? go away */
if(sb->totpoint==0) return;
- if(sb->particles){
- psmd= psys_get_modifier(ob, sb->particles);
- pa= sb->particles->particles;
- }
-
- if(framenr == startframe && cache->flag & PTCACHE_REDO_NEEDED) {
+ if(framenr == startframe) {
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+
+ /* first frame, no simulation to do, just set the positions */
+ softbody_update_positions(ob, sb, vertexCos, numVerts);
+
cache->simframe= framenr;
+ cache->flag |= PTCACHE_SIMULATION_VALID;
cache->flag &= ~PTCACHE_REDO_NEEDED;
return;
}
@@ -4152,8 +3975,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec);
if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
- if(sb->particles==0)
- softbody_to_object(ob, vertexCos, numVerts, sb->local);
+ softbody_to_object(ob, vertexCos, numVerts, sb->local);
cache->simframe= framenr;
cache->flag |= PTCACHE_SIMULATION_VALID;
@@ -4174,36 +3996,23 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
return;
}
- if(framenr == startframe) {
- /* first frame, no simulation to do, just set the positions */
- softbody_update_positions(ob, sb, vertexCos, numVerts);
-
- cache->simframe= framenr;
- cache->flag |= PTCACHE_SIMULATION_VALID;
+ /* 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);
- /* 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);
+ softbody_update_positions(ob, sb, vertexCos, numVerts);
- softbody_update_positions(ob, sb, vertexCos, numVerts);
+ /* checking time: */
+ dtime = framedelta*timescale;
- /* checking time: */
- dtime = framedelta*timescale;
+ softbody_step(scene, ob, sb, dtime);
- softbody_step(scene, ob, sb, dtime);
-
- if(sb->particles==0)
- softbody_to_object(ob, vertexCos, numVerts, 0);
+ softbody_to_object(ob, vertexCos, numVerts, 0);
- /* do simulation */
- cache->simframe= framenr;
- cache->flag |= PTCACHE_SIMULATION_VALID;
+ /* do simulation */
+ cache->simframe= framenr;
+ cache->flag |= PTCACHE_SIMULATION_VALID;
- BKE_ptcache_write_cache(&pid, framenr);
- }
+ BKE_ptcache_write_cache(&pid, framenr);
}