- Regarding the Peach "hair effectors" request in the mailing list I coded quick...
authorJanne Karhu <jhkarh@gmail.com>
Thu, 17 Jan 2008 00:28:14 +0000 (00:28 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Thu, 17 Jan 2008 00:28:14 +0000 (00:28 +0000)
- Keyed particles work again for all visualizations (previously only "path"), they still need some work though to be fully operational.
- Keyed particles weren't saved or loaded correctly.

source/blender/blenkernel/BKE_particle.h
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_particle_types.h
source/blender/src/buttons_object.c
source/blender/src/drawobject.c

index d92e8bad1f904c2f7dda159b0a89cd667db43667..399f67b728896531f3efd9737f869d958b9e656e 100644 (file)
@@ -289,6 +289,8 @@ void psys_particle_on_dm(struct Object *ob, struct DerivedMesh *dm, int from, in
 void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd);
 void reset_particle(struct ParticleData *pa, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct Object *ob, float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot);
 
+void do_effectors(int pa_no, struct ParticleData *pa, struct ParticleKey *state, struct Object *ob, struct ParticleSystem *psys, float *force_field, float *vel,float framestep, float cfra);
+
 void psys_calc_dmfaces(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys);
 int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node);
 
index 0ac60e6da4e8c82a19646dc76e6523876ba72487..8b6d6126124cfe6106b5112a6bf93382ed65a7fc 100644 (file)
@@ -2249,6 +2249,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
        char nosel[4], sel[4];
        float sel_col[3];
        float nosel_col[3];
+       float length, vec[3];
 
        /* we don't have anything valid to create paths from so let's quit here */
        if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0)
@@ -2417,7 +2418,6 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                                : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
                                ,keys, keytime, &result);
 
-
                        /* the velocity needs to be converted back from cubic interpolation */
                        if(psys->flag & PSYS_KEYED){
                                VecMulf(result.vel, frs_sec / dfra);
@@ -2425,12 +2425,49 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                        else if(soft==NULL) { /* softbody and keyed are allready in global space */
                                Mat4MulVecfl(hairmat, result.co);
                        }
-                       
+
+                       VECCOPY(ca->co, result.co);
+               }
+               
+               /*--modify paths--*/
+
+               VecSubf(vec,(cache[i]+1)->co,cache[i]->co);
+               length = VecLength(vec);
+
+               for(k=0, ca=cache[i]; k<=steps; k++, ca++) {
+                       /* apply effectors */
+                       if(edit==0 && k) {
+                               float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f};
+                               ParticleKey eff_key;
+
+                               VECCOPY(eff_key.co,(ca-1)->co);
+                               VECCOPY(eff_key.vel,(ca-1)->vel);
+                               QUATCOPY(eff_key.rot,(ca-1)->rot);
+
+                               do_effectors(i, pa, &eff_key, ob, psys, force, vel, dfra, cfra);
+
+                               VecMulf(force, pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) * steps);
+
+                               VecAddf(force, force, vec);
+
+                               Normalize(force);
+
+                               if(k < steps) {
+                                       VecSubf(vec, (ca+1)->co, ca->co);
+                                       length = VecLength(vec);
+                               }
+
+                               VECADDFAC(ca->co, (ca-1)->co, force, length);
+                       }
 
                        /* apply guide curves to path data */
                        if(edit==0 && psys->effectors.first && (psys->part->flag & PART_CHILD_GUIDE)==0)
                                do_guide(&result, i, time, &psys->effectors);
 
