New things for particle effectors:
authorJanne Karhu <jhkarh@gmail.com>
Thu, 21 Aug 2008 21:12:27 +0000 (21:12 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Thu, 21 Aug 2008 21:12:27 +0000 (21:12 +0000)
- For newtonian particles a "self effect" button in particle extras makes the particles be effected by themselves if a particle effector is defined for this system, currently this is a brute force method so things start getting slow with more than ~100 particles, but this will hopefully change in the future.
- Two new effector types: charge and a Lennard-Jones potential based force (inter-molecular forces for example).
   -Charge is similar to spherical field except it changes behavior (attract/repulse) based on the effected particles charge field (negative/positive) like real particles with a charge.
   -The Lennard-Jones field is a very short range force with a behavior determined by the sizes of the effector and effected particle. At a distance smaller than the combined sizes the field is very repulsive and after that distance it's attractive. It tries to keep the particles at an equilibrium distance from each other. Particles need to be at a close proximity to each other to be effected by this field at all.
- Particle systems can now have two effector fields (two slots in the fields panel). This allows to create particles which for example have both a charge and a Lennard-Jones potential.

13 files changed:
source/blender/blenkernel/BKE_effect.h
source/blender/blenkernel/intern/effect.c
source/blender/blenkernel/intern/ipo.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/makesdna/DNA_ipo_types.h
source/blender/makesdna/DNA_object_force.h
source/blender/makesdna/DNA_particle_types.h
source/blender/src/buttons_object.c
source/blender/src/editipo.c
source/blender/src/editipo_lib.c

index 5d3a0fba45f4745c10b67836313aee7d13eeecb9..6475f7a71ac12a5b7eb4db0f6b2d3f3e82d7ad14 100644 (file)
@@ -66,7 +66,7 @@ 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(Object *ob, float *opco, 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_factor);
+void do_physical_effector(Object *ob, float *opco, 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_factor, float charge, float pa_size);
 float effector_falloff(struct PartDeflect *pd, float *eff_velocity, float *vec_to_part);
 
 
index accc16ea940fbbc88d1163e25ad0f0c4a2fa4805..0842e55a0eaa51a7d829e1894f76156c61b06371 100644 (file)
@@ -332,7 +332,10 @@ 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;
-       
+
+       if(pd->forcefield==PFIELD_LENNARDJ)
+               return falloff; /* Lennard-Jones field has it's own falloff built in */
+
        VecCopyf(eff_dir,eff_velocity);
        Normalize(eff_dir);
 
@@ -369,7 +372,7 @@ float effector_falloff(PartDeflect *pd, float *eff_velocity, float *vec_to_part)
        return falloff;
 }
 
-void do_physical_effector(Object *ob, float *opco, 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_factor)
+void do_physical_effector(Object *ob, float *opco, 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_factor, float charge, float pa_size)
 {
        float mag_vec[3]={0,0,0};
        float temp[3], temp2[3];
@@ -442,14 +445,44 @@ void do_physical_effector(Object *ob, float *opco, short type, float force_val,
                        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);
+               case PFIELD_CHARGE:
+                       if(planar)
+                               Projf(mag_vec,vec_to_part,eff_vel);
+                       else
+                               VecCopyf(mag_vec,vec_to_part);
+
+                       VecMulf(mag_vec,charge*force_val*falloff);
+                       VecAddf(field,field,mag_vec);
+                       break;
+               case PFIELD_LENNARDJ:
+               {
+                       float fac;
+
+                       if(planar) {
+                               Projf(mag_vec,vec_to_part,eff_vel);
+                               distance = VecLength(mag_vec);
+                       }
+                       else
+                               VecCopyf(mag_vec,vec_to_part);
+
+                       /* at this distance the field is 60 times weaker than maximum */
+                       if(distance > 2.22 * (size+pa_size))
+                               break;
+
+                       fac = pow((size+pa_size)/distance,6.0);
+                       
+                       fac = - fac * (1.0 - fac) / distance;
+
+                       /* limit the repulsive term drastically to avoid huge forces */
+                       fac = ((fac>2.0) ? 2.0 : fac);
+
+                       /* 0.003715 is the fac value at 2.22 times (size+pa_size),
+                          substracted to avoid discontinuity at the border
+                       */
+                       VecMulf(mag_vec, force_val * (fac-0.0037315));
+                       VecAddf(field,field,mag_vec);
                        break;
+               }
        }
 }
 
