From d5a890c078c770906e49239e3cbac89bf11ebd8d Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 18 Aug 2008 11:09:27 +0000 Subject: a) New unified effector system by Janne (jahka) + Me (genscher): particle and cloth/sb don't use different systems anymore. b) cloth wind corrected for new system c) Wind has noise option now d) @ Bjornmose: since the old factors are gone SB doesn't need to divide by 1000 etc. anymore. I didn't want to touch your code - you might like to take a look at it :) --- source/blender/blenkernel/BKE_effect.h | 6 + source/blender/blenkernel/intern/effect.c | 372 +++++++++++---------- source/blender/blenkernel/intern/implicit.c | 131 +++++--- source/blender/blenkernel/intern/particle_system.c | 175 +--------- source/blender/blenlib/BLI_rand.h | 1 + source/blender/blenlib/intern/rand.c | 18 +- source/blender/blenloader/intern/readfile.c | 33 +- source/blender/makesdna/DNA_object_force.h | 3 + source/blender/src/buttons_object.c | 2 + 9 files changed, 313 insertions(+), 428 deletions(-) diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 3763a659f2f..3b4c3198179 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -37,6 +37,7 @@ struct Effect; struct ListBase; struct Particle; struct Group; +struct RNG; typedef struct pEffectorCache { struct pEffectorCache *next, *prev; @@ -64,6 +65,11 @@ struct ListBase *pdInitEffectors(struct Object *obsrc, struct Group *group); void pdEndEffectors(struct ListBase *lb); void pdDoEffectors(struct ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags); +/* required for particle_system.c */ +void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise); +float effector_falloff(struct PartDeflect *pd, float *eff_velocity, float *vec_to_part); + + #endif diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 4588ef800e1..7620edac126 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -157,6 +157,13 @@ static void add_to_effectorcache(ListBase *lb, Object *ob, Object *obsrc) } } else if(pd->forcefield) { + + if(pd->forcefield == PFIELD_WIND) + { + pd->rng = rng_new(1); + rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed + } + ec= MEM_callocN(sizeof(pEffectorCache), "effector cache"); ec->ob= ob; BLI_addtail(lb, ec); @@ -205,13 +212,189 @@ void pdEndEffectors(ListBase *lb) pEffectorCache *ec; /* restore full copy */ for(ec= lb->first; ec; ec= ec->next) + { + if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND)) + rng_free(ec->ob->pd->rng); + *(ec->ob)= ec->obcopy; + } BLI_freelistN(lb); } } +/************************************************/ +/* Effectors */ +/************************************************/ + +// noise function for wind e.g. +static float wind_func(struct RNG *rng, float strength) +{ + int random = (rng_getInt(rng)+1) % 65535; // max 2357 + float force = rng_getFloat(rng) + 1.0f; + float ret; + float sign = 0; + + sign = (random > 32000.0) ? 1.0: -1.0; // dividing by 2 is not giving equal sign distribution + + ret = sign*((float)random / force)*strength/65535.0f; + + return ret; +} + + +static float falloff_func(float fac, int usemin, float mindist, int usemax, float maxdist, float power) +{ + if(!usemin) + mindist= 0.0f; + + if(fac < mindist) { + return 1.0f; + } + else if(usemax) { + if(fac>maxdist || (maxdist-mindist)<=0.0f) + return 0.0f; + + fac= (fac-mindist)/(maxdist-mindist); + return 1.0f - (float)pow((double)fac, (double)power); + } + else + return pow((double)1.0f+fac-mindist, (double)-power); +} + +static float falloff_func_dist(PartDeflect *pd, float fac) +{ + return falloff_func(fac, pd->flag&PFIELD_USEMIN, pd->mindist, pd->flag&PFIELD_USEMAX, pd->maxdist, pd->f_power); +} + +static float falloff_func_rad(PartDeflect *pd, float fac) +{ + return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r); +} + +float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part) +{ + float eff_dir[3], temp[3]; + float falloff=1.0, fac, r_fac; + + VecCopyf(eff_dir,eff_velocity); + Normalize(eff_dir); + + if(pd->flag & PFIELD_POSZ && Inpf(eff_dir,vec_to_part)<0.0f) + falloff=0.0f; + else switch(pd->falloff){ + case PFIELD_FALL_SPHERE: + fac=VecLength(vec_to_part); + falloff= falloff_func_dist(pd, fac); + break; + + case PFIELD_FALL_TUBE: + fac=Inpf(vec_to_part,eff_dir); + falloff= falloff_func_dist(pd, ABS(fac)); + if(falloff == 0.0f) + break; + + VECADDFAC(temp,vec_to_part,eff_dir,-fac); + r_fac=VecLength(temp); + falloff*= falloff_func_rad(pd, r_fac); + break; + case PFIELD_FALL_CONE: + fac=Inpf(vec_to_part,eff_dir); + falloff= falloff_func_dist(pd, ABS(fac)); + if(falloff == 0.0f) + break; + + r_fac=saacos(fac/VecLength(vec_to_part))*180.0f/(float)M_PI; + falloff*= falloff_func_rad(pd, r_fac); + + break; + } + + return falloff; +} + +void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar, struct RNG *rng, float noise) +{ + float mag_vec[3]={0,0,0}; + float temp[3], temp2[3]; + float eff_vel[3]; + float wind = 0; + + VecCopyf(eff_vel,eff_velocity); + Normalize(eff_vel); + + switch(type){ + case PFIELD_WIND: + VECCOPY(mag_vec,eff_vel); + + // add wind noise here + if(noise> 0.0f) + wind = wind_func(rng, noise); + + VecMulf(mag_vec,(force_val+wind)*falloff); + VecAddf(field,field,mag_vec); + break; + + case PFIELD_FORCE: + if(planar) + Projf(mag_vec,vec_to_part,eff_vel); + else + VecCopyf(mag_vec,vec_to_part); + + VecMulf(mag_vec,force_val*falloff); + VecAddf(field,field,mag_vec); + break; + + case PFIELD_VORTEX: + Crossf(mag_vec,eff_vel,vec_to_part); + Normalize(mag_vec); + + VecMulf(mag_vec,force_val*distance*falloff); + VecAddf(field,field,mag_vec); + + break; + case PFIELD_MAGNET: + if(planar) + VecCopyf(temp,eff_vel); + else + /* magnetic field of a moving charge */ + Crossf(temp,eff_vel,vec_to_part); + + Crossf(temp2,velocity,temp); + VecAddf(mag_vec,mag_vec,temp2); + + VecMulf(mag_vec,force_val*falloff); + VecAddf(field,field,mag_vec); + break; + case PFIELD_HARMONIC: + if(planar) + Projf(mag_vec,vec_to_part,eff_vel); + else + VecCopyf(mag_vec,vec_to_part); + + VecMulf(mag_vec,force_val*falloff); + VecSubf(field,field,mag_vec); + + VecCopyf(mag_vec,velocity); + /* 1.9 is an experimental value to get critical damping at damp=1.0 */ + VecMulf(mag_vec,damp*1.9f*(float)sqrt(force_val)); + VecSubf(field,field,mag_vec); + break; + case PFIELD_NUCLEAR: + /*pow here is root of cosine expression below*/ + //rad=(float)pow(2.0,-1.0/power)*distance/size; + //VECCOPY(mag_vec,vec_to_part); + //Normalize(mag_vec); + //VecMulf(mag_vec,(float)cos(3.0*M_PI/2.0*(1.0-1.0/(pow(rad,power)+1.0)))/(rad+0.2f)); + //VECADDFAC(field,field,mag_vec,force_val); + break; + } +} + + + + /* -------- pdDoEffectors() -------- generic force/speed system, now used for particles and softbodies lb = listbase with objects that take part in effecting @@ -244,13 +427,10 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float pEffectorCache *ec; PartDeflect *pd; float vect_to_vert[3]; - float f_force, force_vec[3]; float *obloc; - float distance, force_val, ffall_val; - float guidecollect[3], guidedist= 0.0f; - int cur_frame; - guidecollect[0]= guidecollect[1]= guidecollect[2]=0.0f; + float distance, vec_to_part[3]; + float falloff; /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */ /* Check for min distance here? (yes would be cool to add that, ton) */ @@ -261,178 +441,32 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float pd= ob->pd; /* Get IPO force strength and fall off values here */ - if (has_ipo_code(ob->ipo, OB_PD_FSTR)) - force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, cur_time); - else - force_val = pd->f_strength; - - if (has_ipo_code(ob->ipo, OB_PD_FFALL)) - ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, cur_time); - else - ffall_val = pd->f_power; - - /* Need to set r.cfra for paths (investigate, ton) (uses ob->ctime now, ton) */ - if(ob->ctime!=cur_time) { - cur_frame = G.scene->r.cfra; - G.scene->r.cfra = (int)cur_time; - where_is_object_time(ob, cur_time); - G.scene->r.cfra = cur_frame; - } + where_is_object_time(ob,cur_time); /* use center of object for distance calculus */ obloc= ob->obmat[3]; VECSUB(vect_to_vert, obloc, opco); distance = VecLength(vect_to_vert); - - if((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist && pd->forcefield != PFIELD_GUIDE) - ; /* don't do anything */ - else if((pd->flag & PFIELD_USEMIN) && distancemindist && pd->forcefield != PFIELD_GUIDE) + + VecSubf(vec_to_part, opco, ob->obmat[3]); + distance = VecLength(vec_to_part); + + falloff=effector_falloff(pd,ob->obmat[2],vec_to_part); + + if(falloff<=0.0f) ; /* don't do anything */ - else if(pd->forcefield == PFIELD_WIND) { - VECCOPY(force_vec, ob->obmat[2]); - - /* wind works harder perpendicular to normal, would be nice for softbody later (ton) */ - - /* Limit minimum distance to vertex so that */ - /* the force is not too big */ - if (distance < 0.001) distance = 0.001f; - f_force = (force_val)*(1/(1000 * (float)pow((double)distance, (double)ffall_val))); - /* this option for softbody only */ - if(flags && PE_WIND_AS_SPEED){ - speed[0] -= (force_vec[0] * f_force ); - speed[1] -= (force_vec[1] * f_force ); - speed[2] -= (force_vec[2] * f_force ); - } - else{ - force[0] += force_vec[0]*f_force; - force[1] += force_vec[1]*f_force; - force[2] += force_vec[2]*f_force; - } - } - else if(pd->forcefield == PFIELD_FORCE) { - - /* only use center of object */ - obloc= ob->obmat[3]; - - /* Now calculate the gravitational force */ - VECSUB(vect_to_vert, obloc, opco); - distance = VecLength(vect_to_vert); - - /* Limit minimum distance to vertex so that */ - /* the force is not too big */ - if (distance < 0.001) distance = 0.001f; - f_force = (force_val)*(1.0/(1000.0 * (float)pow((double)distance, (double)ffall_val))); - force[0] += (vect_to_vert[0] * f_force ); - force[1] += (vect_to_vert[1] * f_force ); - force[2] += (vect_to_vert[2] * f_force ); - } - else if(pd->forcefield == PFIELD_VORTEX) { - float vortexvec[3]; - - /* only use center of object */ - obloc= ob->obmat[3]; - - /* Now calculate the vortex force */ - VECSUB(vect_to_vert, obloc, opco); - distance = VecLength(vect_to_vert); - - Crossf(force_vec, ob->obmat[2], vect_to_vert); - Normalize(force_vec); - - /* Limit minimum distance to vertex so that */ - /* the force is not too big */ - if (distance < 0.001) distance = 0.001f; - f_force = (force_val)*(1.0/(100.0 * (float)pow((double)distance, (double)ffall_val))); - vortexvec[0]= -(force_vec[0] * f_force ); - vortexvec[1]= -(force_vec[1] * f_force ); - vortexvec[2]= -(force_vec[2] * f_force ); + else { + float field[3]={0,0,0}, tmp[3]; + VECCOPY(field, force); + do_physical_effector(pd->forcefield,pd->f_strength,distance, + falloff,pd->f_dist,pd->f_damp,ob->obmat[2],vec_to_part, + speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise); - /* this option for softbody only */ - if(flags &&PE_WIND_AS_SPEED) { - speed[0]+= vortexvec[0]; - speed[1]+= vortexvec[1]; - speed[2]+= vortexvec[2]; - } - else { - /* since vortex alters the speed, we have to correct for the previous vortex result */ - speed[0]+= vortexvec[0] - ec->oldspeed[0]; - speed[1]+= vortexvec[1] - ec->oldspeed[1]; - speed[2]+= vortexvec[2] - ec->oldspeed[2]; - - VECCOPY(ec->oldspeed, vortexvec); + // for softbody backward compatibility + if(flags & PE_WIND_AS_SPEED){ + VECSUB(tmp, force, field); + VECSUB(speed, speed, tmp); } } - else if(pd->forcefield == PFIELD_GUIDE) { - float guidevec[4], guidedir[3]; - float mindist= force_val; /* force_val is actually mindist in the UI */ - - distance= ec->guide_dist; - - /* WARNING: bails out with continue here */ - if((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist) continue; - - /* calculate contribution factor for this guide */ - if(distance<=mindist) f_force= 1.0f; - else if(pd->flag & PFIELD_USEMAX) { - if(distance>pd->maxdist || mindist>=pd->maxdist) f_force= 0.0f; - else { - f_force= 1.0f - (distance-mindist)/(pd->maxdist - mindist); - if(ffall_val!=0.0f) - f_force = (float)pow(f_force, ffall_val+1.0); - } - } - else { - f_force= 1.0f/(1.0f + distance-mindist); - if(ffall_val!=0.0f) - f_force = (float)pow(f_force, ffall_val+1.0); - } - - /* now derive path point from loc_time */ - if(pd->flag & PFIELD_GUIDE_PATH_ADD) - where_on_path(ob, f_force*loc_time*ec->time_scale, guidevec, guidedir); - else - where_on_path(ob, loc_time*ec->time_scale, guidevec, guidedir); - - VECSUB(guidedir, guidevec, ec->oldloc); - VECCOPY(ec->oldloc, guidevec); - - Mat4Mul3Vecfl(ob->obmat, guidedir); - VecMulf(guidedir, ec->scale); /* correction for lifetime and speed */ - - /* we subtract the speed we gave it previous step */ - VECCOPY(guidevec, guidedir); - VECSUB(guidedir, guidedir, ec->oldspeed); - VECCOPY(ec->oldspeed, guidevec); - - /* if it fully contributes, we stop */ - if(f_force==1.0) { - VECCOPY(guidecollect, guidedir); - guidedist= 1.0f; - break; - } - else if(guidedist<1.0f) { - VecMulf(guidedir, f_force); - VECADD(guidecollect, guidecollect, guidedir); - guidedist += f_force; - } - } - } - - /* all guides are accumulated here */ - if(guidedist!=0.0f) { - if(guidedist!=1.0f) VecMulf(guidecollect, 1.0f/guidedist); - VECADD(speed, speed, guidecollect); } } - - -/* for paf start to end, store all matrices for objects */ -typedef struct pMatrixCache { - float obmat[4][4]; - float imat[3][3]; -} pMatrixCache; - -/* for fluidsim win32 debug messages */ -#if defined(WIN32) && (!(defined snprintf)) -#define snprintf _snprintf -#endif diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index bf3953f999b..0375ab22909 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1354,9 +1354,43 @@ DO_INLINE void cloth_apply_spring_force(ClothModifierData *clmd, ClothSpring *s, } } + +static void CalcFloat( float *v1, float *v2, float *v3, float *n) +{ + float n1[3],n2[3]; + + n1[0]= v1[0]-v2[0]; + n2[0]= v2[0]-v3[0]; + n1[1]= v1[1]-v2[1]; + n2[1]= v2[1]-v3[1]; + n1[2]= v1[2]-v2[2]; + n2[2]= v2[2]-v3[2]; + n[0]= n1[1]*n2[2]-n1[2]*n2[1]; + n[1]= n1[2]*n2[0]-n1[0]*n2[2]; + n[2]= n1[0]*n2[1]-n1[1]*n2[0]; +} + +static void CalcFloat4( float *v1, float *v2, float *v3, float *v4, float *n) +{ + /* real cross! */ + float n1[3],n2[3]; + + n1[0]= v1[0]-v3[0]; + n1[1]= v1[1]-v3[1]; + n1[2]= v1[2]-v3[2]; + + n2[0]= v2[0]-v4[0]; + n2[1]= v2[1]-v4[1]; + n2[2]= v2[2]-v4[2]; + + n[0]= n1[1]*n2[2]-n1[2]*n2[1]; + n[1]= n1[2]*n2[0]-n1[0]*n2[2]; + n[2]= n1[0]*n2[1]-n1[1]*n2[0]; +} + float calculateVertexWindForce(float wind[3], float vertexnormal[3]) { - return fabs(INPR(wind, vertexnormal)); + return (INPR(wind, vertexnormal)); } void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVector *lV, fmatrix3x3 *dFdV, fmatrix3x3 *dFdX, ListBase *effectors, float time, fmatrix3x3 *M) @@ -1368,11 +1402,9 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec float gravity[3]; float tm2[3][3] = {{-spring_air,0,0}, {0,-spring_air,0},{0,0,-spring_air}}; MFace *mfaces = cloth->mfaces; - //ClothVertex *verts = cloth->verts; - float wind_normalized[3]; unsigned int numverts = cloth->numverts; LinkNode *search = cloth->springs; - + lfVector *winvec; VECCOPY(gravity, clmd->sim_parms->gravity); mul_fvector_S(gravity, gravity, 0.001f); /* scale gravity force */ @@ -1399,70 +1431,61 @@ void cloth_calc_force(ClothModifierData *clmd, lfVector *lF, lfVector *lX, lfVec /* handle external forces like wind */ if(effectors) { - for(i = 0; i < cloth->numfaces; i++) + // 0 = force, 1 = normalized force + winvec = create_lfvector(cloth->numverts); + + if(!winvec) + printf("winvec: out of memory in implicit.c\n"); + + // precalculate wind forces + for(i = 0; i < cloth->numverts; i++) { - float vertexnormal[3]={0,0,0}; float speed[3] = {0.0f, 0.0f,0.0f}; - float force[3]= {0.0f, 0.0f, 0.0f}; + pdDoEffectors(effectors, lX[i], winvec[i], speed, (float)G.scene->r.cfra, 0.0f, 0); + } + + for(i = 0; i < cloth->numfaces; i++) + { + float trinormal[3]={0,0,0}; // normalized triangle normal + float triunnormal[3]={0,0,0}; // not-normalized-triangle normal + float tmp[3]={0,0,0}; + float factor = (mfaces[i].v4) ? 0.25 : 1.0 / 3.0; + factor *= 0.05; + + // calculate face normal if(mfaces[i].v4) - CalcNormFloat4(lX[mfaces[i].v1],lX[mfaces[i].v2],lX[mfaces[i].v3],lX[mfaces[i].v4],vertexnormal); + CalcFloat4(lX[mfaces[i].v1],lX[mfaces[i].v2],lX[mfaces[i].v3],lX[mfaces[i].v4],triunnormal); else - CalcNormFloat(lX[mfaces[i].v1],lX[mfaces[i].v2],lX[mfaces[i].v3],vertexnormal); + CalcFloat(lX[mfaces[i].v1],lX[mfaces[i].v2],lX[mfaces[i].v3],triunnormal); - pdDoEffectors(effectors, lX[mfaces[i].v1], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); - VECCOPY(wind_normalized, speed); - Normalize(wind_normalized); - VecMulf(wind_normalized, -calculateVertexWindForce(speed, vertexnormal)); + VECCOPY(trinormal, triunnormal); + Normalize(trinormal); - if(mfaces[i].v4) - { - VECADDS(lF[mfaces[i].v1], lF[mfaces[i].v1], wind_normalized, 0.25); - } - else - { - VECADDS(lF[mfaces[i].v1], lF[mfaces[i].v1], wind_normalized, 1.0 / 3.0); - } + // add wind from v1 + VECCOPY(tmp, trinormal); + VecMulf(tmp, calculateVertexWindForce(winvec[mfaces[i].v1], triunnormal)); + VECADDS(lF[mfaces[i].v1], lF[mfaces[i].v1], tmp, factor); - speed[0] = speed[1] = speed[2] = 0.0; - pdDoEffectors(effectors, lX[mfaces[i].v2], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); - VECCOPY(wind_normalized, speed); - Normalize(wind_normalized); - VecMulf(wind_normalized, -calculateVertexWindForce(speed, vertexnormal)); - if(mfaces[i].v4) - { - VECADDS(lF[mfaces[i].v2], lF[mfaces[i].v2], wind_normalized, 0.25); - } - else - { - VECADDS(lF[mfaces[i].v2], lF[mfaces[i].v2], wind_normalized, 1.0 / 3.0); - } + // add wind from v2 + VECCOPY(tmp, trinormal); + VecMulf(tmp, calculateVertexWindForce(winvec[mfaces[i].v2], triunnormal)); + VECADDS(lF[mfaces[i].v2], lF[mfaces[i].v2], tmp, factor); - speed[0] = speed[1] = speed[2] = 0.0; - pdDoEffectors(effectors, lX[mfaces[i].v3], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); - VECCOPY(wind_normalized, speed); - Normalize(wind_normalized); - VecMulf(wind_normalized, -calculateVertexWindForce(speed, vertexnormal)); - if(mfaces[i].v4) - { - VECADDS(lF[mfaces[i].v3], lF[mfaces[i].v3], wind_normalized, 0.25); - } - else - { - VECADDS(lF[mfaces[i].v3], lF[mfaces[i].v3], wind_normalized, 1.0 / 3.0); - } + // add wind from v3 + VECCOPY(tmp, trinormal); + VecMulf(tmp, calculateVertexWindForce(winvec[mfaces[i].v3], triunnormal)); + VECADDS(lF[mfaces[i].v3], lF[mfaces[i].v3], tmp, factor); - speed[0] = speed[1] = speed[2] = 0.0; + // add wind from v4 if(mfaces[i].v4) { - pdDoEffectors(effectors, lX[mfaces[i].v4], force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED); - VECCOPY(wind_normalized, speed); - Normalize(wind_normalized); - VecMulf(wind_normalized, -calculateVertexWindForce(speed, vertexnormal)); - VECADDS(lF[mfaces[i].v4], lF[mfaces[i].v4], wind_normalized, 0.25); + VECCOPY(tmp, trinormal); + VecMulf(tmp, calculateVertexWindForce(winvec[mfaces[i].v4], triunnormal)); + VECADDS(lF[mfaces[i].v4], lF[mfaces[i].v4], tmp, factor); } - } + del_lfvector(winvec); } // calculate spring forces diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 942c6505975..60fdbca2021 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2205,177 +2205,6 @@ static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra) return 1; } -/************************************************/ -/* Effectors */ -/************************************************/ -static float falloff_func(float fac, int usemin, float mindist, int usemax, float maxdist, float power) -{ - if(!usemin) - mindist= 0.0f; - - if(fac < mindist) { - return 1.0f; - } - else if(usemax) { - if(fac>maxdist || (maxdist-mindist)<=0.0f) - return 0.0f; - - fac= (fac-mindist)/(maxdist-mindist); - return 1.0f - (float)pow((double)fac, (double)power); - } - else - return pow((double)1.0f+fac-mindist, (double)-power); -} - -static float falloff_func_dist(PartDeflect *pd, float fac) -{ - return falloff_func(fac, pd->flag&PFIELD_USEMIN, pd->mindist, pd->flag&PFIELD_USEMAX, pd->maxdist, pd->f_power); -} - -static float falloff_func_rad(PartDeflect *pd, float fac) -{ - return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r); -} - -static float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part) -{ - float eff_dir[3], temp[3]; - float falloff=1.0, fac, r_fac; - - VecCopyf(eff_dir,eff_velocity); - Normalize(eff_dir); - - if(pd->flag & PFIELD_POSZ && Inpf(eff_dir,vec_to_part)<0.0f) - falloff=0.0f; - else switch(pd->falloff){ - case PFIELD_FALL_SPHERE: - fac=VecLength(vec_to_part); - falloff= falloff_func_dist(pd, fac); - break; - - case PFIELD_FALL_TUBE: - fac=Inpf(vec_to_part,eff_dir); - falloff= falloff_func_dist(pd, ABS(fac)); - if(falloff == 0.0f) - break; - - VECADDFAC(temp,vec_to_part,eff_dir,-fac); - r_fac=VecLength(temp); - falloff*= falloff_func_rad(pd, r_fac); - break; - case PFIELD_FALL_CONE: - fac=Inpf(vec_to_part,eff_dir); - falloff= falloff_func_dist(pd, ABS(fac)); - if(falloff == 0.0f) - break; - - r_fac=saacos(fac/VecLength(vec_to_part))*180.0f/(float)M_PI; - falloff*= falloff_func_rad(pd, r_fac); - - break; -// case PFIELD_FALL_INSIDE: - //for(i=0; iv1].co); - // VECCOPY(v2,mvert[mface->v2].co); - // VECCOPY(v3,mvert[mface->v3].co); - - // if(AxialLineIntersectsTriangle(a,co1, co2, v2, v3, v1, &lambda)){ - // if(from==PART_FROM_FACE) - // (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; - // else /* store number of intersections */ - // (pa+(int)(lambda*size[a])*a0mul)->loop++; - // } - // - // if(mface->v4){ - // VECCOPY(v4,mvert[mface->v4].co); - - // if(AxialLineIntersectsTriangle(a,co1, co2, v4, v1, v3, &lambda)){ - // if(from==PART_FROM_FACE) - // (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; - // else - // (pa+(int)(lambda*size[a])*a0mul)->loop++; - // } - // } - //} - -// break; - } - - return falloff; -} -static void do_physical_effector(short type, float force_val, float distance, float falloff, float size, float damp, - float *eff_velocity, float *vec_to_part, float *velocity, float *field, int planar) -{ - float mag_vec[3]={0,0,0}; - float temp[3], temp2[3]; - float eff_vel[3]; - - VecCopyf(eff_vel,eff_velocity); - Normalize(eff_vel); - - switch(type){ - case PFIELD_WIND: - VECCOPY(mag_vec,eff_vel); - - VecMulf(mag_vec,force_val*falloff); - VecAddf(field,field,mag_vec); - break; - - case PFIELD_FORCE: - if(planar) - Projf(mag_vec,vec_to_part,eff_vel); - else - VecCopyf(mag_vec,vec_to_part); - - VecMulf(mag_vec,force_val*falloff); - VecAddf(field,field,mag_vec); - break; - - case PFIELD_VORTEX: - Crossf(mag_vec,eff_vel,vec_to_part); - Normalize(mag_vec); - - VecMulf(mag_vec,force_val*distance*falloff); - VecAddf(field,field,mag_vec); - - break; - case PFIELD_MAGNET: - if(planar) - VecCopyf(temp,eff_vel); - else - /* magnetic field of a moving charge */ - Crossf(temp,eff_vel,vec_to_part); - - Crossf(temp2,velocity,temp); - VecAddf(mag_vec,mag_vec,temp2); - - VecMulf(mag_vec,force_val*falloff); - VecAddf(field,field,mag_vec); - break; - case PFIELD_HARMONIC: - if(planar) - Projf(mag_vec,vec_to_part,eff_vel); - else - VecCopyf(mag_vec,vec_to_part); - - VecMulf(mag_vec,force_val*falloff); - VecSubf(field,field,mag_vec); - - VecCopyf(mag_vec,velocity); - /* 1.9 is an experimental value to get critical damping at damp=1.0 */ - VecMulf(mag_vec,damp*1.9f*(float)sqrt(force_val)); - VecSubf(field,field,mag_vec); - break; - case PFIELD_NUCLEAR: - /*pow here is root of cosine expression below*/ - //rad=(float)pow(2.0,-1.0/power)*distance/size; - //VECCOPY(mag_vec,vec_to_part); - //Normalize(mag_vec); - //VecMulf(mag_vec,(float)cos(3.0*M_PI/2.0*(1.0-1.0/(pow(rad,power)+1.0)))/(rad+0.2f)); - //VECADDFAC(field,field,mag_vec,force_val); - break; - } -} static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, short object, float *pa_co, float obmat[4][4], float force_val, float falloff, float *field) { TexResult result[4]; @@ -2788,7 +2617,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P } else { do_physical_effector(pd->forcefield,pd->f_strength,distance, falloff,pd->f_dist,pd->f_damp,eob->obmat[2],vec_to_part, - pa->state.vel,force_field,pd->flag&PFIELD_PLANAR); + pa->state.vel,force_field,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise); } } if(ec->type & PSYS_EC_PARTICLE){ @@ -2837,7 +2666,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P else do_physical_effector(pd->forcefield,pd->f_strength,distance, falloff,epart->size,pd->f_damp,estate.vel,vec_to_part, - state->vel,force_field,0); + state->vel,force_field,0, pd->rng, pd->f_noise); } else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ diff --git a/source/blender/blenlib/BLI_rand.h b/source/blender/blenlib/BLI_rand.h index 0e534783c17..266aa347aff 100644 --- a/source/blender/blenlib/BLI_rand.h +++ b/source/blender/blenlib/BLI_rand.h @@ -44,6 +44,7 @@ struct RNG* rng_new (unsigned int seed); void rng_free (struct RNG* rng); void rng_seed (struct RNG* rng, unsigned int seed); +void rng_srandom(struct RNG *rng, unsigned int seed); int rng_getInt (struct RNG* rng); double rng_getDouble (struct RNG* rng); float rng_getFloat (struct RNG* rng); diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index ccc478203fe..c484a307393 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -81,6 +81,16 @@ void rng_seed(RNG *rng, unsigned int seed) { rng->X= (((r_uint64) seed)<<16) | LOWSEED; } +void rng_srandom(RNG *rng, unsigned int seed) { + extern unsigned char hash[]; // noise.c + + rng_seed(rng, seed + hash[seed & 255]); + seed= rng_getInt(rng); + rng_seed(rng, seed + hash[seed & 255]); + seed= rng_getInt(rng); + rng_seed(rng, seed + hash[seed & 255]); +} + int rng_getInt(RNG *rng) { rng->X= (MULTIPLIER*rng->X + ADDEND)&MASK; return (int) (rng->X>>17); @@ -132,13 +142,7 @@ void BLI_srand(unsigned int seed) { /* using hash table to create better seed */ void BLI_srandom(unsigned int seed) { - extern unsigned char hash[]; // noise.c - - rng_seed(&theBLI_rng, seed + hash[seed & 255]); - seed= rng_getInt(&theBLI_rng); - rng_seed(&theBLI_rng, seed + hash[seed & 255]); - seed= rng_getInt(&theBLI_rng); - rng_seed(&theBLI_rng, seed + hash[seed & 255]); + rng_srandom(&theBLI_rng, seed); } int BLI_rand(void) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 495a35bbe4c..62e048dc2ee 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7730,31 +7730,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) idproperties_fix_group_lengths(main->brush); idproperties_fix_group_lengths(main->particle); } - - /* only needed until old bad svn/RC1,2 files are saved with a > 17 version -dg */ - if(main->versionfile == 245 && main->subversionfile < 17) { - ModifierData *md; - Object *ob; - - for(ob = main->object.first; ob; ob= ob->id.next) { - for(md=ob->modifiers.first; md; ) { - if(md->type==eModifierType_Cloth) { - ModifierData *next; - MEM_freeN(((ClothModifierData *)md)->sim_parms); - MEM_freeN(((ClothModifierData *)md)->coll_parms); - MEM_freeN(((ClothModifierData *)md)->point_cache); - ((ClothModifierData *)md)->sim_parms = NULL; - ((ClothModifierData *)md)->coll_parms = NULL; - ((ClothModifierData *)md)->point_cache = NULL; - next=md->next; - BLI_remlink(&ob->modifiers, md); - md = next; - } - else - md = md->next; - } - } - } /* sun/sky */ if(main->versionfile < 246) { @@ -7781,6 +7756,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for(me=main->mesh.first; me; me= me->id.next) alphasort_version_246(fd, lib, me); } + + if(main->versionfile <= 246 && main->subversionfile < 1){ + Object *ob; + for(ob = main->object.first; ob; ob= ob->id.next) { + if(ob->pd && (ob->pd->forcefield == PFIELD_WIND)) + ob->pd->f_noise = 0.0; + } + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index dc6c2bcbcc0..5f6ae7c7f06 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -67,6 +67,9 @@ typedef struct PartDeflect { float tex_nabla; short tex_mode, kink, kink_axis, rt2; struct Tex *tex; /* Texture of the texture effector */ + struct RNG *rng; /* random noise generator for e.g. wind */ + float f_noise; /* noise of force (currently used for wind) */ + int pad; } PartDeflect; typedef struct PointCache { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 58f3bff09c8..71b29478f89 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3411,6 +3411,8 @@ static void object_panel_fields(Object *ob) } else if(pd->forcefield == PFIELD_HARMONIC) uiDefButF(block, NUM, B_FIELD_CHANGE, "Damp: ", 10,120,140,20, &pd->f_damp, 0, 10, 10, 0, "Damping of the harmonic force"); + else if(pd->forcefield == PFIELD_WIND) + uiDefButF(block, NUM, B_FIELD_CHANGE, "Noise: ",10,120,140,20, &pd->f_noise, 0, 10, 100, 0, "Noise of the wind force"); } uiBlockEndAlign(block); -- cgit v1.2.3