+                       /* apply lattice */
+                       if(psys->lattice && edit==0)
+                               calc_latt_deform(ca->co, 1.0f);
+
                        /* figure out rotation */
                        
                        if(k) {
@@ -2439,7 +2476,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                                if(k == 1) {
                                        float *q2;
 
-                                       VECSUB(tangent, result.co, (ca - 1)->co);
+                                       VECSUB(tangent, ca->co, (ca - 1)->co);
 
                                        q2 = vectoquat(tangent, OB_POSX, OB_POSZ);
 
@@ -2449,7 +2486,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                                        Normalize(prev_tangent);
                                }
                                else {
-                                       VECSUB(tangent, result.co, (ca - 1)->co);
+                                       VECSUB(tangent, ca->co, (ca - 1)->co);
                                        Normalize(tangent);
                                        angle = saacos(Inpf(tangent, prev_tangent));
 
@@ -2470,8 +2507,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                                }
                        }
 
-                       VECCOPY(ca->co, result.co);
                        
+                       /* set velocity */
+
                        if(k){
                                VECSUB(ca->vel, ca->co, (ca-1)->co);
 
@@ -2512,9 +2550,6 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda
                        else{
                                VECCOPY(ca->col, col);
                        }
-
-                       if(psys->lattice && edit==0)
-                               calc_latt_deform(ca->co, 1.0f);
                }
        }
 
@@ -3200,11 +3235,11 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
        ParticleData *pa;
        ChildParticle *cpa;
        ParticleTexture ptex;
-       ParticleKey tstate;
+       ParticleKey tstate, *kkey[2] = {NULL, NULL};
        HairKey *hkey[2];
        ParticleKey *par=0, keys[4];
 
-       float t, real_t, dfra, keytime;
+       float t, real_t, dfra, keytime, frs_sec = G.scene->r.frs_sec;
        float co[3], orco[3];
        float imat[4][4], hairmat[4][4], cpa_1st[3];
        float pa_clump = 0.0, pa_kink = 0.0;
@@ -3239,19 +3274,39 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
                        return;
                }
                
-               hkey[0] = pa->hair;
-               hkey[1] = pa->hair + 1;
+               if(psys->flag & PSYS_KEYED) {
+                       kkey[0] = pa->keys;
+                       kkey[1] = kkey[0] + 1;
 
-               real_t = hkey[0]->time + (hkey[0][pa->totkey-1].time - hkey[0]->time) * t;
+                       real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time);
+               }
+               else {
+                       hkey[0] = pa->hair;
+                       hkey[1] = pa->hair + 1;
 
-               while(hkey[1]->time < real_t)
-                       hkey[1]++;
+                       real_t = hkey[0]->time + (hkey[0][pa->totkey-1].time - hkey[0]->time) * t;
+               }
 
-               hkey[0] = hkey[1] - 1;
+               if(psys->flag & PSYS_KEYED) {
+                       while(kkey[1]->time < real_t) {
+                               kkey[1]++;
+                       }
+                       kkey[0] = kkey[1] - 1;
 
-               hair_to_particle(keys + 1, hkey[0]);
-               hair_to_particle(keys + 2, hkey[1]);
+                       memcpy(keys + 1, kkey[0], sizeof(ParticleKey));
+                       memcpy(keys + 2, kkey[1], sizeof(ParticleKey));
+               }
+               else {
+                       while(hkey[1]->time < real_t)
+                               hkey[1]++;
+
+                       hkey[0] = hkey[1] - 1;
 
+                       hair_to_particle(keys + 1, hkey[0]);
+                       hair_to_particle(keys + 2, hkey[1]);
+               }
+
+               if((psys->flag & PSYS_KEYED)==0) {
                //if(soft){
                //      if(key[0] != sbel.keys)
                //              DB_copy_key(&k1,key[0]-1);
@@ -3276,6 +3331,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
                                hair_to_particle(keys + 3, hkey[1] + 1);
                        else
                                hair_to_particle(keys + 3, hkey[1]);
+               }
                //}
 
                //psys_get_particle_on_path(bsys,p,t,bkey,ckey[0]);
@@ -3296,24 +3352,38 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
 
                keytime = (real_t - keys[1].time) / dfra;
 