@@ -518,7 +551,7 @@ void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float
                        VECCOPY(field, force);
                        do_physical_effector(ob, opco, 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);
+                                                               speed,force,pd->flag&PFIELD_PLANAR, pd->rng, pd->f_noise, 0.0f, 0.0f);
                        
                        // for softbody backward compatibility
                        if(flags & PE_WIND_AS_SPEED){
index fe92edfbbd5eaeeabccb59c0749f84fbf0714f4d..4af25ee99e713d14c7796ec55cb579476a2f59ae 100644 (file)
@@ -182,7 +182,7 @@ int part_ar[PART_TOTIPO]= {
        PART_EMIT_FREQ, PART_EMIT_LIFE, PART_EMIT_VEL, PART_EMIT_AVE, PART_EMIT_SIZE,
        PART_AVE, PART_SIZE, PART_DRAG, PART_BROWN, PART_DAMP, PART_LENGTH, PART_CLUMP,
     PART_GRAV_X, PART_GRAV_Y, PART_GRAV_Z, PART_KINK_AMP, PART_KINK_FREQ, PART_KINK_SHAPE,
-       PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD
+       PART_BB_TILT, PART_PD_FSTR, PART_PD_FFALL, PART_PD_FMAXD, PART_PD2_FSTR, PART_PD2_FFALL, PART_PD2_FMAXD
 };
 
 
@@ -1614,6 +1614,12 @@ void *get_ipo_poin(ID *id, IpoCurve *icu, int *type)
                        poin= (part->pd?(&(part->pd->f_power)):NULL); break;
                case PART_PD_FMAXD:
                        poin= (part->pd?(&(part->pd->maxdist)):NULL); break;
+               case PART_PD2_FSTR:
+                       poin= (part->pd2?(&(part->pd2->f_strength)):NULL); break;
+               case PART_PD2_FFALL:
+                       poin= (part->pd2?(&(part->pd2->f_power)):NULL); break;
+               case PART_PD2_FMAXD:
+                       poin= (part->pd2?(&(part->pd2->maxdist)):NULL); break;
                }
        }
 
index 643f90637ad7c034d16ef5772629ecf6c702b491..2f4696fc442189c373c8d00bcdd12bc4d4680713 100644 (file)
@@ -320,8 +320,14 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
 /************************************************/
 void psys_free_settings(ParticleSettings *part)
 {
-       if(part->pd)
+       if(part->pd) {
                MEM_freeN(part->pd);
+               part->pd = NULL;
+       }
+       if(part->pd2) {
+               MEM_freeN(part->pd2);
+               part->pd2 = NULL;
+       }
 }
 
 void free_hair(ParticleSystem *psys, int softbody)
@@ -3015,6 +3021,7 @@ ParticleSettings *psys_copy_settings(ParticleSettings *part)
        
        partn= copy_libblock(part);
        if(partn->pd) partn->pd= MEM_dupallocN(part->pd);
+       if(partn->pd2) partn->pd2= MEM_dupallocN(part->pd2);
        
        return partn;
 }
index 8e5b011211b21a3a8383a57a90cb169f393de87d..ef8373ee977f7e34f1c24e3bc37a64ebf77bed6b 100644 (file)
@@ -2206,6 +2206,9 @@ static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra)
        return 1;
 }
 
+/************************************************/
+/*                     Effectors                                                       */
+/************************************************/
 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];
