diff options
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/cloth.c | 45 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/implicit.c | 88 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 209 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 305 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 33 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/softbody.c | 307 |
7 files changed, 481 insertions, 513 deletions
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); } |