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

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to