@@ -2323,10 +2326,11 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy
 
                for(i=0; epsys; epsys=epsys->next,i++){
                        type=0;
-                       if(epsys!=psys){
+                       if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
                                epart=epsys->part;
 
-                               if(epsys->part->pd && epsys->part->pd->forcefield)
+                               if((epsys->part->pd && epsys->part->pd->forcefield)
+                                       || (epsys->part->pd2 && epsys->part->pd2->forcefield))
                                        type=PSYS_EC_PARTICLE;
 
                                if(epart->type==PART_REACTOR) {
@@ -2575,35 +2579,31 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
        ListBase *lb=&psys->effectors;
        ParticleEffectorCache *ec;
        float distance, vec_to_part[3];
-       float falloff;
+       float falloff, charge = 0.0f;
        int p;
 
        /* check all effector objects for interaction */
        if(lb->first){
+               if(psys->part->pd && psys->part->pd->forcefield==PFIELD_CHARGE){
+                       /* Only the charge of the effected particle is used for 
+                          interaction, not fall-offs. If the fall-offs aren't the      
+                          same this will be unphysical, but for animation this         
+                          could be the wanted behavior. If you want physical
+                          correctness the fall-off should be spherical 2.0 anyways.
+                        */
+                       charge = psys->part->pd->f_strength;
+               }
+               if(psys->part->pd2 && psys->part->pd2->forcefield==PFIELD_CHARGE){
+                       charge += psys->part->pd2->f_strength;
+               }
                for(ec = lb->first; ec; ec= ec->next){
                        eob= ec->ob;
                        if(ec->type & PSYS_EC_EFFECTOR){
                                pd=eob->pd;
                                if(psys->part->type!=PART_HAIR && psys->part->integrator)
                                        where_is_object_time(eob,cfra);
-                               /* Get IPO force strength and fall off values here */
-                               //if (has_ipo_code(eob->ipo, OB_PD_FSTR))
-                               //      force_val = IPO_GetFloatValue(eob->ipo, OB_PD_FSTR, cfra);
-                               //else 
-                               //      force_val = pd->f_strength;
-                               
-                               //if (has_ipo_code(eob->ipo, OB_PD_FFALL)) 
-                               //      ffall_val = IPO_GetFloatValue(eob->ipo, OB_PD_FFALL, cfra);
-                               //else 
-                               //      ffall_val = pd->f_power;
-
-                               //if (has_ipo_code(eob->ipo, OB_PD_FMAXD)) 
-                               //      maxdist = IPO_GetFloatValue(eob->ipo, OB_PD_FMAXD, cfra);
-                               //else 
-                               //      maxdist = pd->maxdist;
 
                                /* use center of object for distance calculus */
-                               //obloc= eob->obmat[3];
                                VecSubf(vec_to_part, state->co, eob->obmat[3]);
                                distance = VecLength(vec_to_part);
 
@@ -2617,21 +2617,21 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                                                        pd->f_strength, falloff, force_field);
                                } else {
                                        do_physical_effector(eob, state->co, 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, pd->rng, pd->f_noise);
+                                                                               falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part,
+                                                                               pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,pd->rng,pd->f_noise,charge,pa->size);
                                }
                        }
                        if(ec->type & PSYS_EC_PARTICLE){
-                               int totepart;
+                               int totepart, i;
                                epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr);
                                epart= epsys->part;
-                               pd= epart->pd;
+                               pd=epart->pd;
                                totepart= epsys->totpart;
                                
                                if(totepart <= 0)
                                        continue;
                                
-                               if(pd->forcefield==PFIELD_HARMONIC){
+                               if(pd && pd->forcefield==PFIELD_HARMONIC){
                                        /* every particle is mapped to only one harmonic effector particle */
                                        p= pa_no%epsys->totpart;
                                        totepart= p+1;
@@ -2643,31 +2643,27 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                epsys->lattice=psys_get_lattice(ob,psys);
 
                                for(; p<totepart; p++){
+                                       /* particle skips itself as effector */
+                                       if(epsys==psys && p == pa_no) continue;
+
                                        epa = epsys->particles + p;
                                        estate.time=-1.0;
                                        if(psys_get_particle_state(eob,epsys,p,&estate,0)){
                                                VECSUB(vec_to_part, state->co, estate.co);
                                                distance = VecLength(vec_to_part);
-
-                                               //if(pd->forcefield==PFIELD_HARMONIC){
-                                               //      //if(cfra < epa->time + radius){ /* radius is fade-in in ui */
-                                               //      //      eforce*=(cfra-epa->time)/radius;
-                                               //      //}
-                                               //}
-                                               //else{
-                                               //      /* Limit minimum distance to effector particle so that */
-                                               //      /* the force is not too big */
-                                               //      if (distance < 0.001) distance = 0.001f;
-                                               //}
                                                
-                                               falloff=effector_falloff(pd,estate.vel,vec_to_part);
+                                               for(i=0, pd = epart->pd; i<2; i++,pd = epart->pd2) {
+                                                       if(pd==NULL || pd->forcefield==0) continue;
 
-                                               if(falloff<=0.0f)
-                                                       ;       /* don't do anything */
-                                               else
-                                                       do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
-                                                       falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
-                                                       state->vel,force_field,0, pd->rng, pd->f_noise);
+                                                       falloff=effector_falloff(pd,estate.vel,vec_to_part);
+
+                                                       if(falloff<=0.0f)
+                                                               ;       /* don't do anything */
+                                                       else
+                                                               do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
+                                                               falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
+                                                               state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size);
+                                               }
                                        }
                                        else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){
                                                /* first step after key release */
index ba8cdca0a8337b257252d839c8c197996ac5383f..a5c30f260083081d51eafa3616ff5c5302390955 100644 (file)
@@ -2582,6 +2582,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main)
 static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
 {
        part->pd= newdataadr(fd, part->pd);
+       part->pd2= newdataadr(fd, part->pd2);
 }
 
 static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles)
index b462233528aa5b10016dc9f2e4e9eb2162d6b347..d596f57990f0b1f22279776340325cf655a70387 100644 (file)
@@ -535,6 +535,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
                        writestruct(wd, ID_PA, "ParticleSettings", 1, part);
                        if (part->id.properties) IDP_WriteProperty(part->id.properties, wd);
                        writestruct(wd, DATA, "PartDeflect", 1, part->pd);
+                       writestruct(wd, DATA, "PartDeflect", 1, part->pd2);
                }
                part= part->id.next;
        }