-               interpolate_particle((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL
+               /* convert velocity to timestep size */
+               if(psys->flag & PSYS_KEYED){
+                       VecMulf(keys[1].vel, dfra / frs_sec);
+                       VecMulf(keys[2].vel, dfra / frs_sec);
+                       QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime);
+               }
+
+               interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
+                       : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
                        ,keys, keytime, state);
 
-               if((pa->flag & PARS_REKEY)==0) {
-                       psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat);
-                       Mat4MulVecfl(hairmat, state->co);
+               /* the velocity needs to be converted back from cubic interpolation */
+               if(psys->flag & PSYS_KEYED){
+                       VecMulf(state->vel, frs_sec / dfra);
+               }
+               else {
+                       if((pa->flag & PARS_REKEY)==0) {
+                               psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat);
+                               Mat4MulVecfl(hairmat, state->co);
 
-                       if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) {
-                               do_guide(state, p, state->time, &psys->effectors);
-                               /* TODO: proper velocity handling */
-                       }
+                               if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) {
+                                       do_guide(state, p, state->time, &psys->effectors);
+                                       /* TODO: proper velocity handling */
+                               }
 
-                       if(psys->lattice && edit==0)
-                               calc_latt_deform(state->co,1.0f);
+                               if(psys->lattice && edit==0)
+                                       calc_latt_deform(state->co,1.0f);
+                       }
                }
        }
        else if(totchild){
-               Mat4Invert(imat,ob->obmat);
+               //Mat4Invert(imat,ob->obmat);
                
                cpa=psys->child+p-totpart;
                
@@ -3345,19 +3415,9 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
                        psys_particle_on_emitter(ob,psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0);
 
                        /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
-                       VECCOPY(cpa_1st,co);
-
-                       //w=0;
-                       //while(w<4 && cpa->pa[w]>=0){
-                       //      pa=psys->particles+cpa->pa[w];
-                       //      psys_particle_on_emitter(ob,psmd,part->from,pa->num,pa->fuv,pa->foffset,vec,0,0,0);
-                       //      cpa_1st[0] -= cpa->w[w]*vec[0];
-                       //      cpa_1st[1] -= cpa->w[w]*vec[1];
-                       //      cpa_1st[2] -= cpa->w[w]*vec[2];
-                       //      w++;
-                       //}
+                       //VECCOPY(cpa_1st,co);
 
-                       Mat4MulVecfl(ob->obmat,cpa_1st);
+                       //Mat4MulVecfl(ob->obmat,cpa_1st);
 
                        pa=0;
                }
@@ -3412,7 +3472,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
                                w++;
                        }
                        /* apply offset for correct positioning */
-                       VECADD(state->co,state->co,cpa_1st);
+                       //VECADD(state->co,state->co,cpa_1st);
                }
                else{
                        /* offset the child from the parent position */
@@ -3452,19 +3512,18 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle
                if(part->rough_end != 0.0)
                        do_rough_end(cpa->rand, t, part->rough_end, part->rough_end_shape, state, par); 
 
-               if(vel){
-                       if(t>=0.001f){
-                               tstate.time=t-0.001f;
-                               psys_get_particle_on_path(ob,psys,p,&tstate,0);
-                               VECSUB(state->vel,state->co,tstate.co);
-                       }
-                       else{
-                               tstate.time=t+0.001f;
-                               psys_get_particle_on_path(ob,psys,p,&tstate,0);
-                               VECSUB(state->vel,tstate.co,state->co);
-                       }
-               }
-
+               //if(vel){
+               //      if(t>=0.001f){
+               //              tstate.time=t-0.001f;
+               //              psys_get_particle_on_path(ob,psys,p,&tstate,0);
+               //              VECSUB(state->vel,state->co,tstate.co);
+               //      }
+               //      else{
+               //              tstate.time=t+0.001f;
+               //              psys_get_particle_on_path(ob,psys,p,&tstate,0);
+               //              VECSUB(state->vel,tstate.co,state->co);
+               //      }
+               //}
        }
 }
 /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
