diff options
Diffstat (limited to 'source/blender/blenkernel/intern/particle_system.c')
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 428 |
1 files changed, 237 insertions, 191 deletions
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 1931b89af38..dcd3fcd2f89 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -123,11 +123,21 @@ static int get_current_display_percentage(ParticleSystem *psys) void psys_reset(ParticleSystem *psys, int mode) { ParticleSettings *part= psys->part; - PARTICLE_P; + ParticleData *pa; + int i; if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { - if(mode == PSYS_RESET_ALL || !(part->type == PART_HAIR && (psys->edit && psys->edit->edited))) { - psys_free_particles(psys); + if(mode == PSYS_RESET_ALL || !(part->type == PART_HAIR && (psys->flag & PSYS_EDITED))) { + if(psys->particles) { + if(psys->particles->keys) + MEM_freeN(psys->particles->keys); + + for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) + if(pa->hair) MEM_freeN(pa->hair); + + MEM_freeN(psys->particles); + psys->particles= NULL; + } psys->totpart= 0; psys->totkeyed= 0; @@ -135,17 +145,14 @@ void psys_reset(ParticleSystem *psys, int mode) if(psys->reactevents.first) BLI_freelistN(&psys->reactevents); - - if(psys->edit && psys->free_edit) { - psys->free_edit(psys->edit); - psys->edit = NULL; - psys->free_edit = NULL; - } } } else if(mode == PSYS_RESET_CACHE_MISS) { /* set all particles to be skipped */ - LOOP_PARTICLES + ParticleData *pa = psys->particles; + int p=0; + + for(; p<psys->totpart; p++, pa++) pa->flag |= PARS_NO_DISP; } @@ -158,7 +165,7 @@ void psys_reset(ParticleSystem *psys, int mode) psys->totchild= 0; /* reset path cache */ - psys_free_path_cache(psys, psys->edit); + psys_free_path_cache(psys); /* reset point cache */ psys->pointcache->flag &= ~PTCACHE_SIMULATION_VALID; @@ -167,10 +174,9 @@ void psys_reset(ParticleSystem *psys, int mode) static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) { - ParticleData *newpars = NULL; - BoidParticle *newboids = NULL; - PARTICLE_P; - int totpart, totsaved = 0; + ParticleData *newpars = 0, *pa; + BoidData *newboids = 0; + int i, totpart, totsaved = 0; if(new_totpart<0) { if(psys->part->distr==PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) { @@ -183,46 +189,47 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) else totpart=new_totpart; - if(totpart && totpart != psys->totpart) { + if(totpart) { newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); - - if(psys->particles) { - totsaved=MIN2(psys->totpart,totpart); - /*save old pars*/ - if(totsaved) { - memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData)); - - if(psys->particles->boid) - memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidParticle)); - } - if(psys->particles->keys) - MEM_freeN(psys->particles->keys); + if(psys->part->phystype == PART_PHYS_BOIDS) + newboids = MEM_callocN(totpart*sizeof(BoidData), "Boid Data"); + } + if(psys->particles) { + totsaved=MIN2(psys->totpart,totpart); + /*save old pars*/ + if(totsaved) { + memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData)); - if(psys->particles->boid) - MEM_freeN(psys->particles->boid); + if(newboids) + memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidData)); + } - for(p=0, pa=newpars; p<totsaved; p++, pa++) { - if(pa->keys) { - pa->keys= NULL; - pa->totkey= 0; - } - } + if(psys->particles->keys) + MEM_freeN(psys->particles->keys); - for(p=totsaved, pa=psys->particles+totsaved; p<psys->totpart; p++, pa++) - if(pa->hair) MEM_freeN(pa->hair); + if(psys->particles->boid) + MEM_freeN(psys->particles->boid); - MEM_freeN(psys->particles); + for(i=0, pa=newpars; i<totsaved; i++, pa++) { + if(pa->keys) { + pa->keys= NULL; + pa->totkey= 0; + } } - - psys->particles=newpars; - if(newboids) { - LOOP_PARTICLES - pa->boid = newboids++; - } - - psys->totpart=totpart; + for(i=totsaved, pa=psys->particles+totsaved; i<psys->totpart; i++, pa++) + if(pa->hair) MEM_freeN(pa->hair); + + MEM_freeN(psys->particles); + } + psys->particles=newpars; + + if(newboids) { + pa = psys->particles; + pa->boid = newboids; + for(i=1, pa++; i<totpart; i++,pa++) + pa->boid = (pa-1)->boid + 1; } if(psys->child) { @@ -230,6 +237,8 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) psys->child=0; psys->totchild=0; } + + psys->totpart=totpart; } static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys) @@ -276,7 +285,8 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) each original elements can reference its derived elements */ Mesh *me= (Mesh*)ob->data; - PARTICLE_P; + ParticleData *pa= 0; + int p; /* CACHE LOCATIONS */ if(!dm->deformedOnly) { @@ -313,7 +323,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) } /* cache the verts/faces! */ - LOOP_PARTICLES { + for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++) { if(psys->part->from == PART_FROM_VERT) { if(nodearray[pa->num]) pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link); @@ -333,7 +343,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) * should know to use the num or num_dmcache, set the num_dmcache to * an invalid value, just incase */ - LOOP_PARTICLES + for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++) pa->num_dmcache = -1; } } @@ -1433,11 +1443,12 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Objec /* ready for future use, to emit particles without geometry */ static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int from) { - PARTICLE_P; + ParticleData *pa; + int totpart=psys->totpart, p; fprintf(stderr,"Shape emission not yet possible!\n"); - LOOP_PARTICLES { + for(p=0,pa=psys->particles; p<totpart; p++,pa++){ pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0; pa->foffset= 0.0f; pa->num= -1; @@ -1459,11 +1470,12 @@ static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, distribute_particles_on_shape(ob,psys,from); if(distr_error){ - PARTICLE_P; + ParticleData *pa; + int totpart=psys->totpart, p; fprintf(stderr,"Particle distribution error!\n"); - LOOP_PARTICLES { + for(p=0,pa=psys->particles; p<totpart; p++,pa++){ pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0; pa->foffset= 0.0f; pa->num= -1; @@ -1558,7 +1570,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps Material *ma=0; //IpoCurve *icu=0; // XXX old animation system int totpart; - float rand; + float rand,length; part=psys->part; @@ -1613,8 +1625,40 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps pa->dietime= pa->time+pa->lifetime; + pa->sizemul= BLI_frand(); + + rand= BLI_frand(); + + /* while loops are to have a spherical distribution (avoid cubic distribution) */ + if(part->phystype != PART_PHYS_BOIDS) { + /* boids store gravity in r_ve, so skip here */ + length=2.0f; + while(length>1.0){ + pa->r_ve[0]=2.0f*(BLI_frand()-0.5f); + pa->r_ve[1]=2.0f*(BLI_frand()-0.5f); + pa->r_ve[2]=2.0f*(BLI_frand()-0.5f); + length=VecLength(pa->r_ve); + } + } + + length=2.0f; + while(length>1.0){ + pa->r_ave[0]=2.0f*(BLI_frand()-0.5f); + pa->r_ave[1]=2.0f*(BLI_frand()-0.5f); + pa->r_ave[2]=2.0f*(BLI_frand()-0.5f); + length=VecLength(pa->r_ave); + } + + pa->r_rot[0]=2.0f*(BLI_frand()-0.5f); + pa->r_rot[1]=2.0f*(BLI_frand()-0.5f); + pa->r_rot[2]=2.0f*(BLI_frand()-0.5f); + pa->r_rot[3]=2.0f*(BLI_frand()-0.5f); + + NormalQuat(pa->r_rot); + if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){ - if(ptex.exist < BLI_frand()) + /* any unique random number will do (r_ave[0]) */ + if(ptex.exist < 0.5*(1.0+pa->r_ave[0])) pa->flag |= PARS_UNEXIST; else pa->flag &= ~PARS_UNEXIST; @@ -1628,9 +1672,10 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) { //IpoCurve *icu=0; // XXX old animation system - PARTICLE_P; + ParticleData *pa; + int p, totpart=psys->totpart; - LOOP_PARTICLES + for(p=0, pa=psys->particles; p<totpart; p++, pa++) initialize_particle(pa,p,ob,psys,psmd); if(psys->part->type != PART_FLUID) { @@ -1698,39 +1743,10 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0}; float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; - float q_phase[4], length, r_phase; + float q_phase[4]; part=psys->part; ptex.ivel=1.0; - - BLI_srandom(psys->seed + (pa - psys->particles)); - - /* we need to get every random even if they're not used so that they don't effect eachother */ - /* while loops are to have a spherical distribution (avoid cubic distribution) */ - length=2.0f; - while(length>1.0){ - r_vel[0]=2.0f*(BLI_frand()-0.5f); - r_vel[1]=2.0f*(BLI_frand()-0.5f); - r_vel[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(r_vel); - } - - length=2.0f; - while(length>1.0){ - r_ave[0]=2.0f*(BLI_frand()-0.5f); - r_ave[1]=2.0f*(BLI_frand()-0.5f); - r_ave[2]=2.0f*(BLI_frand()-0.5f); - length=VecLength(r_ave); - } - - r_rot[0]=2.0f*(BLI_frand()-0.5f); - r_rot[1]=2.0f*(BLI_frand()-0.5f); - r_rot[2]=2.0f*(BLI_frand()-0.5f); - r_rot[3]=2.0f*(BLI_frand()-0.5f); - - NormalQuat(r_rot); - - r_phase = BLI_frand(); if(part->from==PART_FROM_PARTICLE){ Object *tob; @@ -1741,26 +1757,29 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic if(tob==0) tob=ob; - tpsys=BLI_findlink(&tob->particlesystem, psys->target_psys-1); + tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); state.time = pa->time; if(pa->num == -1) memset(&state, 0, sizeof(state)); else psys_get_particle_state(scene, tob,tpsys,pa->num,&state,1); - psys_get_from_key(&state, loc, nor, rot, 0); + psys_get_from_key(&state,loc,nor,rot,0); - QuatMulVecf(rot, vtan); - QuatMulVecf(rot, utan); + QuatMulVecf(rot,vtan); + QuatMulVecf(rot,utan); + VECCOPY(r_vel,pa->r_ve); + VECCOPY(r_rot,pa->r_rot); + VECCOPY(r_ave,pa->r_ave); - VECCOPY(p_vel, state.vel); + VECCOPY(p_vel,state.vel); speed=Normalize(p_vel); - VecMulf(p_vel, Inpf(r_vel, p_vel)); - VECSUB(p_vel, r_vel, p_vel); + VecMulf(p_vel,Inpf(pa->r_ve,p_vel)); + VECSUB(p_vel,pa->r_ve,p_vel); Normalize(p_vel); - VecMulf(p_vel, speed); + VecMulf(p_vel,speed); - VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */ + VECCOPY(pa->fuv,loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */ } else{ /* get precise emitter matrix if particle is born */ @@ -1814,25 +1833,29 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic /* -velocity */ if(part->randfac!=0.0){ - Mat4Mul3Vecfl(ob->obmat,r_vel); + VECADD(r_vel,tloc,pa->r_ve); + Mat4MulVecfl(ob->obmat,r_vel); + VECSUB(r_vel,r_vel,loc); Normalize(r_vel); } /* -angular velocity */ if(part->avemode==PART_AVE_RAND){ - Mat4Mul3Vecfl(ob->obmat,r_ave); + VECADD(r_ave,tloc,pa->r_ave); + Mat4MulVecfl(ob->obmat,r_ave); + VECSUB(r_ave,r_ave,loc); Normalize(r_ave); } /* -rotation */ if(part->randrotfac != 0.0f){ + QUATCOPY(r_rot,pa->r_rot); Mat4ToQuat(ob->obmat,rot); QuatMul(r_rot,r_rot,rot); } } if(part->phystype==PART_PHYS_BOIDS) { - BoidParticle *bpa = pa->boid; float dvec[3], q[4], mat[3][3]; VECCOPY(pa->state.co,loc); @@ -1849,21 +1872,16 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic VECCOPY(pa->state.ave, nor); } /* and gravity in r_ve */ - bpa->gravity[0] = bpa->gravity[1] = 0.0f; - bpa->gravity[2] = -1.0f; + pa->r_ve[0] = pa->r_ve[1] = 0.0f; + pa->r_ve[2] = -1.0f; if(part->acc[2]!=0.0f) - bpa->gravity[2] = part->acc[2]; - - //pa->r_ve[0] = pa->r_ve[1] = 0.0f; - //pa->r_ve[2] = -1.0f; - //if(part->acc[2]!=0.0f) - // pa->r_ve[2] = part->acc[2]; + pa->r_ve[2] = part->acc[2]; /* calculate rotation matrix */ - Projf(dvec, r_vel, pa->state.ave); + Projf(dvec, pa->r_ve, pa->state.ave); VecSubf(mat[0], pa->state.ave, dvec); Normalize(mat[0]); - VECCOPY(mat[2], r_vel); + VECCOPY(mat[2], pa->r_ve); VecMulf(mat[2], -1.0f); Normalize(mat[2]); Crossf(mat[1], mat[2], mat[0]); @@ -1872,10 +1890,10 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic Mat3ToQuat_is_ok(mat, q); QuatCopy(pa->state.rot, q); - bpa->data.health = part->boids->health; - bpa->data.mode = eBoidMode_InAir; - bpa->data.state_id = ((BoidState*)part->boids->states.first)->id; - bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f; + pa->boid->health = part->boids->health; + pa->boid->mode = eBoidMode_InAir; + pa->boid->state_id = ((BoidState*)part->boids->states.first)->id; + pa->boid->acc[0]=pa->boid->acc[1]=pa->boid->acc[2]=0.0f; } else { /* conversion done so now we apply new: */ @@ -1964,8 +1982,8 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic /* rotation phase */ phasefac = part->phasefac; - if(part->randphasefac != 0.0f) - phasefac += part->randphasefac * r_phase; + if(part->randphasefac != 0.0f) /* abuse r_ave[0] as a random number */ + phasefac += part->randphasefac * pa->r_ave[0]; VecRotToQuat(x_vec, phasefac*(float)M_PI, q_phase); /* combine base rotation & phase */ @@ -2003,7 +2021,8 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic pa->state.time = cfra; -// pa->flag &= ~PARS_STICKY; + pa->stick_ob = 0; + pa->flag &= ~PARS_STICKY; } static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from) { @@ -2069,9 +2088,8 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSystem *kpsys = psys; ParticleTarget *pt; - PARTICLE_P; - ParticleKey *key; - int totpart = psys->totpart, k, totkeys = psys->totkeyed; + ParticleData *pa; + int totpart = psys->totpart, i, k, totkeys = psys->totkeyed; /* no proper targets so let's clear and bail out */ if(psys->totkeyed==0) { @@ -2083,12 +2101,12 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) if(totpart && psys->particles->totkey != totkeys) { free_keyed_keys(psys); - key = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); + psys->particles->keys = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); + psys->particles->totkey = totkeys; - LOOP_PARTICLES { - pa->keys = key; + for(i=1, pa=psys->particles+1; i<totpart; i++,pa++){ + pa->keys = (pa-1)->keys + totkeys; pa->totkey = totkeys; - key += totkeys; } } @@ -2102,23 +2120,22 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) else kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1); - LOOP_PARTICLES { - key = pa->keys + k; - key->time = -1.0; /* use current time */ + for(i=0,pa=psys->particles; i<totpart; i++, pa++) { + (pa->keys + k)->time = -1.0; /* use current time */ - psys_get_particle_state(scene, pt->ob, kpsys, p%kpsys->totpart, key, 1); + psys_get_particle_state(scene, pt->ob, kpsys, i%kpsys->totpart, pa->keys + k, 1); if(psys->flag & PSYS_KEYED_TIMING){ - key->time = pa->time + pt->time; + (pa->keys+k)->time = pa->time + pt->time; if(pt->duration != 0.0f && k+1 < totkeys) { - copy_particle_key(key+1, key, 1); - (key+1)->time = pa->time + pt->time + pt->duration; + copy_particle_key(pa->keys+k+1, pa->keys+k, 1); + (pa->keys+k+1)->time = pa->time + pt->time + pt->duration; } } else if(totkeys > 1) - key->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime; + (pa->keys+k)->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime; else - key->time = pa->time; + pa->keys->time = pa->time; } if(psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f) @@ -2257,7 +2274,7 @@ void psys_clear_temp_pointcache(ParticleSystem *psys) if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0) return; - BKE_ptcache_free_mem(&psys->pointcache->mem_cache); + BKE_ptache_free_mem(psys->pointcache); } void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra) { @@ -2273,15 +2290,16 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra static void update_particle_tree(ParticleSystem *psys) { if(psys) { - PARTICLE_P; + ParticleData *pa = psys->particles; + int p, totpart = psys->totpart; if(!psys->tree || psys->tree_frame != psys->cfra) { BLI_kdtree_free(psys->tree); - psys->tree = BLI_kdtree_new(psys->totpart); + psys->tree = BLI_kdtree_new(totpart); - LOOP_PARTICLES { + for(p=0, pa=psys->particles; p<totpart; p++,pa++){ if(pa->flag & (PARS_NO_DISP+PARS_UNEXIST) || pa->alive != PARS_ALIVE) continue; @@ -2524,9 +2542,9 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; ParticleSettings *part=psys->part; - PARTICLE_P; - int totpart; + ParticleData *pa; float vec2[3],loc[3],*co=0; + int p,totpart; for(ec= lb->first; ec; ec= ec->next) { PartDeflect *pd= ec->ob->pd; @@ -2550,7 +2568,7 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa ec->distances=MEM_callocN(totpart*sizeof(float),"particle distances"); ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations"); - LOOP_PARTICLES { + for(p=0,pa=psys->particles; p<totpart; p++, pa++){ if(part->from == PART_FROM_PARTICLE) { VECCOPY(loc, pa->fuv); } @@ -3220,7 +3238,7 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa ParticleCollision col; BVHTreeRayHit hit; float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; - float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z = 0.0f; + float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f), boid_z; int deflections=0, max_deflections=10; VECCOPY(col.co1, pa->prev_state.co); @@ -3229,10 +3247,9 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /* override for boids */ if(part->phystype == PART_PHYS_BOIDS) { - BoidParticle *bpa = pa->boid; radius = pa->size; boid_z = pa->state.co[2]; - skip_ob = bpa->ground; + skip_ob = pa->stick_ob; } /* 10 iterations to catch multiple deflections */ @@ -3302,7 +3319,12 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa deflections=max_deflections; /* store for reactors */ - copy_particle_key(&reaction_state, &pa->state, 0); + copy_particle_key(&reaction_state,&pa->state,0); + + if(part->flag & PART_STICKY){ + pa->stick_ob=ob; + pa->flag |= PARS_STICKY; + } } else { float nor_vec[3], tan_vec[3], tan_vel[3], vel[3]; @@ -3390,8 +3412,7 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); if(part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) { - BoidParticle *bpa = pa->boid; - if(bpa->data.mode == eBoidMode_OnLand || co[2] <= boid_z) { + if(pa->boid->mode == eBoidMode_OnLand || co[2] <= boid_z) { co[2] = boid_z; vel[2] = 0.0f; } @@ -3433,9 +3454,10 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /* Hair */ /************************************************/ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ - HairKey *key, *root; - PARTICLE_P; + ParticleData *pa; + HairKey *key; int totpart; + int i; Mat4Invert(ob->imat,ob->obmat); @@ -3446,22 +3468,21 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy totpart=psys->totpart; /* save new keys for elements if needed */ - LOOP_PARTICLES { + for(i=0,pa=psys->particles; i<totpart; i++,pa++) { /* first time alloc */ if(pa->totkey==0 || pa->hair==NULL) { pa->hair = MEM_callocN((psys->part->hair_step + 1) * sizeof(HairKey), "HairKeys"); pa->totkey = 0; } - key = root = pa->hair; - key += pa->totkey; + key = pa->hair + pa->totkey; /* convert from global to geometry space */ VecCopyf(key->co, pa->state.co); Mat4MulVecfl(ob->imat, key->co); if(pa->totkey) { - VECSUB(key->co, key->co, root->co); + VECSUB(key->co, key->co, pa->hair->co); psys_vec_rot_to_face(psmd->dm, pa, key->co); } @@ -3473,7 +3494,7 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy /* root is always in the origin of hair space so we set it to be so after the last key is saved*/ if(pa->totkey == psys->part->hair_step + 1) - root->co[0] = root->co[1] = root->co[2] = 0.0f; + pa->hair->co[0] = pa->hair->co[1] = pa->hair->co[2] = 0.0f; } } /************************************************/ @@ -3483,14 +3504,14 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra, float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size) { + ParticleData *pa; ParticleSettings *part=psys->part; KDTree *tree=0; IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system Material *ma=give_current_material(ob,part->omat); BoidBrainData bbd; - PARTICLE_P; float timestep; - int totpart; + int p, totpart; /* current time */ float ctime, ipotime; // XXX old animation system /* frame & time changes */ @@ -3519,7 +3540,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic if(part->type==PART_REACTOR) vg_size=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); - LOOP_PARTICLES { + for(p=0, pa=psys->particles; p<totpart; p++,pa++){ if(pa->flag & PARS_UNEXIST) continue; /* set correct ipo timing */ @@ -3588,7 +3609,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } /* main loop: calculate physics for all particles */ - LOOP_PARTICLES { + for(p=0, pa=psys->particles; p<totpart; p++,pa++){ if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; copy_particle_key(&pa->prev_state,&pa->state,1); @@ -3676,6 +3697,9 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic else{ pa->alive=PARS_DEAD; pa->state.time=pa->dietime; + + if(pa->flag&PARS_STICKY) + psys_key_to_object(pa->stick_ob,&pa->state,0); } } else @@ -3723,29 +3747,52 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){ - psys_cache_paths(scene, ob, psys, cfra); + psys_cache_paths(scene, ob, psys, cfra, 0); /* for render, child particle paths are computed on the fly */ if(part->childtype) { - if(((psys->totchild!=0)) || (psys_in_edit_mode(scene, psys) && (pset->flag&PE_DRAW_PART))) + if(((psys->totchild!=0)) || (psys_in_edit_mode(scene, psys) && (pset->flag&PE_SHOW_CHILD))) if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) psys_cache_child_paths(scene, ob, psys, cfra, 0); } } else if(psys->pathcache) - psys_free_path_cache(psys, NULL); + psys_free_path_cache(psys); +} + +/* calculate and store key locations in world coordinates */ +void psys_update_world_cos(Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + ParticleData *pa; + ParticleEditKey *key; + int i, k, totpart; + float hairmat[4][4]; + + if(psys==0 || psys->edit==0) + return; + + totpart= psys->totpart; + + for(i=0, pa=psys->particles; i<totpart; i++, pa++) { + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + + for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) { + VECCOPY(key->world_co,key->co); + Mat4MulVecfl(hairmat, key->world_co); + } + } } static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { ParticleSettings *part = psys->part; - PARTICLE_P; - float disp = (float)get_current_display_percentage(psys)/100.0f; - - BLI_srandom(psys->seed); + ParticleData *pa; + int p; + float disp = (float)get_current_display_percentage(psys)/50.0f-1.0f; - LOOP_PARTICLES { - if(BLI_frand() > disp) + for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){ + if(pa->r_rot[0] > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -3761,6 +3808,9 @@ static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd psys_init_effectors(scene, ob, part->eff_group, psys); if(psys->effectors.first) precalc_effectors(scene, ob,psys,psmd,cfra); + + if(psys_in_edit_mode(scene, psys)) + psys_update_world_cos(ob, psys); psys_update_path_cache(scene, ob,psmd,psys,cfra); } @@ -3769,14 +3819,13 @@ static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { ParticleSettings *part=psys->part; + ParticleData *pa; ParticleKey state; IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system Material *ma=give_current_material(ob,part->omat); - PARTICLE_P; + int p; float disp, birthtime, dietime, *vg_size= NULL; // XXX ipotime=cfra - BLI_srandom(psys->seed); - if(part->from!=PART_FROM_PARTICLE) vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); @@ -3789,9 +3838,9 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps precalc_effectors(scene, ob,psys,psmd,cfra); //} - disp= (float)get_current_display_percentage(psys)/100.0f; + disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; - LOOP_PARTICLES { + for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){ #if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ ipotime=100.0f*(cfra-pa->time)/pa->lifetime; @@ -3838,7 +3887,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps psys->lattice= NULL; } - if(BLI_frand() > disp) + if(pa->r_rot[0] > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -3891,8 +3940,8 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys) else { free_hair(psys, 1); - CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime)); - CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime)); + CLAMP(part->path_start, part->sta, part->end + part->lifetime); + CLAMP(part->path_end, part->sta, part->end + part->lifetime); } psys->softflag= 0; @@ -3901,25 +3950,23 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys) } void psys_check_boid_data(ParticleSystem *psys) { - BoidParticle *bpa; - PARTICLE_P; - - pa = psys->particles; + ParticleData *pa = psys->particles; + int p = 1; if(!pa) return; if(psys->part && psys->part->phystype==PART_PHYS_BOIDS) { if(!pa->boid) { - bpa = MEM_callocN(psys->totpart * sizeof(BoidParticle), "Boid Data"); + pa->boid = MEM_callocN(psys->totpart * sizeof(BoidData), "Boid Data"); - LOOP_PARTICLES - pa->boid = bpa++; + for(pa++; p<psys->totpart; p++, pa++) + pa->boid = (pa-1)->boid + 1; } } else if(pa->boid){ MEM_freeN(pa->boid); - LOOP_PARTICLES + for(; p<psys->totpart; p++, pa++) pa->boid = NULL; } } @@ -4067,10 +4114,10 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ParticleSettings *part; + ParticleData *pa; PointCache *cache; PTCacheID pid; - PARTICLE_P; - int totpart, oldtotpart, totchild, oldtotchild; + int totpart, oldtotpart, totchild, oldtotchild, p; float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; int framenr, framedelta, startframe, endframe; @@ -4213,7 +4260,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle } else if(result==PTCACHE_READ_OLD) { psys->cfra = (float)cache->simframe; - LOOP_PARTICLES { + for(p=0, pa=psys->particles; p<totpart; p++, pa++) { /* update alive status */ if(pa->time > psys->cfra) pa->alive = PARS_UNBORN; @@ -4252,11 +4299,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle } /* set particles to be not calculated TODO: can't work with pointcache */ - disp= (float)get_current_display_percentage(psys)/100.0f; + disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; - BLI_srandom(psys->seed); - LOOP_PARTICLES { - if(BLI_frand() > disp) + for(p=0, pa=psys->particles; p<totpart; p++,pa++){ + if(pa->r_rot[0] > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -4293,7 +4339,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle psys_update_path_cache(scene, ob, psmd, psys,(int)cfra); } else if(psys->pathcache) - psys_free_path_cache(psys, NULL); + psys_free_path_cache(psys); /* cleanup */ if(vg_vel) MEM_freeN(vg_vel); @@ -4339,7 +4385,7 @@ static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys) static int hair_needs_recalc(ParticleSystem *psys) { - if((!psys->edit || !psys->edit->edited) && + if((psys->flag & PSYS_EDITED)==0 && ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET)) { return 1; } |