index 03ffef3cd55e3e91dbd024146a39b9d0935d9eab..1e30f3f7640a2b0eaebd95b184a4064667162c10 100644 (file)
@@ -354,8 +354,8 @@ typedef short IPO_Channel;
 
 /* ******************** */
 /* particle ipos */
-#define PART_TOTIPO            22
-#define PART_TOTNAM            22
+#define PART_TOTIPO            25
+#define PART_TOTNAM            25
 
 #define PART_EMIT_FREQ 1
 #define PART_EMIT_LIFE 2
@@ -385,6 +385,10 @@ typedef short IPO_Channel;
 #define PART_PD_FFALL  21
 #define PART_PD_FMAXD  22
 
+#define PART_PD2_FSTR  23
+#define PART_PD2_FFALL 24
+#define PART_PD2_FMAXD 25
+
 
 /* these are IpoCurve specific */
 /* **************** IPO ********************* */
index 5f6ae7c7f06922c00f2e0030434f4cbe08f76b75..5900e16d5e804f7a3e7420f8fac9b48e719bef6c 100644 (file)
@@ -156,8 +156,8 @@ typedef struct SoftBody {
 #define PFIELD_GUIDE   5
 #define PFIELD_TEXTURE 6
 #define PFIELD_HARMONIC        7
-#define PFIELD_NUCLEAR 8
-#define PFIELD_MDIPOLE 9
+#define PFIELD_CHARGE  8
+#define PFIELD_LENNARDJ        9
 
 
 /* pd->flag: various settings */
index 4f62cd084cc9b0ca0095635d1ab4d3276ea15bb5..363f0075e23f20513446ee353d28313b418fc908 100644 (file)
@@ -166,6 +166,7 @@ typedef struct ParticleSettings {
        struct Object *bb_ob;
        struct Ipo *ipo;
        struct PartDeflect *pd;
+       struct PartDeflect *pd2;
 } ParticleSettings;
 
 typedef struct ParticleSystem{                         /* note, make sure all (runtime) are NULL's in copy_particlesystem */
@@ -264,6 +265,8 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 #define PART_CHILD_RENDER      (1<<29)
 #define PART_CHILD_GUIDE       (1<<30)
 
+#define PART_SELF_EFFECT       (1<<22)
+
 /* part->rotfrom */
 #define PART_ROT_KEYS          0       /* interpolate directly from keys */
 #define PART_ROT_ZINCR         1       /* same as zdir but done incrementally from previous position */
index 98476cb5cd3cc44fe2470bd099fcaa4830023ed0..b0d612456d22ed191a9b24c6344f7557c2d5538b 100644 (file)
@@ -3317,6 +3317,7 @@ static void object_panel_fields(Object *ob)
        uiBut *but;
        int particles=0;
        static short actpsys=-1;
+       static char slot=0;
 
        block= uiNewBlock(&curarea->uiblocks, "object_panel_fields", UI_EMBOSS, UI_HELV, curarea->win);
        if(uiNewPanel(curarea, block, "Fields", "Physics", 0, 0, 318, 204)==0) return;
@@ -3338,7 +3339,7 @@ static void object_panel_fields(Object *ob)
                char *tipstr="Choose field type";
 
                uiBlockBeginAlign(block);
-               
+
                if(ob->particlesystem.first) {
                        ParticleSystem *psys;
                        char *menustr2= psys_menu_string(ob,1);
@@ -3350,8 +3351,16 @@ static void object_panel_fields(Object *ob)
                                if(psys->part->pd==NULL)
                                        psys->part->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
 
-                               pd= psys->part->pd;
+                               if(psys->part->pd2==NULL)
+                                       psys->part->pd2= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
+
+                               pd= ((slot==1) ? psys->part->pd2 : psys->part->pd);
                                particles=1;
+
+                               uiDefButC(block, ROW, B_REDR, "",       10, 163, 14, 14, &slot, 3.0, 0, 0, 0, "Edit first particle effector slot");
+                               uiDefButC(block, ROW, B_REDR, "",       24, 163, 14, 14, &slot, 3.0, 1, 0, 0, "Edit second particle effector slot");
+                               uiBlockEndAlign(block);
+                               uiBlockBeginAlign(block);
                        }
                        else
                                actpsys= -1; /* -1 = object */
@@ -3364,8 +3373,8 @@ static void object_panel_fields(Object *ob)
 
                /* setup menu button */
                if(particles){
-                       sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d", 
-                                       PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC);
+                       sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
+                                       PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_CHARGE, PFIELD_LENNARDJ);
 
                        if(pd->forcefield==PFIELD_FORCE) tipstr= "Particle attracts or repels particles (On shared object layers)";
                        else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of particle Z axis (On shared object layers)";
@@ -3373,11 +3382,11 @@ static void object_panel_fields(Object *ob)
                }
                else{
                        if(ob->type==OB_CURVE)
-                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Curve Guide%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d", 
-                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE);
+                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Curve Guide%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
+                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
                        else