@@ -3505,18 +3564,18 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey
                                return 0;
        }
 
-       //if(bsys->flag & (BSYS_DONE|BSYS_KEYED)){
-       //      if(between){
-       //              //ChildParticle *cpa=psys->child+p-totpart;
-       //              //state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]);
-       //      }
-       //      else
-       //              state->time= (cfra-pa->time)/(pa->dietime-pa->time);//pa->lifetime;
+       if(psys->flag & PSYS_KEYED){
+               if(between){
+                       ChildParticle *cpa=psys->child+p-totpart;
+                       state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]);
+               }
+               else
+                       state->time= (cfra-pa->time)/(pa->dietime-pa->time);
 
-       //      psys_get_particle_on_path(ob,psys,p,state,1);
-       //      return 1;
-       //}
-       //else{
+               psys_get_particle_on_path(ob,psys,p,state,1);
+               return 1;
+       }
+       else{
                //if(psys->totchild && p>=psys->totpart){
                //      ChildParticle *cpa=psys->child+p-psys->totpart;
                //      ParticleKey *key1, skey;
@@ -3560,7 +3619,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey
                //}
                
                return 1;
-       //}
+       }
 }
 
 void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
index f69e7bcd05f05f47b23c2f6f78abdc229db66b4a..94cfdadbb16a13c0e8d34ecfb255bb814c5ae0f4 100644 (file)
@@ -2607,7 +2607,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo
 
 
 /* calculate forces that all effectors apply to a particle*/
-static void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, ParticleSystem *psys, float *force_field, float *vel,float framestep, float cfra)
+void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, ParticleSystem *psys, float *force_field, float *vel,float framestep, float cfra)
 {
        Object *eob;
        ParticleSystem *epsys;
@@ -4050,12 +4050,16 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
                                pa->alive=PARS_UNBORN;
                        }
                        else{
-                               pa->loop=0;
-                               if(cfra<=pa->time)
-                                       pa->alive=PARS_UNBORN;
+                               pa->loop = 0;
+                               if(cfra <= pa->time)
+                                       pa->alive = PARS_UNBORN;
                                                /* without dynamics the state is allways known so no need to kill */
-                               else if(ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)==0)
-                                       pa->alive=PARS_KILLED;
+                               else if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)){
+                                       if(cfra < pa->dietime)
+                                               pa->alive = PARS_ALIVE;
+                               }
+                               else
+                                       pa->alive = PARS_KILLED;
                        }
                }
 
@@ -4398,7 +4402,9 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
                        return;
                }
        }
-       else if(part->phystype != PART_PHYS_NO) {       /* cache shouldn't be used for none physics */
+       else if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED))
+               ; /* cache shouldn't be used for "none" or "keyed" physics */
+       else {
                if(psys->recalc && (psys->flag & PSYS_PROTECT_CACHE) == 0)
                        clear_particles_from_cache(ob,psys,(int)cfra);
                else if(get_particles_from_cache(ob, psys, (int)cfra)) {
@@ -4500,9 +4506,12 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
                dynamics_step(ob,psys,psmd,cfra,vg_vel,vg_tan,vg_rot,vg_size);
 
        psys->recalc = 0;
-       psys->cfra=cfra;
+       psys->cfra = cfra;
 
-       if(part->type!=PART_HAIR)
+       if(part->type == PART_HAIR || part->phystype == PART_PHYS_NO
+               || (part->phystype == PART_PHYS_KEYED && psys->flag & PSYS_FIRST_KEYED))
+               ; /* cache shouldn't be used for hair or "none" or "first keyed" physics */
+       else
                write_particles_to_cache(ob, psys, cfra);
 
        /* for keyed particles the path is allways known so it can be drawn */
index 4812d7e39047166d5b77c90bdcbec7db66477222..6a2e3aa481af91291793377efc55047ca5e0aa9c 100644 (file)
@@ -2526,6 +2526,11 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
                        for(a=0; a<psys->totpart; a++, pa++)
                                pa->hair=newdataadr(fd,pa->hair);
                }
+               if(psys->particles && psys->particles->keys){
+                       ParticleData *pa = psys->particles;
+                       for(a=0; a<psys->totpart; a++, pa++)
+                               pa->keys=newdataadr(fd,pa->keys);
+               }
                psys->child=newdataadr(fd,psys->child);
                psys->effectors.first=psys->effectors.last=0;
 
index 9c013fbc1d0848b2868c93d8075c8cf1addd3826..fdea98c7ab250fe5d22648b10bdf96507e1155ed 100644 (file)
@@ -558,6 +558,13 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
                                for(a=0; a<psys->totpart; a++, pa++)
                                        writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair);
                        }
