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 :)

This commit is contained in:
Daniel Genrich 2008-08-18 11:09:27 +00:00
parent a84d346939
commit d5a890c078
9 changed files with 316 additions and 431 deletions

@ -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

@ -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)
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->flag & PFIELD_USEMIN) && distance<pd->mindist && pd->forcefield != PFIELD_GUIDE)
; /* don't do anything */
else if(pd->forcefield == PFIELD_WIND) {
VECCOPY(force_vec, ob->obmat[2]);
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);
/* 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;
// for softbody backward compatibility
if(flags & PE_WIND_AS_SPEED){
VECSUB(tmp, force, field);
VECSUB(speed, speed, tmp);
}
}
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 );
/* 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);
}
}
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

@ -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)
{
// 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 speed[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 vertexnormal[3]={0,0,0};
float speed[3] = {0.0f, 0.0f,0.0f};
float force[3]= {0.0f, 0.0f, 0.0f};
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);
// 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);
// 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);
// 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);
// add wind from v4
if(mfaces[i].v4)
{
VECADDS(lF[mfaces[i].v1], lF[mfaces[i].v1], 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);
}
else
{
VECADDS(lF[mfaces[i].v1], lF[mfaces[i].v1], wind_normalized, 1.0 / 3.0);
}
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);
}
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);
}
speed[0] = speed[1] = speed[2] = 0.0;
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);
}
}
del_lfvector(winvec);
}
// calculate spring forces

@ -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; i<totface; i++,mface++){
// VECCOPY(v1,mvert[mface->v1].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 */

@ -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);

@ -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) {

@ -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! */

@ -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 {

@ -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);