-                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d", 
-                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE);
+                               sprintf(menustr, "Field Type%%t|None%%x0|Spherical%%x%d|Wind%%x%d|Vortex%%x%d|Magnetic%%x%d|Harmonic%%x%d|Texture%%x%d|Charge%%x%d|Lennard-Jones%%x%d", 
+                                               PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_MAGNET, PFIELD_HARMONIC, PFIELD_TEXTURE, PFIELD_CHARGE, PFIELD_LENNARDJ);
 
                        if(pd->forcefield==PFIELD_FORCE) tipstr= "Object center attracts or repels particles (On shared object layers)";
                        else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of Object Z axis (On shared object layers)";
@@ -3392,8 +3401,6 @@ static void object_panel_fields(Object *ob)
 
                uiBlockEndAlign(block);
                uiDefBut(block, LABEL, 0, "",160,180,150,2, NULL, 0.0, 0, 0, 0, "");
-
-               MEM_freeN(menustr);
                
                if(pd->forcefield) {
                        uiBlockBeginAlign(block);
@@ -3459,40 +3466,49 @@ static void object_panel_fields(Object *ob)
                                uiBlockEndAlign(block);
                        }
                        else{
-                               uiDefButS(block, MENU, B_FIELD_DEP, "Fall-off%t|Cone%x2|Tube%x1|Sphere%x0",     160,180,140,20, &pd->falloff, 0.0, 0.0, 0, 0, "Fall-off shape");
-                               if(pd->falloff==PFIELD_FALL_TUBE)
-                                       uiDefBut(block, LABEL, 0, "Longitudinal",               160,160,140,20, NULL, 0.0, 0, 0, 0, "");
-                               uiBlockBeginAlign(block);
-                               uiDefButBitS(block, TOG, PFIELD_POSZ, B_FIELD_CHANGE, "Pos",    160,140,40,20, &pd->flag, 0.0, 0, 0, 0, "Effect only in direction of positive Z axis");
-                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     200,140,100,20, &pd->f_power, 0, 10, 10, 0, "Falloff power (real gravitational falloff = 2)");
-                               uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use",  160,120,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
-                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,120,100,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
-                               uiDefButBitS(block, TOG, PFIELD_USEMIN, B_FIELD_CHANGE, "Use",  160,100,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum distance for the field's fall-off");
-                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,100,100,20, &pd->mindist, 0, 1000.0, 10, 0, "Minimum distance for the field's fall-off");
-                               uiBlockEndAlign(block);
-
-                               if(pd->falloff==PFIELD_FALL_TUBE){
-                                       uiDefBut(block, LABEL, 0, "Radial",             160,80,70,20, NULL, 0.0, 0, 0, 0, "");
-                                       uiBlockBeginAlign(block);
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum radial distance for the field to work");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,40,100,20, &pd->maxrad, 0, 1000.0, 10, 0, "Maximum radial distance for the field to work");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum radial distance for the field's fall-off");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,20,100,20, &pd->minrad, 0, 1000.0, 10, 0, "Minimum radial distance for the field's fall-off");
-                                       uiBlockEndAlign(block);
+                               if(pd->forcefield==PFIELD_LENNARDJ) {
+                                       uiDefBut(block, LABEL, 0, "Fall-off determined",                160,140,140,20, NULL, 0.0, 0, 0, 0, "");
+                                       uiDefBut(block, LABEL, 0, "by particle sizes",          160,120,140,20, NULL, 0.0, 0, 0, 0, "");
                                }
