[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16168] trunk/blender/source/blender: a) New unified effector system by Janne (jahka) + Me (genscher): particle and cloth/sb don't use different systems anymore.
Daniel Genrich
daniel.genrich at gmx.net
Mon Aug 18 13:09:27 CEST 2008
Revision: 16168
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16168
Author: genscher
Date: 2008-08-18 13:09:27 +0200 (Mon, 18 Aug 2008)
Log Message:
-----------
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 :)
Modified Paths:
--------------
trunk/blender/source/blender/blenkernel/BKE_effect.h
trunk/blender/source/blender/blenkernel/intern/effect.c
trunk/blender/source/blender/blenkernel/intern/implicit.c
trunk/blender/source/blender/blenkernel/intern/particle_system.c
trunk/blender/source/blender/blenlib/BLI_rand.h
trunk/blender/source/blender/blenlib/intern/rand.c
trunk/blender/source/blender/blenloader/intern/readfile.c
trunk/blender/source/blender/makesdna/DNA_object_force.h
trunk/blender/source/blender/src/buttons_object.c
Modified: trunk/blender/source/blender/blenkernel/BKE_effect.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_effect.h 2008-08-18 10:48:37 UTC (rev 16167)
+++ trunk/blender/source/blender/blenkernel/BKE_effect.h 2008-08-18 11:09:27 UTC (rev 16168)
@@ -37,6 +37,7 @@
struct ListBase;
struct Particle;
struct Group;
+struct RNG;
typedef struct pEffectorCache {
struct pEffectorCache *next, *prev;
@@ -64,7 +65,12 @@
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
Modified: trunk/blender/source/blender/blenkernel/intern/effect.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/effect.c 2008-08-18 10:48:37 UTC (rev 16167)
+++ trunk/blender/source/blender/blenkernel/intern/effect.c 2008-08-18 11:09:27 UTC (rev 16168)
@@ -157,6 +157,13 @@
}
}
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 @@
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 @@
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 @@
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;
+ where_is_object_time(ob,cur_time);
- /* 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;
- }
-
/* 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) && distance<pd->mindist && pd->forcefield != PFIELD_GUIDE)
- ; /* 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];
+
+ VecSubf(vec_to_part, opco, ob->obmat[3]);
+ distance = VecLength(vec_to_part);
- /* Now calculate the gravitational force */
- VECSUB(vect_to_vert, obloc, opco);
- distance = VecLength(vect_to_vert);
+ falloff=effector_falloff(pd,ob->obmat[2],vec_to_part);
- /* 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];
+ if(falloff<=0.0f)
+ ; /* don't do anything */
+ 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);
- /* 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;
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list