+                       
+                       if(psys->particles->keys) {
+                               ParticleData *pa = psys->particles;
+
+                               for(a=0; a<psys->totpart; a++, pa++)
+                                       writestruct(wd, DATA, "ParticleKey", pa->totkey, pa->keys);
+                       }
                }
                if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
                writestruct(wd, DATA, "SoftBody", 1, psys->soft);
index f83c2a5979953055b03cc88ab6487899bc9d4a76..d39fbbbc679ddda30911f3f61205731ca5a66dab 100644 (file)
@@ -128,7 +128,7 @@ typedef struct ParticleSettings {
 
        /* general values */
        float sta, end, lifetime, randlife;
-       float timetweak, jitfac, keyed_time;
+       float timetweak, jitfac, keyed_time, eff_hair, rt;
        int totpart, userjit, grid_res;
 
        /* initial velocity factors */
index 1815fdd06f2eee78ba046f9d9ba74dd42ffb26c1..5443aa1de5e314de8750a9c92063c590c3a23482 100644 (file)
@@ -3912,9 +3912,13 @@ static void object_panel_particle_extra(Object *ob)
        buty=butx=160;
 
        uiDefButI(block, NUM, B_PART_DISTR, "Seed:",                            butx,(buty-=buth),butw,buth, &psys->seed, 0.0, 255.0, 1, 0, "Set an offset in the random table");
+       if(part->type == PART_HAIR && psys->flag & PSYS_EDITED)
+               uiDefButF(block, NUM, B_PART_RECALC, "Stiff:",  butx,(buty-=buth),butw,buth, &part->eff_hair, 0.0, 1.0, 0, 0, "Hair stiffness for effectors");
+       else
+               buty-=buth;
 
        /* size changes must create a recalc event always so that sizes are updated properly */
-       uiDefButF(block, NUM, B_PART_RECALC, "Size:",   butx,(buty-=2*buth),butw,buth, &part->size, 0.01, 100, 10, 1, "The size of the particles");
+       uiDefButF(block, NUM, B_PART_RECALC, "Size:",   butx,(buty-=buth),butw,buth, &part->size, 0.01, 100, 10, 1, "The size of the particles");
        uiDefButF(block, NUM, B_PART_RECALC, "Rand:",   butx,(buty-=buth),butw,buth, &part->randsize, 0.0, 2.0, 10, 1, "Give the particle size a random variation");
 
        uiDefButBitI(block, TOG, PART_SIZEMASS, B_PART_RECALC, "Mass from size",         butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Multiply mass with particle size");
index 2ae272cd5bad7f71fb92bf4fd65acc5040e1c0f6..3e154298517daf3184a572f99bf8e902761e7257 100644 (file)
@@ -3037,7 +3037,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys)
 
        psys->flag|=PSYS_DRAWING;
 
-       if(!psys->childcache)
+       if(part->type==PART_HAIR && !psys->childcache)
                totchild=0;
        else
                totchild=psys->totchild*part->disp/100;