-                               else if(pd->falloff==PFIELD_FALL_CONE){
-                                       uiDefBut(block, LABEL, 0, "Angular",            160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+                               else {
+                                       uiDefButS(block, MENU, B_FIELD_DEP, "Fall-off%t|Cone%x2|Tube%x1|Sphere%x0",     160,180,140,20, &pd->falloff, 0.0, 0.0, 0, 0, "Fall-off shape");
+                                       if(pd->falloff==PFIELD_FALL_TUBE)
+                                               uiDefBut(block, LABEL, 0, "Longitudinal",               160,160,140,20, NULL, 0.0, 0, 0, 0, "");
                                        uiBlockBeginAlign(block);
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum angle for the field to work");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxAngle: ",     200,40,100,20, &pd->maxrad, 0, 89.0, 10, 0, "Maximum angle for the field to work (in radians)");
-                                       uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum angle for the field's fall-off");
-                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MinAngle: ",     200,20,100,20, &pd->minrad, 0, 89.0, 10, 0, "Minimum angle for the field's fall-off (in radians)");
+                                       uiDefButBitS(block, TOG, PFIELD_POSZ, B_FIELD_CHANGE, "Pos",    160,140,40,20, &pd->flag, 0.0, 0, 0, 0, "Effect only in direction of positive Z axis");
+                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     200,140,100,20, &pd->f_power, 0, 10, 10, 0, "Falloff power (real gravitational falloff = 2)");
+                                       uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use",  160,120,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
+                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,120,100,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
+                                       uiDefButBitS(block, TOG, PFIELD_USEMIN, B_FIELD_CHANGE, "Use",  160,100,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum distance for the field's fall-off");
+                                       uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,100,100,20, &pd->mindist, 0, 1000.0, 10, 0, "Minimum distance for the field's fall-off");
                                        uiBlockEndAlign(block);
+
+                                       if(pd->falloff==PFIELD_FALL_TUBE){
+                                               uiDefBut(block, LABEL, 0, "Radial",             160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+                                               uiBlockBeginAlign(block);
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum radial distance for the field to work");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ",      200,40,100,20, &pd->maxrad, 0, 1000.0, 10, 0, "Maximum radial distance for the field to work");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum radial distance for the field's fall-off");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ",      200,20,100,20, &pd->minrad, 0, 1000.0, 10, 0, "Minimum radial distance for the field's fall-off");
+                                               uiBlockEndAlign(block);
+                                       }
+                                       else if(pd->falloff==PFIELD_FALL_CONE){
+                                               uiDefBut(block, LABEL, 0, "Angular",            160,80,70,20, NULL, 0.0, 0, 0, 0, "");
+                                               uiBlockBeginAlign(block);
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ",     160,60,140,20, &pd->f_power_r, 0, 10, 10, 0, "Radial falloff power (real gravitational falloff = 2)");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMAXR, B_FIELD_CHANGE, "Use", 160,40,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum angle for the field to work");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxAngle: ",     200,40,100,20, &pd->maxrad, 0, 89.0, 10, 0, "Maximum angle for the field to work (in radians)");
+                                               uiDefButBitS(block, TOG, PFIELD_USEMINR, B_FIELD_CHANGE, "Use", 160,20,40,20, &pd->flag, 0.0, 0, 0, 0, "Use a minimum angle for the field's fall-off");
+                                               uiDefButF(block, NUM, B_FIELD_CHANGE, "MinAngle: ",     200,20,100,20, &pd->minrad, 0, 89.0, 10, 0, "Minimum angle for the field's fall-off (in radians)");
+                                               uiBlockEndAlign(block);
+                                       }
                                }
                        }
+
                }       
+               
+               MEM_freeN(menustr);
        }
 }
 
@@ -4339,6 +4355,8 @@ static void object_panel_particle_extra(Object *ob)
                uiDefButBitI(block, TOG, PART_CHILD_EFFECT, B_PART_RECALC, "Children", butx+(butw*3)/5,buty,(butw*2)/5,buth, &part->flag, 0, 0, 0, 0, "Apply effectors to children");
                uiBlockEndAlign(block);
        }
+       else if(part->phystype == PART_PHYS_NEWTON)
+               uiDefButBitI(block, TOG, PART_SELF_EFFECT, B_PART_RECALC, "Self Effect",         butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Particle effectors effect themselves");
        else
                buty-=buth;
 
index aa7787c5905485ccea6f359f16f94d0348cc60bc..cd6aefdb87c72e1859b4f432bc117cd13a419364 100644 (file)
@@ -462,24 +462,7 @@ static void make_part_editipo(SpaceIpo *si)
                name = getname_part_ei(part_ar[a]);
                strcpy(ei->name, name);
                ei->adrcode= part_ar[a];
-               
-               //if(ei->adrcode & MA_MAP1) {
-               //      ei->adrcode-= MA_MAP1;
-               //      ei->adrcode |= texchannel_to_adrcode(si->channel);
-               //}
-               //else {
-               //      if(ei->adrcode==MA_MODE) ei->disptype= IPO_DISPBITS;
-               //}
-               
                ei->col= ipo_rainbow(a, PART_TOTIPO);
-               
-               //len= strlen(ei->name);
-               //if(len) {
-               //      if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
-               //      else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
-               //      else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
-               //}
-               
                ei->icu= find_ipocurve(si->ipo, ei->adrcode);
                if(ei->icu) {
                        ei->flag= ei->icu->flag;
index 7b3d439833eda033a69492bebfc63ce54a2bbfab..e1e286e10cf706f010e1b5f72c9c3dbc1ddcd82d 100644 (file)
@@ -103,7 +103,8 @@ char *ic_name_empty[1] ={ "" };
 char *fluidsim_ic_names[FLUIDSIM_TOTNAM] = { "Fac-Visc", "Fac-Time",  "GravX","GravY","GravZ",  "VelX","VelY","VelZ", "Active"  };
 char *part_ic_names[PART_TOTNAM] = { "E_Freq", "E_Life", "E_Speed", "E_Angular", "E_Size",
 "Angular", "Size", "Drag", "Brown", "Damp", "Length", "Clump",
-"GravX", "GravY", "GravZ", "KinkAmp", "KinkFreq", "KinkShape", "BBTilt", "FStreng", "FFall", "FMaxD"};
+"GravX", "GravY", "GravZ", "KinkAmp", "KinkFreq", "KinkShape", "BBTilt",
+"FStreng", "FFall", "FMaxD", "F2Streng", "F2Fall", "F2MaxD"};
 
 /* gets the appropriate icon for the given blocktype */
 int geticon_ipo_blocktype(short blocktype)