diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py index 1bbd64c9b0f..e72bd38e563 100644 --- a/release/ui/buttons_particle.py +++ b/release/ui/buttons_particle.py @@ -255,6 +255,7 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel): sub = col.column(align=True) sub.itemR(cloth, "pin_stiffness", text="Stiffness") sub.itemR(cloth, "mass") + sub.itemR(cloth, "bending_stiffness", text="Bending") col.itemL(text="Damping:") sub = col.column(align=True) sub.itemR(cloth, "spring_damping", text="Spring") diff --git a/source/blender/blenkernel/BKE_boids.h b/source/blender/blenkernel/BKE_boids.h index acceff863b9..fb65c9c8920 100644 --- a/source/blender/blenkernel/BKE_boids.h +++ b/source/blender/blenkernel/BKE_boids.h @@ -35,9 +35,7 @@ #include "DNA_boid_types.h" typedef struct BoidBrainData { - Scene *scene; - struct Object *ob; - struct ParticleSystem *psys; + struct ParticleSimulationData *sim; struct ParticleSettings *part; float timestep, cfra, dfra; float wanted_co[3], wanted_speed; diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index c22778f5a30..5850ddaca08 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -61,6 +61,23 @@ struct BVHTreeRayHit; #define PARTICLE_P ParticleData *pa; int p #define LOOP_PARTICLES for(p=0, pa=psys->particles; ptotpart; p++, pa++) +#define LOOP_EXISTING_PARTICLES for(p=0, pa=psys->particles; ptotpart; p++, pa++) if(!(pa->flag & PARS_UNEXIST)) +#define LOOP_SHOWN_PARTICLES for(p=0, pa=psys->particles; ptotpart; p++, pa++) if(!(pa->flag & (PARS_UNEXIST|PARS_NO_DISP))) + +#define PSYS_FRAND_COUNT 1024 +#define PSYS_FRAND(seed) psys->frand[(seed) % PSYS_FRAND_COUNT] + +/* fast but sure way to get the modifier*/ +#define PARTICLE_PSMD ParticleSystemModifierData *psmd = sim->psmd ? sim->psmd : psys_get_modifier(sim->ob, sim->psys) + +/* common stuff that many particle functions need */ +typedef struct ParticleSimulationData { + struct Scene *scene; + struct Object *ob; + struct ParticleSystem *psys; + struct ParticleSystemModifierData *psmd; + float timestep; +} ParticleSimulationData; typedef struct ParticleEffectorCache { struct ParticleEffectorCache *next, *prev; @@ -118,11 +135,8 @@ typedef struct ParticleCacheKey{ typedef struct ParticleThreadContext { /* shared */ - struct Scene *scene; - struct Object *ob; + struct ParticleSimulationData sim; struct DerivedMesh *dm; - struct ParticleSystemModifierData *psmd; - struct ParticleSystem *psys; struct Material *ma; /* distribution */ @@ -166,8 +180,7 @@ typedef struct ParticleBillboardData int lock, num; int totnum; short align, uv_split, anim, split_offset; -} -ParticleBillboardData; +} ParticleBillboardData; /* container for moving data between deflet_particle and particle_intersect_face */ typedef struct ParticleCollision @@ -179,40 +192,40 @@ typedef struct ParticleCollision float co1[3], co2[3]; // ray start and end points float ray_len; // original length of co2-co1, needed for collision time evaluation float t; // time of previous collision, needed for substracting face velocity -} -ParticleCollision; +} ParticleCollision; + +typedef struct ParticleDrawData { + float *vdata, *vd; /* vertice data */ + float *ndata, *nd; /* normal data */ + float *cdata, *cd; /* color data */ + float *vedata, *ved; /* velocity data */ + float *ma_r, *ma_g, *ma_b; + int tot_vec_size, flag; + int totpoint, totve; +} ParticleDrawData; + +#define PARTICLE_DRAW_DATA_UPDATED 1 /* ----------- functions needed outside particlesystem ---------------- */ /* particle.c */ int count_particles(struct ParticleSystem *psys); int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur); -int psys_count_keys(struct ParticleSystem *psys); -char *psys_menu_string(struct Object *ob, int for_sb); struct ParticleSystem *psys_get_current(struct Object *ob); +/* for rna */ short psys_get_current_num(struct Object *ob); void psys_set_current_num(Object *ob, int index); struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); -//struct ParticleSystem *psys_get(struct Object *ob, int index); -struct ParticleData *psys_get_selected_particle(struct ParticleSystem *psys, int *index); -struct ParticleKey *psys_get_selected_key(struct ParticleSystem *psys, int pa_index, int *key_index); -void psys_change_act(void *ob_v, void *act_v); -struct Object *psys_get_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); -void psys_disable_all(struct Object *ob); -void psys_enable_all(struct Object *ob); -int psys_ob_has_hair(struct Object *ob); + +struct Object *psys_get_lattice(struct ParticleSimulationData *sim); + int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys); int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); -void psys_free_boid_rules(struct ListBase *list); +/* free */ void psys_free_settings(struct ParticleSettings *part); -void free_child_path_cache(struct ParticleSystem *psys); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); -void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics); -void free_keyed_keys(struct ParticleSystem *psys); -void psys_free_particles(struct ParticleSystem *psys); void psys_free(struct Object * ob, struct ParticleSystem * psys); -void psys_free_children(struct ParticleSystem *psys); void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset); void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); @@ -234,45 +247,38 @@ struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc); void make_local_particlesettings(struct ParticleSettings *part); -struct LinkNode *psys_using_settings(struct Scene *scene, struct ParticleSettings *part, int flush_update); void psys_reset(struct ParticleSystem *psys, int mode); -void psys_find_parents(struct Object *ob, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys); +void psys_find_parents(struct ParticleSimulationData *sim); -void psys_cache_paths(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float cfra); +void psys_cache_paths(struct ParticleSimulationData *sim, float cfra); void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra); -void psys_cache_child_paths(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float cfra, int editupdate); +void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, int editupdate); int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb); -float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size); -float psys_get_timestep(struct ParticleSettings *part); +float psys_get_timestep(struct ParticleSimulationData *sim); float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime); float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time); -void psys_get_particle_on_path(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel); -int psys_get_particle_state(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always); +void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, struct ParticleKey *state, int vel); +int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always); + +/* for anim.c */ void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco); -void psys_get_dupli_path_transform(struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); +void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); -ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); -int psys_threads_init_distribution(ParticleThread *threads, struct Scene *scene, struct DerivedMesh *dm, int from); -int psys_threads_init_path(ParticleThread *threads, struct Scene *scene, float cfra, int editupdate); +ParticleThread *psys_threads_create(struct ParticleSimulationData *sim); void psys_threads_free(ParticleThread *threads); -void psys_thread_distribute_particle(ParticleThread *thread, struct ParticleData *pa, struct ChildParticle *cpa, int p); -void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i); - void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]); /* particle_system.c */ struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt); -void psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys); -void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys); +void psys_count_keyed_targets(struct ParticleSimulationData *sim); +//void psys_get_reactor_target(struct ParticleSimulationData *sim, struct Object **target_ob, struct ParticleSystem **target_psys); -void psys_init_effectors(struct Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys); -void psys_end_effectors(struct ParticleSystem *psys); +int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc); void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys); -void psys_end_temp_pointcache(struct ParticleSystem *psys); -void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra); +void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra); void psys_check_boid_data(struct ParticleSystem *psys); @@ -280,39 +286,45 @@ void particle_system_update(struct Scene *scene, struct Object *ob, struct Parti /* ----------- functions needed only inside particlesystem ------------ */ /* particle.c */ +void psys_disable_all(struct Object *ob); +void psys_enable_all(struct Object *ob); + +void free_hair(struct Object *ob, struct ParticleSystem *psys, int dynamics); +void free_keyed_keys(struct ParticleSystem *psys); +void psys_free_particles(struct ParticleSystem *psys); +void psys_free_children(struct ParticleSystem *psys); + void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity); -void psys_key_to_object(struct Object *ob, struct ParticleKey *key, float imat[][4]); -//void psys_key_to_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key); -//void psys_key_from_geometry(struct DerivedMesh *dm, struct ParticleData *pa, struct ParticleKey *key); -//void psys_face_mat(struct DerivedMesh *dm, struct ParticleData *pa, float mat[][4]); void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); -//void psys_vec_rot_from_face(struct DerivedMesh *dm, struct ParticleData *pa, float *vec); void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[][4]); +void psys_free_pdd(struct ParticleSystem *psys); + float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, int vgroup); -void psys_get_texture(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys, struct ParticleData *pa, struct ParticleTexture *ptex, int event); +void psys_get_texture(struct ParticleSimulationData *sim, struct Material *ma, struct ParticleData *pa, struct ParticleTexture *ptex, int event); void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float *uv, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values); -float psys_interpolate_value_from_verts(struct DerivedMesh *dm, short from, int index, float *fw, float *values); void psys_get_from_key(struct ParticleKey *key, float *loc, float *vel, float *rot, float *time); +/* only in edisparticle.c*/ int psys_intersect_dm(struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_uv, float *face_minmax, float *pa_minmax, float radius, float *ipoint); +/* BLI_bvhtree_ray_cast callback */ void particle_intersect_face(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit); void psys_particle_on_dm(struct DerivedMesh *dm, int from, int index, int index_dmcache, float *fw, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor); /* particle_system.c */ -void initialize_particle(struct ParticleData *pa, int p, struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd); +void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, int p); int effector_find_co(struct Scene *scene, float *pco, struct SurfaceModifierData *sur, struct Object *ob, struct PartDeflect *pd, float *co, float *nor, float *vel, int *index); -void do_effectors(int pa_no, struct ParticleData *pa, struct ParticleKey *state, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, float *texco, float *force_field, float *vel,float framestep, float cfra); +void do_effectors(struct ParticleSimulationData *sim, int pa_no, struct ParticleData *pa, struct ParticleKey *state, float *texco, float *force_field, float *vel,float framestep, float cfra); +void psys_end_effectors(struct ParticleSystem *psys); void psys_calc_dmcache(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); -void reset_particle(struct Scene *scene, 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 reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); /* psys_reset */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 8cb88cdb786..e943d92a0b5 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -766,12 +766,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p GroupObject *go; Object *ob=0, **oblist=0, obcopy, *obcopylist=0; DupliObject *dob; + ParticleSimulationData sim = {scene, par, psys, psys_get_modifier(par, psys)}; ParticleSettings *part; ParticleData *pa; ChildParticle *cpa=0; ParticleKey state; ParticleCacheKey *cache; - ParticleSystemModifierData *psmd; float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], size=0.0; float (*obmat)[4], (*oldobmat)[4]; @@ -784,7 +784,6 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if(level>MAX_DUPLI_RECUR) return; part=psys->part; - psmd= psys_get_modifier(par, psys); if(part==0) return; @@ -816,7 +815,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p totpart = psys->totcached; } - psys->lattice = psys_get_lattice(scene, par, psys); + psys->lattice = psys_get_lattice(&sim); /* gather list of objects or single object */ if(part->ren_as==PART_DRAW_GR) { @@ -887,11 +886,11 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p /* hair we handle separate and compute transform based on hair keys */ if(a < totpart) { cache = psys->pathcache[a]; - psys_get_dupli_path_transform(par, psys, psmd, pa, 0, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, pa, 0, cache, pamat, &scale); } else { cache = psys->childcache[a-totpart]; - psys_get_dupli_path_transform(par, psys, psmd, 0, cpa, cache, pamat, &scale); + psys_get_dupli_path_transform(&sim, 0, cpa, cache, pamat, &scale); } VECCOPY(pamat[3], cache->co); @@ -901,7 +900,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else { /* first key */ state.time = ctime; - if(psys_get_particle_state(scene, par, psys, a, &state, 0) == 0) + if(psys_get_particle_state(&sim, a, &state, 0) == 0) continue; QuatToMat4(state.rot, pamat); @@ -921,7 +920,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, obcopylist[b].obmat); if(G.rendering) - psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); + psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } else { @@ -940,7 +939,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p dob= new_dupli_object(lb, ob, mat, ob->lay, counter, OB_DUPLIPARTS, animated); Mat4CpyMat4(dob->omat, oldobmat); if(G.rendering) - psys_get_dupli_texture(par, part, psmd, pa, cpa, dob->uv, dob->orco); + psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } } diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 18f065b59d9..7c3f3a7876f 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -87,7 +87,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, float vec_to_part[3]; if(pd && pd->forcefield == PFIELD_BOID) { - effector_find_co(bbd->scene, pa->prev_state.co, NULL, gabr->ob, pd, loc, vec, NULL, NULL); + effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, gabr->ob, pd, loc, vec, NULL, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); @@ -99,7 +99,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, priority = 1.0; priority_ob = gabr->ob; } - else for(ec=bbd->psys->effectors.first; ec; ec=ec->next) { + else for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { if(ec->type & PSYS_EC_EFFECTOR) { Object *eob = ec->ob; PartDeflect *pd = eob->pd; @@ -111,7 +111,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f) { float vec_to_part[3], temp; - effector_find_co(bbd->scene, pa->prev_state.co, NULL, eob, pd, loc, vec, NULL, NULL); + effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, vec, NULL, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); @@ -147,7 +147,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, if(gabr->options & BRULE_GOAL_AVOID_PREDICT) { /* estimate future location of target */ - surface = (float)effector_find_co(bbd->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, vec, NULL); + surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, vec, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); len = Normalize(vec_to_part); @@ -157,7 +157,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, VecSubf(vec_to_part, pa->prev_state.co, loc); } else { - surface = (float)effector_find_co(bbd->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, NULL, NULL); + surface = (float)effector_find_co(bbd->sim->scene, pa->prev_state.co, NULL, eob, pd, loc, nor, NULL, NULL); VecSubf(vec_to_part, pa->prev_state.co, loc); len = VecLength(vec_to_part); @@ -228,7 +228,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * hit.dist = col.ray_len = VecLength(ray_dir); /* find out closest deflector object */ - for(ec=bbd->psys->effectors.first; ec; ec=ec->next) { + for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { if(ec->type & PSYS_EC_DEFLECT) { Object *eob = ec->ob; @@ -261,12 +261,12 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * //check boids in own system if(acbr->options & BRULE_ACOLL_WITH_BOIDS) { - neighbors = BLI_kdtree_range_search(bbd->psys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); + neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); if(neighbors > 1) for(n=1; nprev_state.co); VECCOPY(vel1, pa->prev_state.vel); - VECCOPY(co2, (bbd->psys->particles + ptn[n].index)->prev_state.co); - VECCOPY(vel2, (bbd->psys->particles + ptn[n].index)->prev_state.vel); + VECCOPY(co2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.co); + VECCOPY(vel2, (bbd->sim->psys->particles + ptn[n].index)->prev_state.vel); VecSubf(loc, co1, co2); @@ -303,8 +303,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* check boids in other systems */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { neighbors = BLI_kdtree_range_search(epsys->tree, acbr->look_ahead * VecLength(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); @@ -362,11 +362,11 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa ParticleTarget *pt; float len = 2.0f * val->personal_space * pa->size + 1.0f; float vec[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_range_search(bbd->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); int ret = 0; if(neighbors > 1 && ptn[1].dist!=0.0f) { - VecSubf(vec, pa->prev_state.co, bbd->psys->particles[ptn[1].index].state.co); + VecSubf(vec, pa->prev_state.co, bbd->sim->psys->particles[ptn[1].index].state.co); VecMulf(vec, (2.0f * val->personal_space * pa->size - ptn[1].dist) / ptn[1].dist); VecAddf(bbd->wanted_co, bbd->wanted_co, vec); bbd->wanted_speed = val->max_speed; @@ -376,8 +376,8 @@ static int rule_separate(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Pa if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* check other boid systems */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { neighbors = BLI_kdtree_range_search(epsys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); @@ -400,14 +400,14 @@ static int rule_flock(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti { KDTreeNearest ptn[11]; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_find_n_nearest(bbd->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn); + int neighbors = BLI_kdtree_find_n_nearest(bbd->sim->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn); int n; int ret = 0; if(neighbors > 1) { for(n=1; npsys->particles[ptn[n].index].prev_state.co); - VecAddf(vec, vec, bbd->psys->particles[ptn[n].index].prev_state.vel); + VecAddf(loc, loc, bbd->sim->psys->particles[ptn[n].index].prev_state.co); + VecAddf(vec, vec, bbd->sim->psys->particles[ptn[n].index].prev_state.vel); } VecMulf(loc, 1.0f/((float)neighbors - 1.0f)); @@ -429,8 +429,8 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader*) rule; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; float mul, len; - int n = (flbr->queue_size <= 1) ? bbd->psys->totpart : flbr->queue_size; - int i, ret = 0, p = pa - bbd->psys->particles; + int n = (flbr->queue_size <= 1) ? bbd->sim->psys->totpart : flbr->queue_size; + int i, ret = 0, p = pa - bbd->sim->psys->particles; if(flbr->ob) { float vec2[3], t; @@ -475,8 +475,8 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* not blocking so try to follow leader */ if(p && flbr->options & BRULE_LEADER_IN_LINE) { - VECCOPY(vec, bbd->psys->particles[p-1].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p-1].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p-1].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p-1].prev_state.co); } else { VECCOPY(loc, flbr->oloc); @@ -496,10 +496,10 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va float vec2[3], t, t_min = 3.0f; /* first check we're not blocking any leaders */ - for(i = 0; i< bbd->psys->totpart; i+=n){ - VECCOPY(vec, bbd->psys->particles[i].prev_state.vel); + for(i = 0; i< bbd->sim->psys->totpart; i+=n){ + VECCOPY(vec, bbd->sim->psys->particles[i].prev_state.vel); - VecSubf(loc, pa->prev_state.co, bbd->psys->particles[i].prev_state.co); + VecSubf(loc, pa->prev_state.co, bbd->sim->psys->particles[i].prev_state.co); mul = Inpf(vec, vec); @@ -539,12 +539,12 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* not blocking so try to follow leader */ if(flbr->options & BRULE_LEADER_IN_LINE) { - VECCOPY(vec, bbd->psys->particles[p-1].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p-1].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p-1].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p-1].prev_state.co); } else { - VECCOPY(vec, bbd->psys->particles[p - p%n].prev_state.vel); - VECCOPY(loc, bbd->psys->particles[p - p%n].prev_state.co); + VECCOPY(vec, bbd->sim->psys->particles[p - p%n].prev_state.vel); + VECCOPY(loc, bbd->sim->psys->particles[p - p%n].prev_state.co); } /* fac is seconds behind leader */ @@ -584,7 +584,7 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* leveling */ if(asbr->level > 0.0f) { - Projf(vec, bbd->wanted_co, bbd->psys->part->acc); + Projf(vec, bbd->wanted_co, bbd->sim->psys->part->acc); VecMulf(vec, asbr->level); VecSubf(bbd->wanted_co, bbd->wanted_co, vec); } @@ -601,7 +601,7 @@ static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *va /* leveling */ if(asbr->level > 0.0f) { - Projf(vec, bbd->wanted_co, bbd->psys->part->acc); + Projf(vec, bbd->wanted_co, bbd->sim->psys->part->acc); VecMulf(vec, asbr->level); VecSubf(bbd->wanted_co, bbd->wanted_co, vec); } @@ -627,9 +627,9 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti int n, ret = 0; /* calculate own group strength */ - int neighbors = BLI_kdtree_range_search(bbd->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); for(n=0; npsys->particles[ptn[n].index].boid; + bpa = bbd->sim->psys->particles[ptn[n].index].boid; health += bpa->data.health; } @@ -638,8 +638,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti if(ptn){ MEM_freeN(ptn); ptn=NULL; } /* add other friendlies and calculate enemy strength and find closest enemy */ - for(pt=bbd->psys->targets.first; pt; pt=pt->next) { - ParticleSystem *epsys = psys_get_target_system(bbd->ob, pt); + for(pt=bbd->sim->psys->targets.first; pt; pt=pt->next) { + ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if(epsys) { epars = epsys->particles; @@ -760,11 +760,11 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro surmd = (SurfaceModifierData *)modifiers_findByType ( bpa->ground, eModifierType_Surface ); /* take surface velocity into account */ - effector_find_co(bbd->scene, pa->state.co, surmd, NULL, NULL, x, NULL, v, NULL); + effector_find_co(bbd->sim->scene, pa->state.co, surmd, NULL, NULL, x, NULL, v, NULL); VecAddf(x, x, v); /* get actual position on surface */ - effector_find_co(bbd->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL); + effector_find_co(bbd->sim->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL); return bpa->ground; } @@ -785,7 +785,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro hit.dist = col.ray_len = VecLength(ray_dir); /* find out upmost deflector object */ - for(ec=bbd->psys->effectors.first; ec; ec=ec->next) { + for(ec=bbd->sim->psys->effectors.first; ec; ec=ec->next) { if(ec->type & PSYS_EC_DEFLECT) { Object *eob = ec->ob; @@ -941,7 +941,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) bbd->wanted_co[0]=bbd->wanted_co[1]=bbd->wanted_co[2]=bbd->wanted_speed=0.0f; /* create random seed for every particle & frame */ - BLI_srandom(bbd->psys->seed + p); + BLI_srandom(bbd->sim->psys->seed + p); rand = BLI_rand(); BLI_srandom((int)bbd->cfra + rand); @@ -1077,7 +1077,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) float ground_co[3] = {0.0f, 0.0f, 0.0f}, ground_nor[3] = {0.0f, 0.0f, 1.0f}; float force[3] = {0.0f, 0.0f, 0.0f}, tvel[3] = {0.0f, 0.0f, 1.0f}; float pa_mass=bbd->part->mass, dtime=bbd->dfra*bbd->timestep; - int p = pa - bbd->psys->particles; + int p = pa - bbd->sim->psys->particles; set_boid_values(&val, boids, pa); @@ -1208,7 +1208,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa) } /* account for effectors */ - do_effectors(p, pa, &pa->state, bbd->scene, bbd->ob, bbd->psys, pa->state.co, force, tvel, bbd->dfra, bbd->cfra); + do_effectors(bbd->sim, p, pa, &pa->state, pa->state.co, force, tvel, bbd->dfra, bbd->cfra); if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) { float length = Normalize(force); diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 9ee6be903fa..5cfbd5c18dc 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -1160,25 +1160,66 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) BLI_linklist_prepend ( &cloth->springs, spring ); } - // bending springs - search2 = cloth->springs; - for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) - { - if ( !search2 ) - break; + if(numfaces) { + // bending springs + search2 = cloth->springs; + for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) + { + if ( !search2 ) + break; - tspring2 = search2->link; - search = edgelist[tspring2->kl]; - while ( search ) + tspring2 = search2->link; + search = edgelist[tspring2->kl]; + while ( search ) + { + tspring = search->link; + index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); + + // check for existing spring + // check also if startpoint is equal to endpoint + if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) ) + && ( index2!=tspring2->ij ) ) + { + spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + + if(!spring) + { + cloth_free_errorsprings(cloth, edgehash, edgelist); + return 0; + } + + spring->ij = MIN2(tspring2->ij, index2); + spring->kl = MAX2(tspring2->ij, index2); + VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); + spring->restlen = sqrt ( INPR ( temp, temp ) ); + spring->type = CLOTH_SPRING_TYPE_BENDING; + spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; + BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL ); + bend_springs++; + + BLI_linklist_prepend ( &cloth->springs, spring ); + } + search = search->next; + } + search2 = search2->next; + } + } + else if(struct_springs > 2) { + /* bending springs for hair strands */ + /* The current algorightm only goes through the edges in order of the mesh edges list */ + /* and makes springs between the outer vert of edges sharing a vertice. This works just */ + /* fine for hair, but not for user generated string meshes. This could/should be later */ + /* extended to work with non-ordered edges so that it can be used for general "rope */ + /* dynamics" without the need for the vertices or edges to be ordered through the length*/ + /* of the strands. -jahka */ + search = cloth->springs; + search2 = search->next; + while(search && search2) { tspring = search->link; - index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); - - // check for existing spring - // check also if startpoint is equal to endpoint - if ( !BLI_edgehash_haskey ( edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2) ) - && ( index2!=tspring2->ij ) ) - { + tspring2 = search2->link; + + if(tspring->ij == tspring2->kl) { spring = ( ClothSpring * ) MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if(!spring) @@ -1187,20 +1228,20 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) return 0; } - spring->ij = MIN2(tspring2->ij, index2); - spring->kl = MAX2(tspring2->ij, index2); + spring->ij = tspring2->ij; + spring->kl = tspring->kl; VECSUB ( temp, cloth->verts[spring->kl].x, cloth->verts[spring->ij].x ); spring->restlen = sqrt ( INPR ( temp, temp ) ); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0; - BLI_edgehash_insert ( edgehash, spring->ij, spring->kl, NULL ); bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); } + search = search->next; + search2 = search2->next; } - search2 = search2->next; } /* insert other near springs in edgehash AFTER bending springs are calculated (for selfcolls) */ diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 58f3db50d0f..4c2b2f3ec12 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -560,6 +560,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O for(; psys; psys=psys->next) { BoidRule *rule = NULL; BoidState *state = NULL; + ParticleSimulationData sim = {scene, ob, psys, NULL}; ParticleSettings *part= psys->part; dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); @@ -592,8 +593,7 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } - psys_end_effectors(psys); - psys_init_effectors(scene, ob, psys->part->eff_group, psys); + psys_update_effectors(&sim, 0.0, 0); for(nec= psys->effectors.first; nec; nec= nec->next) { Object *ob1= nec->ob; diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index c64c48b9ce7..b9b9ea6b4f3 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6601,6 +6601,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( { DerivedMesh *dm = derivedData, *result; ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md; + ParticleSimulationData sim; ParticleSystem * psys=0; ParticleData *pa=0, *pars=0; MFace *mface, *orig_mface; @@ -6635,6 +6636,11 @@ static DerivedMesh * particleInstanceModifier_applyModifier( if(totpart==0) return derivedData; + sim.scene = md->scene; + sim.ob = pimd->ob; + sim.psys = psys; + sim.psmd = psys_get_modifier(pimd->ob, psys); + if(pimd->flag & eParticleInstanceFlag_UseSize) { int p; float *si; @@ -6662,7 +6668,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( maxvert=totvert*totpart; maxface=totface*totpart; - psys->lattice=psys_get_lattice(md->scene, ob, psys); + psys->lattice=psys_get_lattice(&sim); if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){ @@ -6712,7 +6718,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( mv->co[axis] = 0.0; } - psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1); + psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1); Normalize(state.vel); @@ -6734,7 +6740,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier( } else{ state.time=-1.0; - psys_get_particle_state(md->scene, pimd->ob, psys, first_particle + i/totvert, &state,1); + psys_get_particle_state(&sim, first_particle + i/totvert, &state,1); } QuatMulVecf(state.rot,mv->co); @@ -7416,6 +7422,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, DerivedMesh *explode, *dm=to_explode; MFace *mf=0; ParticleSettings *part=psmd->psys->part; + ParticleSimulationData sim = {scene, ob, psmd->psys, psmd}; ParticleData *pa=NULL, *pars=psmd->psys->particles; ParticleKey state; EdgeHash *vertpahash; @@ -7431,7 +7438,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, totvert= dm->getNumVerts(dm); totpart= psmd->psys->totpart; - timestep= psys_get_timestep(part); + timestep= psys_get_timestep(&sim); //if(part->flag & PART_GLOB_TIME) cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0); @@ -7474,7 +7481,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, /* getting back to object space */ Mat4Invert(imat,ob->obmat); - psmd->psys->lattice = psys_get_lattice(scene, ob, psmd->psys); + psmd->psys->lattice = psys_get_lattice(&sim); /* duplicate & displace vertices */ ehi= BLI_edgehashIterator_new(vertpahash); @@ -7502,7 +7509,7 @@ static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd, Mat4MulVecfl(ob->obmat,loc0); state.time=cfra; - psys_get_particle_state(scene, ob, psmd->psys, i, &state,1); + psys_get_particle_state(&sim, i, &state, 1); vertco=CDDM_get_vert(explode,v)->co; @@ -7591,7 +7598,7 @@ static DerivedMesh * explodeModifier_applyModifier( { DerivedMesh *dm = derivedData; ExplodeModifierData *emd= (ExplodeModifierData*) md; - ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md);; + ParticleSystemModifierData *psmd=explodeModifier_findPrecedingParticlesystem(ob,md); if(psmd){ ParticleSystem * psys=psmd->psys; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index cce18e99157..0dc041bfc6a 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -69,7 +69,7 @@ #include "BKE_particle.h" #include "BKE_DerivedMesh.h" #include "BKE_object.h" -#include "BKE_softbody.h" +#include "BKE_cloth.h" #include "BKE_material.h" #include "BKE_key.h" #include "BKE_library.h" @@ -85,7 +85,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float *fuv, float *orco, ParticleTexture *ptex, int event); static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex); -static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, +static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t); @@ -95,11 +95,10 @@ int count_particles(ParticleSystem *psys){ PARTICLE_P; int tot=0; - LOOP_PARTICLES { + LOOP_SHOWN_PARTICLES { if(pa->alive == PARS_KILLED); else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)); else tot++; } return tot; @@ -109,55 +108,14 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){ PARTICLE_P; int tot=0; - LOOP_PARTICLES { + LOOP_SHOWN_PARTICLES { if(pa->alive == PARS_KILLED); else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0); else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0); - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)); else if(p%totgr==cur) tot++; } return tot; } -int psys_count_keys(ParticleSystem *psys) -{ - PARTICLE_P; - int totkey=0; - - LOOP_PARTICLES - totkey += pa->totkey; - - return totkey; -} -/* remember to free the pointer returned from this! */ -char *psys_menu_string(Object *ob, int for_sb) -{ - ParticleSystem *psys; - DynStr *ds; - char *str, num[6]; - int i; - - ds = BLI_dynstr_new(); - - if(for_sb) - BLI_dynstr_append(ds, "|Object%x-1"); - - for(i=0,psys=ob->particlesystem.first; psys; i++,psys=psys->next){ - - BLI_dynstr_append(ds, "|"); - sprintf(num,"%i. ",i+1); - BLI_dynstr_append(ds, num); - BLI_dynstr_append(ds, psys->part->id.name+2); - sprintf(num,"%%x%i",i+1); - BLI_dynstr_append(ds, num); - } - - str = BLI_dynstr_get_cstring(ds); - - BLI_dynstr_free(ds); - - return str; -} - /* we allocate path cache memory in chunks instead of a big continguous * chunk, windows' memory allocater fails to find big blocks of memory often */ @@ -257,30 +215,13 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys) return NULL; } -/* change object's active particle system */ -void psys_change_act(void *ob_v, void *act_v) -{ - Object *ob = ob_v; - ParticleSystem *npsys, *psys; - short act = *((short*)act_v)-1; - - if(act>=0){ - npsys=BLI_findlink(&ob->particlesystem,act); - psys=psys_get_current(ob); - - if(psys) - psys->flag &= ~PSYS_CURRENT; - if(npsys) - npsys->flag |= PSYS_CURRENT; - } -} -Object *psys_get_lattice(Scene *scene, Object *ob, ParticleSystem *psys) +Object *psys_get_lattice(ParticleSimulationData *sim) { Object *lattice=0; - if(psys_in_edit_mode(scene, psys)==0){ + if(psys_in_edit_mode(sim->scene, sim->psys)==0){ - ModifierData *md = (ModifierData*)psys_get_modifier(ob,psys); + ModifierData *md = (ModifierData*)psys_get_modifier(sim->ob, sim->psys); for(; md; md=md->next){ if(md->type==eModifierType_Lattice){ @@ -309,20 +250,20 @@ void psys_enable_all(Object *ob) for(; psys; psys=psys->next) psys->flag &= ~PSYS_DISABLED; } -int psys_ob_has_hair(Object *ob) -{ - ParticleSystem *psys = ob->particlesystem.first; - - for(; psys; psys=psys->next) - if(psys->part->type == PART_HAIR) - return 1; - - return 0; -} int psys_in_edit_mode(Scene *scene, ParticleSystem *psys) { return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit)); } +static void psys_create_frand(ParticleSystem *psys) +{ + int i; + float *rand = psys->frand = MEM_callocN(PSYS_FRAND_COUNT * sizeof(float), "particle randoms"); + + BLI_srandom(psys->seed); + + for(i=0; i<1024; i++, rand++) + *rand = BLI_frand(); +} int psys_check_enabled(Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd; @@ -344,6 +285,14 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) } else if(!(psmd->modifier.mode & eModifierMode_Realtime)) return 0; + + /* perhaps not the perfect place, but we have to be sure the rands are there before usage */ + if(!psys->frand) + psys_create_frand(psys); + else if(psys->recalc & PSYS_RECALC_RESET) { + MEM_freeN(psys->frand); + psys_create_frand(psys); + } return 1; } @@ -423,7 +372,7 @@ void free_keyed_keys(ParticleSystem *psys) } } } -void free_child_path_cache(ParticleSystem *psys) +static void free_child_path_cache(ParticleSystem *psys) { psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs); psys->childcache = NULL; @@ -477,6 +426,24 @@ void psys_free_particles(ParticleSystem *psys) psys->totpart= 0; } } +void psys_free_pdd(ParticleSystem *psys) +{ + if(psys->pdd->cdata) + MEM_freeN(psys->pdd->cdata); + psys->pdd->cdata = NULL; + + if(psys->pdd->vdata) + MEM_freeN(psys->pdd->vdata); + psys->pdd->vdata = NULL; + + if(psys->pdd->ndata) + MEM_freeN(psys->pdd->ndata); + psys->pdd->ndata = NULL; + + if(psys->pdd->vedata) + MEM_freeN(psys->pdd->vedata); + psys->pdd->vedata = NULL; +} /* free everything */ void psys_free(Object *ob, ParticleSystem * psys) { @@ -530,6 +497,14 @@ void psys_free(Object *ob, ParticleSystem * psys) BLI_kdtree_free(psys->tree); + if(psys->frand) + MEM_freeN(psys->frand); + + if(psys->pdd) { + psys_free_pdd(psys); + MEM_freeN(psys->pdd); + } + MEM_freeN(psys); } } @@ -721,12 +696,12 @@ void psys_render_restore(Object *ob, ParticleSystem *psys) int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) { DerivedMesh *dm= ctx->dm; - Mesh *me= (Mesh*)(ctx->ob->data); + Mesh *me= (Mesh*)(ctx->sim.ob->data); MFace *mf, *mface; MVert *mvert; ParticleRenderData *data; ParticleRenderElem *elems, *elem; - ParticleSettings *part= ctx->psys->part; + ParticleSettings *part= ctx->sim.psys->part; float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp; float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport; double vprate; @@ -735,10 +710,10 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) return tot; - if(!ctx->psys->renderdata) + if(!ctx->sim.psys->renderdata) return tot; - data= ctx->psys->renderdata; + data= ctx->sim.psys->renderdata; if(data->timeoffset) return 0; if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE)) @@ -815,7 +790,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) /* set simplification parameters per original face */ for(a=0, elem=elems; apsys, facecenter[a], facearea[a], vprate, &viewport); + area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport); arearatio= fac*area/facearea[a]; if((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) { @@ -1437,7 +1412,7 @@ void psys_interpolate_mcol(MCol *mcol, int quad, float *w, MCol *mc) } } -float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values) +static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values) { if(values==0 || index==-1) return 0.0; @@ -2074,7 +2049,7 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float VECADDFAC(state->co,state->co,mat[0],rough[0]); VECADDFAC(state->co,state->co,mat[1],rough[1]); } -static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) +static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) { float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}; ParticleKey eff_key; @@ -2084,10 +2059,10 @@ static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, in VECCOPY(eff_key.vel,(ca-1)->vel); QUATCOPY(eff_key.rot,(ca-1)->rot); - pa= psys->particles+i; - do_effectors(i, pa, &eff_key, scene, ob, psys, rootco, force, vel, dfra, cfra); + pa= sim->psys->particles+i; + do_effectors(sim, i, pa, &eff_key, rootco, force, vel, dfra, cfra); - VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps); + VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps); VecAddf(force, force, vec); @@ -2154,12 +2129,12 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup) } return vg; } -void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys) +void psys_find_parents(ParticleSimulationData *sim) { - ParticleSettings *part=psys->part; + ParticleSettings *part=sim->psys->part; KDTree *tree; ChildParticle *cpa; - int p, totparent,totchild=psys->totchild; + int p, totparent,totchild=sim->psys->totchild; float co[3], orco[3]; int from=PART_FROM_FACE; totparent=(int)(totchild*part->parents*0.3); @@ -2169,15 +2144,15 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys tree=BLI_kdtree_new(totparent); - for(p=0,cpa=psys->child; pnum,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + for(p=0,cpa=sim->psys->child; ppsmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); BLI_kdtree_insert(tree, p, orco, NULL); } BLI_kdtree_balance(tree); for(; pnum,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); cpa->parent=BLI_kdtree_find_nearest(tree, orco, NULL, NULL); } @@ -2215,11 +2190,11 @@ static void get_strand_normal(Material *ma, float *surfnor, float surfdist, floa VECCOPY(nor, vnor); } -int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) +static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) { ParticleThreadContext *ctx= threads[0].ctx; - Object *ob= ctx->ob; - ParticleSystem *psys= ctx->psys; + Object *ob= ctx->sim.ob; + ParticleSystem *psys= ctx->sim.psys; ParticleSettings *part = psys->part; ParticleEditSettings *pset = &scene->toolsettings->particle; int totparent=0, between=0; @@ -2252,10 +2227,10 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in if(totchild==0) return 0; /* init random number generator */ - if(ctx->psys->part->flag & PART_ANIM_BRANCHING) - seed= 31415926 + ctx->psys->seed + (int)cfra; + if(ctx->sim.psys->part->flag & PART_ANIM_BRANCHING) + seed= 31415926 + ctx->sim.psys->seed + (int)cfra; else - seed= 31415926 + ctx->psys->seed; + seed= 31415926 + ctx->sim.psys->seed; if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000) totthread= 1; @@ -2273,7 +2248,7 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in ctx->parent_pass= 0; ctx->cfra= cfra; - psys->lattice = psys_get_lattice(scene, ob, psys); + psys->lattice = psys_get_lattice(&ctx->sim); /* cache all relevant vertex groups if they exist */ if(part->from!=PART_FROM_PARTICLE){ @@ -2299,11 +2274,11 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in } /* note: this function must be thread safe, except for branching! */ -void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) +static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i) { ParticleThreadContext *ctx= thread->ctx; - Object *ob= ctx->ob; - ParticleSystem *psys = ctx->psys; + Object *ob= ctx->sim.ob; + ParticleSystem *psys = ctx->sim.psys; ParticleSettings *part = psys->part; ParticleCacheKey **cache= psys->childcache; ParticleCacheKey **pcache= psys->pathcache; @@ -2372,7 +2347,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; - psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); + psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0); if(part->path_start==0.0f) { /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ @@ -2382,7 +2357,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, pa = psys->particles + cpa->parent; - psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); pa=0; } @@ -2404,9 +2379,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, cpa_num=pa->num; cpa_fuv=pa->fuv; - psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); + psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0); - psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat); } keys->steps = ctx->steps; @@ -2423,7 +2398,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, /* get different child parameters from textures & vgroups */ get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex); - if(ptex.exist < cpa->rand[1]) { + if(ptex.exist < PSYS_FRAND(i + 24)) { keys->steps = -1; return; } @@ -2472,7 +2447,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, if(part->flag & PART_CHILD_EFFECT) { for(k=0,state=keys; k<=ctx->steps; k++,state++) { if(k) { - do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); + do_path_effectors(&ctx->sim, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec); } else { VecSubf(eff_vec,(state+1)->co,state->co); @@ -2498,7 +2473,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, } /* apply different deformations to the child path */ - do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); + do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t); /* TODO: better branching */ //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING) @@ -2575,7 +2550,7 @@ static void *exec_child_path_cache(void *data) { ParticleThread *thread= (ParticleThread*)data; ParticleThreadContext *ctx= thread->ctx; - ParticleSystem *psys= ctx->psys; + ParticleSystem *psys= ctx->sim.psys; ParticleCacheKey **cache= psys->childcache; ChildParticle *cpa; int i, totchild= ctx->totchild, first= 0; @@ -2592,21 +2567,21 @@ static void *exec_child_path_cache(void *data) return 0; } -void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate) { - ParticleSettings *part = psys->part; + ParticleSettings *part = sim->psys->part; ParticleThread *pthreads; ParticleThreadContext *ctx; ParticleCacheKey **cache; ListBase threads; int i, totchild, totparent, totthread; - if(psys->flag & PSYS_GLOBAL_HAIR) + if(sim->psys->flag & PSYS_GLOBAL_HAIR) return; - pthreads= psys_threads_create(scene, ob, psys); + pthreads= psys_threads_create(sim); - if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) { + if(!psys_threads_init_path(pthreads, sim->scene, cfra, editupdate)) { psys_threads_free(pthreads); return; } @@ -2615,14 +2590,14 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa totchild= ctx->totchild; totparent= ctx->totparent; - if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) { - cache = psys->childcache; + if(editupdate && sim->psys->childcache && !(part->flag & PART_BRANCHING) && totchild == sim->psys->totchildcache) { + cache = sim->psys->childcache; } else { /* clear out old and create new empty path cache */ - free_child_path_cache(psys); - psys->childcache= psys_alloc_path_cache_buffers(&psys->childcachebufs, totchild, ctx->steps+1); - psys->totchildcache = totchild; + free_child_path_cache(sim->psys); + sim->psys->childcache= psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps+1); + sim->psys->totchildcache = totchild; } totthread= pthreads[0].tot; @@ -2660,27 +2635,29 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ /* -Cached path data is also used to determine cut position for the editmode tool. */ -void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra) +void psys_cache_paths(ParticleSimulationData *sim, float cfra) { - ParticleCacheKey *ca, **cache= psys->pathcache; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + PARTICLE_PSMD; + ParticleEditSettings *pset = &sim->scene->toolsettings->particle; + ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; - ParticleEditSettings *pset = &scene->toolsettings->particle; + ParticleCacheKey *ca, **cache= psys->pathcache; DerivedMesh *hair_dm = psys->hair_out_dm; - ParticleData *pa = psys->particles; ParticleKey result; Material *ma; ParticleInterpolationData pind; + + PARTICLE_P; float birthtime = 0.0, dietime = 0.0; - float t, time = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; + float t, time = 0.0, dfra = 1.0, frs_sec = sim->scene->r.frs_sec; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; float prev_tangent[3], hairmat[4][4]; float rotmat[3][3]; - int k,i; + int k; int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step)); int totpart = psys->totpart; float length, vec[3]; @@ -2692,7 +2669,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) return; - if(psys_in_edit_mode(scene, psys)) + if(psys_in_edit_mode(sim->scene, psys)) if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0) return; @@ -2705,8 +2682,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra psys_free_path_cache(psys, psys->edit); cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1); - psys->lattice = psys_get_lattice(scene, ob, psys); - ma= give_current_material(ob, psys->part->omat); + psys->lattice = psys_get_lattice(sim); + ma= give_current_material(sim->ob, psys->part->omat); if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) @@ -2719,12 +2696,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } /*---first main loop: create all actual particles' paths---*/ - for(i=0; iflag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) - continue; - + LOOP_SHOWN_PARTICLES { if(!psys->totchild) { - BLI_srandom(psys->seed + i); + BLI_srandom(psys->seed + p); pa_length = 1.0f - part->randlength * BLI_frand(); if(vg_length) pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length); @@ -2736,15 +2710,15 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE); pind.dm = hair_dm; - memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); + memset(cache[p], 0, sizeof(*cache[p])*(steps+1)); - cache[i]->steps = steps; + cache[p]->steps = steps; /*--get the first data points--*/ - init_particle_interpolation(ob, psys, pa, &pind); + init_particle_interpolation(sim->ob, sim->psys, pa, &pind); /* hairmat is needed for for non-hair particle too so we get proper rotations */ - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, psmd->dm, psys->part->from, pa, hairmat); VECCOPY(rotmat[0], hairmat[2]); VECCOPY(rotmat[1], hairmat[1]); VECCOPY(rotmat[2], hairmat[0]); @@ -2760,26 +2734,26 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra } if(birthtime >= dietime) { - cache[i]->steps = -1; + cache[p]->steps = -1; continue; } dietime = birthtime + pa_length * (dietime - birthtime); /*--interpolate actual path from data points--*/ - for(k=0, ca=cache[i]; k<=steps; k++, ca++){ + for(k=0, ca=cache[p]; k<=steps; k++, ca++){ time = (float)k / (float)steps; t = birthtime + time * (dietime - birthtime); result.time = -t; - do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result); + do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, &result); /* dynamic hair is in object space */ /* keyed and baked are allready in global space */ if(hair_dm) - Mat4MulVecfl(ob->obmat, result.co); + Mat4MulVecfl(sim->ob->obmat, result.co); else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR)) Mat4MulVecfl(hairmat, result.co); @@ -2789,23 +2763,23 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra /*--modify paths and calculate rotation & velocity--*/ - VecSubf(vec,(cache[i]+1)->co,cache[i]->co); + VecSubf(vec,(cache[p]+1)->co,cache[p]->co); length = VecLength(vec); effector= 1.0f; if(vg_effector) effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector); - for(k=0, ca=cache[i]; k<=steps; k++, ca++) { + for(k=0, ca=cache[p]; k<=steps; k++, ca++) { if(!(psys->flag & PSYS_GLOBAL_HAIR)) { /* apply effectors */ if(!(psys->part->flag & PART_CHILD_EFFECT) && k) - do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); + do_path_effectors(sim, p, ca, k, steps, cache[p]->co, effector, dfra, cfra, &length, vec); /* apply guide curves to path data */ if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) /* ca is safe to cast, since only co and vel are used */ - do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); + do_guide(sim->scene, (ParticleKey*)ca, p, (float)k/(float)steps, &psys->effectors); /* apply lattice */ if(psys->lattice) @@ -3021,23 +2995,6 @@ void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, flo if(time) *time=key->time; } /*-------changing particle keys from space to another-------*/ -void psys_key_to_object(Object *ob, ParticleKey *key, float imat[][4]){ - float q[4], imat2[4][4]; - - if(imat==0){ - Mat4Invert(imat2,ob->obmat); - imat=imat2; - } - - VECADD(key->vel,key->vel,key->co); - - Mat4MulVecfl(imat,key->co); - Mat4MulVecfl(imat,key->vel); - Mat4ToQuat(imat,q); - - VECSUB(key->vel,key->vel,key->co); - QuatMul(key->rot,q,key->rot); -} #if 0 static void key_from_object(Object *ob, ParticleKey *key){ float q[4]; @@ -3410,41 +3367,6 @@ void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int reca } } -LinkNode *psys_using_settings(struct Scene *scene, ParticleSettings *part, int flush_update) -{ - Object *ob, *tob; - ParticleSystem *psys, *tpsys; - LinkNode *node= NULL; - int found; - - /* update all that have same particle settings */ - for(ob=G.main->object.first; ob; ob=ob->id.next) { - found= 0; - - for(psys=ob->particlesystem.first; psys; psys=psys->next) { - if(psys->part == part) { - BLI_linklist_append(&node, psys); - found++; - } - else if(psys->part->type == PART_REACTOR){ - tob= (psys->target_ob)? psys->target_ob: ob; - tpsys= BLI_findlink(&tob->particlesystem, psys->target_psys-1); - - if(tpsys && tpsys->part==part) { - BLI_linklist_append(&node, tpsys); - found++; - } - } - } - - if(flush_update && found) - DAG_id_flush_update(&ob->id, OB_RECALC_DATA); - } - - return node; -} - - /************************************************/ /* Textures */ /************************************************/ @@ -3541,7 +3463,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float } if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } } -void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event) +void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *pa, ParticleTexture *ptex, int event) { MTex *mtex; int m; @@ -3556,14 +3478,14 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd short blend=mtex->blendtype; short neg=mtex->pmaptoneg; - if((mtex->texco & TEXCO_UV) && ELEM(psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { - if(!get_particle_uv(psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { + if((mtex->texco & TEXCO_UV) && ELEM(sim->psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) { + if(!get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) { /* failed to get uv's, let's try orco's */ - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } } else { - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); + psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0); } externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3); @@ -3608,38 +3530,9 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd /************************************************/ /* Particle State */ /************************************************/ -float psys_get_timestep(ParticleSettings *part) +float psys_get_timestep(ParticleSimulationData *sim) { - return 0.04f*part->timetweak; -} -/* part->size should be updated with possible ipo effection before this is called */ -float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, IpoCurve *icu_size, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, float *vg_size) -{ - ParticleTexture ptex; - float size=1.0f; - - BLI_srandom(psys->seed + (pa - psys->particles) + 100); - - if(ma && part->from!=PART_FROM_PARTICLE){ - ptex.size=size; - psys_get_texture(ob,ma,psmd,psys,pa,&ptex,MAP_PA_SIZE); - size=ptex.size; - } - -#if 0 // XXX old animation system - if(icu_size){ - calc_icu(icu_size,pa->time); - size*=icu_size->curval; - } -#endif // XXX old animation system - - if(vg_size) - size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size); - - if(part->randsize!=0.0) - size*= 1.0f - part->randsize * BLI_frand(); - - return size*part->size; + return 0.04f * sim->psys->part->timetweak; } float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime) { @@ -3654,7 +3547,7 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, w++; } - life = part->lifetime*(1.0f-part->randlife*cpa->rand[1]); + life = part->lifetime * (1.0f - part->randlife * PSYS_FRAND(cpa - psys->child + 25)); } else{ ParticleData *pa = psys->particles + cpa->parent; @@ -3703,13 +3596,16 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, size*=part->childsize; if(part->childrandsize!=0.0) - size *= 1.0f - part->childrandsize*cpa->rand[2]; + size *= 1.0f - part->childrandsize * PSYS_FRAND(cpa - psys->child + 26); return size; } static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex) { - ptex->length= 1.0f - part->randlength*cpa->rand[0]; + ParticleSystem *psys = ctx->sim.psys; + int i = cpa - psys->child; + + ptex->length= 1.0f - part->randlength * PSYS_FRAND(i + 26); ptex->clump=1.0; ptex->kink=1.0; ptex->rough1= 1.0; @@ -3718,13 +3614,13 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread ptex->exist= 1.0; ptex->effector= 1.0; - ptex->length*= part->clength_thres < cpa->rand[1] ? part->clength : 1.0f; + ptex->length*= part->clength_thres < PSYS_FRAND(i + 27) ? part->clength : 1.0f; get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex, MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); - if(ptex->exist < cpa->rand[1]) + if(ptex->exist < PSYS_FRAND(i + 24)) return; if(ctx->vg_length) @@ -3742,18 +3638,20 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread if(ctx->vg_effector) ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector); } -static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t) +static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t) { + ParticleSettings *part = sim->psys->part; + int i = cpa - sim->psys->child; int guided = 0; if(part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ - guided = do_guide(scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors)); + guided = do_guide(sim->scene, (ParticleKey*)state, cpa->parent, t, &(sim->psys->effectors)); if(guided==0){ if(part->kink) do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape, - part->kink_amp, part->kink, part->kink_axis, ob->obmat); + part->kink_amp, part->kink, part->kink_axis, sim->ob->obmat); do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump); } @@ -3762,17 +3660,18 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state); if(part->rough2 != 0.0 && ptex->rough2 != 0.0) - do_rough(cpa->rand, mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); + do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state); if(part->rough_end != 0.0 && ptex->roughe != 0.0) - do_rough_end(cpa->rand, mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); + do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state); } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ -void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) +void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, int vel) { - ParticleSettings *part = psys->part; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - Material *ma = give_current_material(ob, part->omat); + PARTICLE_PSMD; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = sim->psys->part; + Material *ma = give_current_material(sim->ob, part->omat); ParticleData *pa; ChildParticle *cpa; ParticleTexture ptex; @@ -3780,7 +3679,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i ParticleThreadContext ctx; /* fake thread context for child modifiers */ ParticleInterpolationData pind; - float t, frs_sec = scene->r.frs_sec; + float t, frs_sec = sim->scene->r.frs_sec; float co[3], orco[3]; float hairmat[4][4]; int totparent = 0; @@ -3808,17 +3707,17 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i pind.cache = cached ? psys->pointcache : NULL; pind.epoint = NULL; pind.dm = psys->hair_out_dm; - init_particle_interpolation(ob, psys, pa, &pind); + init_particle_interpolation(sim->ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state); if(!keyed && !cached) { if((pa->flag & PARS_REKEY)==0) { - psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat); Mat4MulVecfl(hairmat, state->co); Mat4Mul3Vecfl(hairmat, state->vel); if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { - do_guide(scene, state, p, state->time, &psys->effectors); + do_guide(sim->scene, state, p, state->time, &psys->effectors); /* TODO: proper velocity handling */ } @@ -3851,7 +3750,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i /* get parent states */ while(w<4 && cpa->pa[w]>=0){ keys[w].time = state->time; - psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1); + psys_get_particle_on_path(sim, cpa->pa[w], keys+w, 1); w++; } @@ -3871,14 +3770,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i pa = psys->particles + cpa->parent; - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); pa=0; } else{ /* get the parent state */ keys->time = state->time; - psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); + psys_get_particle_on_path(sim, cpa->parent, keys,1); /* get the original coordinates (orco) for texture usage */ pa=psys->particles+cpa->parent; @@ -3889,7 +3788,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0); - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); } /* correct child ipo timing */ @@ -3938,7 +3837,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i copy_particle_key(&tstate, state, 1); /* apply different deformations to the child path */ - do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, hairmat, state, t); + do_child_modifiers(sim, &ptex, par, par->rot, cpa, orco, hairmat, state, t); /* try to estimate correct velocity */ if(vel){ @@ -3947,13 +3846,13 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i if(t>=0.001f){ tstate.time=t-0.001f; - psys_get_particle_on_path(scene,ob,psys,p,&tstate,0); + psys_get_particle_on_path(sim,p,&tstate,0); VECSUB(state->vel,state->co,tstate.co); Normalize(state->vel); } else{ tstate.time=t+0.001f; - psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); + psys_get_particle_on_path(sim,p,&tstate,0); VECSUB(state->vel,tstate.co,state->co); Normalize(state->vel); } @@ -3963,39 +3862,52 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i } } /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ -int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){ - ParticleSettings *part=psys->part; - ParticleData *pa=0; +int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always){ + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + ParticleData *pa = NULL; + ChildParticle *cpa = NULL; float cfra; - int totpart=psys->totpart, between=0; + int totpart = psys->totpart, between = 0; /* negative time means "use current time" */ - if(state->time>0) - cfra=state->time; - else - cfra= bsystem_time(scene, 0, (float)scene->r.cfra,0.0); + cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0); - if(psys->totchild && p>=totpart){ - if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ - between=1; - } - else - pa=psys->particles+(psys->child+p-totpart)->parent; - } - else - pa=psys->particles+p; + if(p>=totpart){ + if(!psys->totchild) + return 0; - if(between){ - state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL); - - if(always==0) - if((state->time<0.0 && (part->flag & PART_UNBORN)==0) - || (state->time>1.0 && (part->flag & PART_DIED)==0)) + if(part->from != PART_FROM_PARTICLE && part->childtype == PART_CHILD_FACES){ + if(!(psys->flag & PSYS_KEYED)) return 0; + + cpa = psys->child + p - totpart; + + state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL); + + if(!always) + if((state->time < 0.0 && !(part->flag & PART_UNBORN)) + || (state->time > 1.0 && !(part->flag & PART_DIED))) + return 0; + + state->time= (cfra - (part->sta + (part->end - part->sta) * PSYS_FRAND(p + 23))) / (part->lifetime * PSYS_FRAND(p + 24)); + + psys_get_particle_on_path(sim, p, state,1); + return 1; + } + else { + cpa = sim->psys->child + p - totpart; + pa = sim->psys->particles + cpa->parent; + } } - else{ - if(pa->alive==PARS_KILLED) return 0; - if(always==0) + else { + pa = sim->psys->particles + p; + } + + if(pa) { + if(pa->alive == PARS_KILLED) return 0; + + if(!always) if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0) || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0)) return 0; @@ -4003,38 +3915,28 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy state->time = MIN2(state->time, pa->dietime); } - 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; - - psys_get_particle_on_path(scene, ob, psys, p, state,1); + if(sim->psys->flag & PSYS_KEYED){ + state->time= -cfra; + psys_get_particle_on_path(sim, p, state,1); return 1; } else{ - if(between) - return 0; /* currently not supported */ - else if(psys->totchild && p>=psys->totpart){ - ChildParticle *cpa=psys->child+p-psys->totpart; + if(cpa){ ParticleKey *key1; float t = (cfra - pa->time + pa->loop * pa->lifetime) / pa->lifetime; - pa = psys->particles + cpa->parent; key1=&pa->state; offset_child(cpa, key1, state, part->childflat, part->childrad); CLAMP(t,0.0,1.0); if(part->kink) /* TODO: part->kink_freq*pa_kink */ - do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,ob->obmat); + do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,sim->ob->obmat); /* TODO: pa_clump vgroup */ do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); if(psys->lattice) - calc_latt_deform(psys->lattice, state->co,1.0f); + calc_latt_deform(sim->psys->lattice, state->co,1.0f); } else{ if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) @@ -4045,7 +3947,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy /* let's interpolate to try to be as accurate as possible */ if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { ParticleKey keys[4]; - float dfra, keytime, frs_sec = scene->r.frs_sec; + float dfra, keytime, frs_sec = sim->scene->r.frs_sec; if(pa->prev_state.time >= pa->state.time) { /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ @@ -4080,8 +3982,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy } } - if(psys->lattice) - calc_latt_deform(psys->lattice, state->co,1.0f); + if(sim->psys->lattice) + calc_latt_deform(sim->psys->lattice, state->co,1.0f); } return 1; @@ -4137,8 +4039,11 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo } } -void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) +void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) { + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; + ParticleSystemModifierData *psmd = sim->psmd; float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4]; float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; @@ -4146,7 +4051,7 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys len= Normalize(vec); if(pa) - psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); + psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0); else psys_particle_on_emitter(psmd, (psys->part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE, diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 26d23399316..9cd897e4bcd 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -164,20 +164,22 @@ void psys_reset(ParticleSystem *psys, int mode) psys->pointcache->simframe= 0; } -static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) +static void realloc_particles(ParticleSimulationData *sim, int new_totpart) { + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; ParticleData *newpars = NULL; BoidParticle *newboids = NULL; PARTICLE_P; int totpart, totsaved = 0; if(new_totpart<0) { - if(psys->part->distr==PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) { - totpart= psys->part->grid_res; + if(part->distr==PART_DISTR_GRID && part->from != PART_FROM_VERT) { + totpart= part->grid_res; totpart*=totpart*totpart; } else - totpart=psys->part->totpart; + totpart=part->totpart; } else totpart=new_totpart; @@ -212,6 +214,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(pa->hair) MEM_freeN(pa->hair); MEM_freeN(psys->particles); + psys_free_pdd(psys); } psys->particles=newpars; @@ -605,13 +608,13 @@ static int binary_search_distribution(float *sum, int n, float value) /* note: this function must be thread safe, for from == PART_FROM_CHILD */ #define ONLY_WORKING_WITH_PA_VERTS 0 -void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) +static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) { ParticleThreadContext *ctx= thread->ctx; - Object *ob= ctx->ob; + Object *ob= ctx->sim.ob; DerivedMesh *dm= ctx->dm; ParticleData *tpa; - ParticleSettings *part= ctx->psys->part; + ParticleSettings *part= ctx->sim.psys->part; float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3], ornor1[3]; float cur_d, min_d, randu, randv; int from= ctx->from; @@ -624,7 +627,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C pa->num= ctx->index[p]; pa->fuv[0] = 1.0f; pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; - //pa->verts[0] = pa->verts[1] = pa->verts[2] = 0; #if ONLY_WORKING_WITH_PA_VERTS if(ctx->tree){ @@ -652,7 +654,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel); psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); ctx->jitoff[i]++; - //ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); break; case PART_DISTR_RAND: randu= rng_getFloat(thread->rng); @@ -662,12 +663,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C } pa->foffset= 0.0f; - /* - pa->verts[0] = mface->v1; - pa->verts[1] = mface->v2; - pa->verts[2] = mface->v3; - */ - /* experimental */ if(from==PART_FROM_VOLUME){ MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); @@ -723,10 +718,6 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C } } else if(from == PART_FROM_PARTICLE) { - //pa->verts[0]=0; /* not applicable */ - //pa->verts[1]=0; - //pa->verts[2]=0; - tpa=ctx->tpars+ctx->index[p]; pa->num=ctx->index[p]; pa->fuv[0]=tpa->fuv[0]; @@ -742,42 +733,30 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C cpa->num=0; cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f; cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - cpa->rand[0]=cpa->rand[1]=cpa->rand[2]=0.0f; return; } mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE); - //switch(distr){ - // case PART_DISTR_JIT: - // i=index[p]; - // psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mf->v4, cpa->fuv); - // ctx->jitoff[i]=(float)fmod(ctx->jitoff[i]+ctx->maxweight/ctx->weight[i],(float)ctx->jitlevel); - // break; - // case PART_DISTR_RAND: - randu= rng_getFloat(thread->rng); - randv= rng_getFloat(thread->rng); - psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); - // break; - //} + randu= rng_getFloat(thread->rng); + randv= rng_getFloat(thread->rng); + psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); - cpa->rand[0] = rng_getFloat(thread->rng); - cpa->rand[1] = rng_getFloat(thread->rng); - cpa->rand[2] = rng_getFloat(thread->rng); cpa->num = ctx->index[p]; if(ctx->tree){ KDTreeNearest ptn[10]; - int w,maxw, do_seams; + int w,maxw;//, do_seams; float maxd,mind,dd,totw=0.0; int parent[10]; float pweight[10]; - do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams); + /*do_seams= (part->flag&PART_CHILD_SEAMS && ctx->seams);*/ psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,0,0,orco1,ornor1); transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); - maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); + //maxw = BLI_kdtree_find_n_nearest(ctx->tree,(do_seams)?10:4,orco1,ornor1,ptn); + maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,ornor1,ptn); maxd=ptn[maxw-1].dist; mind=ptn[0].dist; @@ -787,70 +766,68 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C for(w=0; wseams; - float temp[3],temp2[3],tan[3]; - float inp,cur_len,min_len=10000.0f; - int min_seam=0, near_vert=0; - /* find closest seam */ - for(i=0; itotseam; i++, seam++){ - VecSubf(temp,co1,seam->v0); - inp=Inpf(temp,seam->dir)/seam->length2; - if(inp<0.0f){ - cur_len=VecLenf(co1,seam->v0); - } - else if(inp>1.0f){ - cur_len=VecLenf(co1,seam->v1); - } - else{ - VecCopyf(temp2,seam->dir); - VecMulf(temp2,inp); - cur_len=VecLenf(temp,temp2); - } - if(cur_len1.0f) near_vert=1; - else near_vert=0; - } - } - seam=ctx->seams+min_seam; - - VecCopyf(temp,seam->v0); - - if(near_vert){ - if(near_vert==-1) - VecSubf(tan,co1,seam->v0); - else{ - VecSubf(tan,co1,seam->v1); - VecCopyf(temp,seam->v1); - } + //if(do_seams){ + // ParticleSeam *seam=ctx->seams; + // float temp[3],temp2[3],tan[3]; + // float inp,cur_len,min_len=10000.0f; + // int min_seam=0, near_vert=0; + // /* find closest seam */ + // for(i=0; itotseam; i++, seam++){ + // VecSubf(temp,co1,seam->v0); + // inp=Inpf(temp,seam->dir)/seam->length2; + // if(inp<0.0f){ + // cur_len=VecLenf(co1,seam->v0); + // } + // else if(inp>1.0f){ + // cur_len=VecLenf(co1,seam->v1); + // } + // else{ + // VecCopyf(temp2,seam->dir); + // VecMulf(temp2,inp); + // cur_len=VecLenf(temp,temp2); + // } + // if(cur_len1.0f) near_vert=1; + // else near_vert=0; + // } + // } + // seam=ctx->seams+min_seam; + // + // VecCopyf(temp,seam->v0); + // + // if(near_vert){ + // if(near_vert==-1) + // VecSubf(tan,co1,seam->v0); + // else{ + // VecSubf(tan,co1,seam->v1); + // VecCopyf(temp,seam->v1); + // } - Normalize(tan); - } - else{ - VecCopyf(tan,seam->tan); - VecSubf(temp2,co1,temp); - if(Inpf(tan,temp2)<0.0f) - VecNegf(tan); - } - for(w=0; wtan); + // VecSubf(temp2,co1,temp); + // if(Inpf(tan,temp2)<0.0f) + // VecNegf(tan); + // } + // for(w=0; w=0){ @@ -876,7 +853,7 @@ void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, C static void *exec_distribution(void *data) { ParticleThread *thread= (ParticleThread*)data; - ParticleSystem *psys= thread->ctx->psys; + ParticleSystem *psys= thread->ctx->sim.psys; ParticleData *pa; ChildParticle *cpa; int p, totpart; @@ -943,11 +920,11 @@ static int compare_orig_index(const void *p1, const void *p2) /* 6. and we're done! */ /* This is to denote functionality that does not yet work with mesh - only derived mesh */ -int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) +static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) { ParticleThreadContext *ctx= threads[0].ctx; - Object *ob= ctx->ob; - ParticleSystem *psys= ctx->psys; + Object *ob= ctx->sim.ob; + ParticleSystem *psys= ctx->sim.psys; Object *tob; ParticleData *pa=0, *tpars= 0; ParticleSettings *part; @@ -999,49 +976,49 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive totpart=get_psys_tot_child(scene, psys); cfrom=from=PART_FROM_FACE; - if(part->flag&PART_CHILD_SEAMS){ - MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE); - MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); - int totedge=dm->getNumEdges(dm); + //if(part->flag&PART_CHILD_SEAMS){ + // MEdge *ed, *medge=dm->getEdgeDataArray(dm,CD_MEDGE); + // MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); + // int totedge=dm->getNumEdges(dm); - for(p=0, ed=medge; pflag&ME_SEAM) - totseam++; + // for(p=0, ed=medge; pflag&ME_SEAM) + // totseam++; - if(totseam){ - ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams"); - float temp[3],temp2[3]; + // if(totseam){ + // ParticleSeam *cur_seam=seams=MEM_callocN(totseam*sizeof(ParticleSeam),"Child Distribution Seams"); + // float temp[3],temp2[3]; - for(p=0, ed=medge; pflag&ME_SEAM){ - VecCopyf(cur_seam->v0,(mvert+ed->v1)->co); - VecCopyf(cur_seam->v1,(mvert+ed->v2)->co); + // for(p=0, ed=medge; pflag&ME_SEAM){ + // VecCopyf(cur_seam->v0,(mvert+ed->v1)->co); + // VecCopyf(cur_seam->v1,(mvert+ed->v2)->co); - VecSubf(cur_seam->dir,cur_seam->v1,cur_seam->v0); + // VecSubf(cur_seam->dir,cur_seam->v1,cur_seam->v0); - cur_seam->length2=VecLength(cur_seam->dir); - cur_seam->length2*=cur_seam->length2; + // cur_seam->length2=VecLength(cur_seam->dir); + // cur_seam->length2*=cur_seam->length2; - temp[0]=(float)((mvert+ed->v1)->no[0]); - temp[1]=(float)((mvert+ed->v1)->no[1]); - temp[2]=(float)((mvert+ed->v1)->no[2]); - temp2[0]=(float)((mvert+ed->v2)->no[0]); - temp2[1]=(float)((mvert+ed->v2)->no[1]); - temp2[2]=(float)((mvert+ed->v2)->no[2]); + // temp[0]=(float)((mvert+ed->v1)->no[0]); + // temp[1]=(float)((mvert+ed->v1)->no[1]); + // temp[2]=(float)((mvert+ed->v1)->no[2]); + // temp2[0]=(float)((mvert+ed->v2)->no[0]); + // temp2[1]=(float)((mvert+ed->v2)->no[1]); + // temp2[2]=(float)((mvert+ed->v2)->no[2]); - VecAddf(cur_seam->nor,temp,temp2); - Normalize(cur_seam->nor); + // VecAddf(cur_seam->nor,temp,temp2); + // Normalize(cur_seam->nor); - Crossf(cur_seam->tan,cur_seam->dir,cur_seam->nor); + // Crossf(cur_seam->tan,cur_seam->dir,cur_seam->nor); - Normalize(cur_seam->tan); + // Normalize(cur_seam->tan); - cur_seam++; - } - } - } - - } + // cur_seam++; + // } + // } + // } + // + //} } else{ /* no need to figure out distribution */ @@ -1063,10 +1040,6 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive length=VecLength(cpa->fuv); } - cpa->rand[0]=BLI_frand(); - cpa->rand[1]=BLI_frand(); - cpa->rand[2]=BLI_frand(); - cpa->num=-1; } } @@ -1345,7 +1318,6 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive jitlevel= totpart/tot; if(part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */ if(jitlevel<3) jitlevel= 3; - //if(jitlevel>100) jitlevel= 100; } jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit"); @@ -1364,7 +1336,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive ctx->tree= tree; ctx->seams= seams; ctx->totseam= totseam; - ctx->psys= psys; + ctx->sim.psys= psys; ctx->index= index; ctx->jit= jit; ctx->jitlevel= jitlevel; @@ -1385,7 +1357,7 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive if(!children || psys->totchild < 10000) totthread= 1; - seed= 31415926 + ctx->psys->seed; + seed= 31415926 + ctx->sim.psys->seed; for(i=0; ipsmd->dm; ListBase threads; ParticleThread *pthreads; ParticleThreadContext *ctx; int i, totthread; - pthreads= psys_threads_create(scene, ob, psys); + pthreads= psys_threads_create(sim); - if(!psys_threads_init_distribution(pthreads, scene, finaldm, from)) { + if(!psys_threads_init_distribution(pthreads, sim->scene, finaldm, from)) { psys_threads_free(pthreads); return; } @@ -1420,7 +1393,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Objec else exec_distribution(&pthreads[0]); - psys_calc_dmcache(ob, finaldm, psys); + psys_calc_dmcache(sim->ob, finaldm, sim->psys); ctx= pthreads[0].ctx; if(ctx->dm != finaldm) @@ -1430,8 +1403,9 @@ 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) +static void distribute_particles_on_shape(ParticleSimulationData *sim, int from) { + ParticleSystem *psys = sim->psys; PARTICLE_P; fprintf(stderr,"Shape emission not yet possible!\n"); @@ -1442,22 +1416,22 @@ static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int pa->num= -1; } } -static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, int from) +static void distribute_particles(ParticleSimulationData *sim, int from) { - ParticleSystemModifierData *psmd=0; + PARTICLE_PSMD; int distr_error=0; - psmd=psys_get_modifier(ob,psys); if(psmd){ if(psmd->dm) - distribute_particles_on_dm(psmd->dm, scene, ob, psys, from); + distribute_particles_on_dm(sim, from); else distr_error=1; } else - distribute_particles_on_shape(ob,psys,from); + distribute_particles_on_shape(sim, from); if(distr_error){ + ParticleSystem *psys = sim->psys; PARTICLE_P; fprintf(stderr,"Particle distribution error!\n"); @@ -1471,26 +1445,23 @@ static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, } /* threaded child particle distribution and path caching */ -ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys) +ParticleThread *psys_threads_create(ParticleSimulationData *sim) { ParticleThread *threads; ParticleThreadContext *ctx; int i, totthread; - if(scene->r.mode & R_FIXED_THREADS) - totthread= scene->r.threads; + if(sim->scene->r.mode & R_FIXED_THREADS) + totthread= sim->scene->r.threads; else totthread= BLI_system_thread_count(); threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread"); ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext"); - ctx->scene= scene; - ctx->ob= ob; - ctx->psys= psys; - ctx->psmd= psys_get_modifier(ob, psys); - ctx->dm= ctx->psmd->dm; - ctx->ma= give_current_material(ob, psys->part->omat); + ctx->sim = *sim; + ctx->dm= ctx->sim.psmd->dm; + ctx->ma= give_current_material(sim->ob, sim->psys->part->omat); memset(threads, 0, sizeof(ParticleThread)*totthread); @@ -1522,9 +1493,9 @@ void psys_threads_free(ParticleThread *threads) if(ctx->vg_roughe) MEM_freeN(ctx->vg_roughe); - if(ctx->psys->lattice){ - end_latt_deform(ctx->psys->lattice); - ctx->psys->lattice= NULL; + if(ctx->sim.psys->lattice){ + end_latt_deform(ctx->sim.psys->lattice); + ctx->sim.psys->lattice= NULL; } /* distribution */ @@ -1550,37 +1521,34 @@ void psys_threads_free(ParticleThread *threads) } /* set particle parameters that don't change during particle's life */ -void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) { - ParticleSettings *part; + ParticleSettings *part = sim->psys->part; ParticleTexture ptex; Material *ma=0; //IpoCurve *icu=0; // XXX old animation system int totpart; - float rand; - part=psys->part; - - totpart=psys->totpart; + totpart=sim->psys->totpart; ptex.life=ptex.size=ptex.exist=ptex.length=1.0; ptex.time=(float)p/(float)totpart; - BLI_srandom(psys->seed+p); + BLI_srandom(sim->psys->seed + p + 125); if(part->from!=PART_FROM_PARTICLE && part->type!=PART_FLUID){ - ma=give_current_material(ob,part->omat); + ma=give_current_material(sim->ob,part->omat); /* TODO: needs some work to make most blendtypes generally usefull */ - psys_get_texture(ob,ma,psmd,psys,pa,&ptex,MAP_PA_INIT); + psys_get_texture(sim,ma,pa,&ptex,MAP_PA_INIT); } pa->lifetime= part->lifetime*ptex.life; if(part->type==PART_HAIR) pa->time= 0.0f; - else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) - pa->time= 300000.0f; /* max frame */ + //else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0) + // pa->time= 300000.0f; /* max frame */ else{ //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME); //if(icu){ @@ -1604,10 +1572,8 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps } #endif // XXX old animation system - /* need to get every rand even if we don't use them so that randoms don't affect each other */ - rand= BLI_frand(); if(part->randlife!=0.0) - pa->lifetime*= 1.0f - part->randlife*rand; + pa->lifetime*= 1.0f - part->randlife * BLI_frand(); } pa->dietime= pa->time+pa->lifetime; @@ -1624,13 +1590,14 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps /* usage other than straight after distribute has to handle this index by itself - jahka*/ //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */ } -static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void initialize_all_particles(ParticleSimulationData *sim) { //IpoCurve *icu=0; // XXX old animation system + ParticleSystem *psys = sim->psys; PARTICLE_P; LOOP_PARTICLES - initialize_particle(pa,p,ob,psys,psmd); + initialize_particle(sim, pa, p); if(psys->part->type != PART_FLUID) { #if 0 // XXX old animation system @@ -1687,66 +1654,51 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS } } /* sets particle to the emitter surface with initial velocity & rotation */ -void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, ParticleSystemModifierData *psmd, Object *ob, - float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot) +void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra) { + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; ParticleSettings *part; ParticleTexture ptex; ParticleKey state; //IpoCurve *icu=0; // XXX old animation system - 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 fac, phasefac, nor[3]={0,0,0},loc[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], r_phase; + int p = pa - psys->particles; 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); - } + r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); + r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); + r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); - 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); + r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); + r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); + r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); + r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); + r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); + r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); + r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); NormalQuat(r_rot); - r_phase = BLI_frand(); + r_phase = PSYS_FRAND(p + 20); if(part->from==PART_FROM_PARTICLE){ - Object *tob; - ParticleSystem *tpsys=0; + ParticleSimulationData tsim = {sim->scene, psys->target_ob ? psys->target_ob : ob, NULL, NULL}; float speed; - tob=psys->target_ob; - if(tob==0) - tob=ob; - - tpsys=BLI_findlink(&tob->particlesystem, psys->target_psys-1); + tsim.psys = BLI_findlink(&tsim.ob->particlesystem, sim->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_particle_state(&tsim, pa->num, &state, 1); psys_get_from_key(&state, loc, nor, rot, 0); QuatMulVecf(rot, vtan); @@ -1763,23 +1715,20 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic } else{ /* get precise emitter matrix if particle is born */ - if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= psys->cfra) - where_is_object_time(scene, ob,pa->time); + if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) + where_is_object_time(sim->scene, sim->ob, pa->time); /* get birth location from object */ if(part->tanfac!=0.0) - psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); else - psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); - - /* save local coordinates for later */ - VECCOPY(tloc,loc); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); /* get possible textural influence */ - psys_get_texture(ob,give_current_material(ob,part->omat),psmd,psys,pa,&ptex,MAP_PA_IVEL); + psys_get_texture(sim, give_current_material(sim->ob,part->omat), pa, &ptex, MAP_PA_IVEL); - if(vg_vel && pa->num != -1) - ptex.ivel*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_vel); + //if(vg_vel && pa->num != -1) + // ptex.ivel*=psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_vel); /* particles live in global space so */ /* let's convert: */ @@ -1787,21 +1736,18 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic Mat4MulVecfl(ob->obmat,loc); /* -normal */ - VECADD(nor,tloc,nor); - Mat4MulVecfl(ob->obmat,nor); - VECSUB(nor,nor,loc); + Mat4Mul3Vecfl(ob->obmat,nor); Normalize(nor); /* -tangent */ if(part->tanfac!=0.0){ - float phase=vg_rot?2.0f*(psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; + float phase=0.0f; VecMulf(vtan,-(float)cos(M_PI*(part->tanphase+phase))); fac=-(float)sin(M_PI*(part->tanphase+phase)); VECADDFAC(vtan,vtan,utan,fac); - VECADD(vtan,tloc,vtan); - Mat4MulVecfl(ob->obmat,vtan); - VECSUB(vtan,vtan,loc); + Mat4Mul3Vecfl(ob->obmat,vtan); VECCOPY(utan,nor); VecMulf(utan,Inpf(vtan,nor)); @@ -1853,11 +1799,6 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic 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]; - /* calculate rotation matrix */ Projf(dvec, r_vel, pa->state.ave); VecSubf(mat[0], pa->state.ave, dvec); @@ -1896,8 +1837,9 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic VECADDFAC(vel,vel,nor,part->normfac); /* *emitter tangent */ - if(psmd && part->tanfac!=0.0) - VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_tan):1.0f)); + if(sim->psmd && part->tanfac!=0.0) + VECADDFAC(vel,vel,vtan,part->tanfac); + //VECADDFAC(vel,vel,vtan,part->tanfac*(vg_tan?psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_tan):1.0f)); /* *texture */ /* TODO */ @@ -1917,9 +1859,6 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic //} VecMulf(vel,ptex.ivel); - - //if(ELEM(part->phystype, PART_PHYS_GRADU_EX, PART_PHYS_GRADU_SIM)) - // VecAddf(vel,vel,part->acc); VECCOPY(pa->state.vel,vel); @@ -2001,22 +1940,20 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic pa->alive = PARS_UNBORN; pa->state.time = cfra; - -// pa->flag &= ~PARS_STICKY; } -static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from) +static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from) { ParticleData *pa; - int p, totpart=psys->totpart; - float *vg_vel=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); - float *vg_tan=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); - float *vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); + int p, totpart=sim->psys->totpart; + //float *vg_vel=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_VEL); + //float *vg_tan=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_TAN); + //float *vg_rot=psys_cache_vgroup(sim->psmd->dm,sim->psys,PSYS_VG_ROT); - for(p=from, pa=psys->particles+from; ppsys->particles+from; ppsys, *kpsys; ParticleTarget *pt = psys->targets.first; int keys_valid = 1; psys->totkeyed = 0; for(; pt; pt=pt->next) { - kpsys = psys_get_target_system(ob, pt); + kpsys = psys_get_target_system(sim->ob, pt); if(kpsys && kpsys->totpart) { psys->totkeyed += keys_valid; @@ -2064,9 +2001,10 @@ void psys_count_keyed_targets(Object *ob, ParticleSystem *psys) psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops; } -static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) +static void set_keyed_keys(ParticleSimulationData *sim) { - ParticleSystem *kpsys = psys; + ParticleSystem *psys = sim->psys; + ParticleSimulationData ksim = {sim->scene, NULL, NULL, NULL}; ParticleTarget *pt; PARTICLE_P; ParticleKey *key; @@ -2096,16 +2034,14 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) pt = psys->targets.first; for(k=0; kob) - kpsys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1); - else - kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1); + ksim.ob = pt->ob ? pt->ob : sim->ob; + ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1); LOOP_PARTICLES { key = pa->keys + k; key->time = -1.0; /* use current time */ - psys_get_particle_state(scene, pt->ob, kpsys, p%kpsys->totpart, key, 1); + psys_get_particle_state(&ksim, p%ksim.psys->totpart, key, 1); if(psys->flag & PSYS_KEYED_TIMING){ key->time = pa->time + pt->time; @@ -2131,111 +2067,109 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys) /************************************************/ /* Reactors */ /************************************************/ -static void push_reaction(Object* ob, ParticleSystem *psys, int pa_num, int event, ParticleKey *state) -{ - Object *rob; - ParticleSystem *rpsys; - ParticleSettings *rpart; - ParticleData *pa; - ListBase *lb=&psys->effectors; - ParticleEffectorCache *ec; - ParticleReactEvent *re; - - if(lb->first) for(ec = lb->first; ec; ec= ec->next){ - if(ec->type & PSYS_EC_REACTOR){ - /* all validity checks already done in add_to_effectors */ - rob=ec->ob; - rpsys=BLI_findlink(&rob->particlesystem,ec->psys_nbr); - rpart=rpsys->part; - if(rpsys->part->reactevent==event){ - pa=psys->particles+pa_num; - re= MEM_callocN(sizeof(ParticleReactEvent), "react event"); - re->event=event; - re->pa_num = pa_num; - re->ob = ob; - re->psys = psys; - re->size = pa->size; - copy_particle_key(&re->state,state,1); - - switch(event){ - case PART_EVENT_DEATH: - re->time=pa->dietime; - break; - case PART_EVENT_COLLIDE: - re->time=state->time; - break; - case PART_EVENT_NEAR: - re->time=state->time; - break; - } - - BLI_addtail(&rpsys->reactevents, re); - } - } - } -} -static void react_to_events(ParticleSystem *psys, int pa_num) -{ - ParticleSettings *part=psys->part; - ParticleData *pa=psys->particles+pa_num; - ParticleReactEvent *re=psys->reactevents.first; - int birth=0; - float dist=0.0f; - - for(re=psys->reactevents.first; re; re=re->next){ - birth=0; - if(part->from==PART_FROM_PARTICLE){ - if(pa->num==re->pa_num && pa->alive==PARS_UNBORN){ - if(re->event==PART_EVENT_NEAR){ - ParticleData *tpa = re->psys->particles+re->pa_num; - float pa_time=tpa->time + pa->foffset*tpa->lifetime; - if(re->time >= pa_time){ - pa->time=pa_time; - pa->dietime=pa->time+pa->lifetime; - } - } - else{ - pa->time=re->time; - pa->dietime=pa->time+pa->lifetime; - } - } - } - else{ - dist=VecLenf(pa->state.co, re->state.co); - if(dist <= re->size){ - if(pa->alive==PARS_UNBORN){ - pa->time=re->time; - pa->dietime=pa->time+pa->lifetime; - birth=1; - } - if(birth || part->flag&PART_REACT_MULTIPLE){ - float vec[3]; - VECSUB(vec,pa->state.co, re->state.co); - if(birth==0) - VecMulf(vec,(float)pow(1.0f-dist/re->size,part->reactshape)); - VECADDFAC(pa->state.vel,pa->state.vel,vec,part->reactfac); - VECADDFAC(pa->state.vel,pa->state.vel,re->state.vel,part->partfac); - } - if(birth) - VecMulf(pa->state.vel,(float)pow(1.0f-dist/re->size,part->reactshape)); - } - } - } -} -void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_ob, ParticleSystem **target_psys) -{ - Object *tob; - - tob=psys->target_ob; - if(tob==0) - tob=ob; - - *target_psys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); - if(*target_psys) - *target_ob=tob; - else - *target_ob=0; -} +//static void push_reaction(ParticleSimulationData *sim, int pa_num, int event, ParticleKey *state) +//{ +// Object *rob; +// ParticleSystem *rpsys; +// ParticleSettings *rpart; +// ParticleData *pa; +// ListBase *lb=&sim->psys->effectors; +// ParticleEffectorCache *ec; +// ParticleReactEvent *re; +// +// if(lb->first) for(ec = lb->first; ec; ec= ec->next){ +// if(ec->type & PSYS_EC_REACTOR){ +// /* all validity checks already done in add_to_effectors */ +// rob=ec->ob; +// rpsys=BLI_findlink(&rob->particlesystem,ec->psys_nbr); +// rpart=rpsys->part; +// if(rpsys->part->reactevent==event){ +// pa=sim->psys->particles+pa_num; +// re= MEM_callocN(sizeof(ParticleReactEvent), "react event"); +// re->event=event; +// re->pa_num = pa_num; +// re->ob = sim->ob; +// re->psys = sim->psys; +// re->size = pa->size; +// copy_particle_key(&re->state,state,1); +// +// switch(event){ +// case PART_EVENT_DEATH: +// re->time=pa->dietime; +// break; +// case PART_EVENT_COLLIDE: +// re->time=state->time; +// break; +// case PART_EVENT_NEAR: +// re->time=state->time; +// break; +// } +// +// BLI_addtail(&rpsys->reactevents, re); +// } +// } +// } +//} +//static void react_to_events(ParticleSystem *psys, int pa_num) +//{ +// ParticleSettings *part=psys->part; +// ParticleData *pa=psys->particles+pa_num; +// ParticleReactEvent *re=psys->reactevents.first; +// int birth=0; +// float dist=0.0f; +// +// for(re=psys->reactevents.first; re; re=re->next){ +// birth=0; +// if(part->from==PART_FROM_PARTICLE){ +// if(pa->num==re->pa_num && pa->alive==PARS_UNBORN){ +// if(re->event==PART_EVENT_NEAR){ +// ParticleData *tpa = re->psys->particles+re->pa_num; +// float pa_time=tpa->time + pa->foffset*tpa->lifetime; +// if(re->time >= pa_time){ +// pa->time=pa_time; +// pa->dietime=pa->time+pa->lifetime; +// } +// } +// else{ +// pa->time=re->time; +// pa->dietime=pa->time+pa->lifetime; +// } +// } +// } +// else{ +// dist=VecLenf(pa->state.co, re->state.co); +// if(dist <= re->size){ +// if(pa->alive==PARS_UNBORN){ +// pa->time=re->time; +// pa->dietime=pa->time+pa->lifetime; +// birth=1; +// } +// if(birth || part->flag&PART_REACT_MULTIPLE){ +// float vec[3]; +// VECSUB(vec,pa->state.co, re->state.co); +// if(birth==0) +// VecMulf(vec,(float)pow(1.0f-dist/re->size,part->reactshape)); +// VECADDFAC(pa->state.vel,pa->state.vel,vec,part->reactfac); +// VECADDFAC(pa->state.vel,pa->state.vel,re->state.vel,part->partfac); +// } +// if(birth) +// VecMulf(pa->state.vel,(float)pow(1.0f-dist/re->size,part->reactshape)); +// } +// } +// } +//} +//void psys_get_reactor_target(ParticleSimulationData *sim, Object **target_ob, ParticleSystem **target_psys) +//{ +// Object *tob; +// +// tob = sim->psys->target_ob ? sim->psys->target_ob : sim->ob; +// +// *target_psys = BLI_findlink(&tob->particlesystem, sim->psys->target_psys-1); +// if(*target_psys) +// *target_ob=tob; +// else +// *target_ob=0; +//} /************************************************/ /* Point Cache */ /************************************************/ @@ -2280,11 +2214,9 @@ static void update_particle_tree(ParticleSystem *psys) psys->tree = BLI_kdtree_new(psys->totpart); - LOOP_PARTICLES { - if(pa->flag & (PARS_NO_DISP+PARS_UNEXIST) || pa->alive != PARS_ALIVE) - continue; - - BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); + LOOP_SHOWN_PARTICLES { + if(pa->alive == PARS_ALIVE) + BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); } BLI_kdtree_balance(psys->tree); @@ -2301,7 +2233,7 @@ static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, result[0].nor = result[1].nor = result[2].nor = result[3].nor = 0; - strength= force_val*falloff;///(float)pow((double)distance,(double)power); + strength= force_val*falloff; VECCOPY(tex_co,pa_co); @@ -2364,19 +2296,19 @@ static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla, VecAddf(field,field,mag_vec); } -static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys) +static void add_to_effectors(ParticleSimulationData *sim, ListBase *lb, Object *ob) { ParticleEffectorCache *ec; PartDeflect *pd= ob->pd; short type=0,i; - if(pd && ob != obsrc){ + if(pd && ob != sim->ob){ if(pd->forcefield == PFIELD_GUIDE) { if(ob->type==OB_CURVE) { Curve *cu= ob->data; if(cu->flag & CU_PATH) { if(cu->path==NULL || cu->path->data==NULL) - makeDispListCurveTypes(scene, ob, 0); + makeDispListCurveTypes(sim->scene, ob, 0); if(cu->path && cu->path->data) { type |= PSYS_EC_EFFECTOR; } @@ -2410,13 +2342,13 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs if(ob->particlesystem.first){ ParticleSystem *epsys=ob->particlesystem.first; ParticleSettings *epart=0; - Object *tob; + //Object *tob; for(i=0; epsys; epsys=epsys->next,i++){ if(!psys_check_enabled(ob, epsys)) continue; type=0; - if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){ + if(epsys!=sim->psys || (sim->psys->part->flag & PART_SELF_EFFECT)){ epart=epsys->part; if((epsys->part->pd && epsys->part->pd->forcefield) @@ -2425,13 +2357,13 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs type=PSYS_EC_PARTICLE; } - if(epart->type==PART_REACTOR) { - tob=epsys->target_ob; - if(tob==0) - tob=ob; - if(BLI_findlink(&tob->particlesystem,epsys->target_psys-1)==psys) - type|=PSYS_EC_REACTOR; - } + //if(epart->type==PART_REACTOR) { + // tob=epsys->target_ob; + // if(tob==0) + // tob=ob; + // if(BLI_findlink(&tob->particlesystem,epsys->target_psys-1)==sim->psys) + // type|=PSYS_EC_REACTOR; + //} if(type){ ec= MEM_callocN(sizeof(ParticleEffectorCache), "effector cache"); @@ -2449,29 +2381,29 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs } } -static void psys_init_effectors_recurs(Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys, ListBase *listb, int level) +static void psys_init_effectors_recurs(ParticleSimulationData *sim, Object *ob, ListBase *listb, int level) { Group *group; GroupObject *go; - unsigned int layer= obsrc->lay; + unsigned int layer= sim->ob->lay; if(level>MAX_DUPLI_RECUR) return; if(ob->lay & layer) { if(ob->pd || ob->particlesystem.first) - add_to_effectors(listb, scene, ob, obsrc, psys); + add_to_effectors(sim, listb, ob); if(ob->dup_group) { group= ob->dup_group; for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, level+1); + psys_init_effectors_recurs(sim, go->ob, listb, level+1); } } } -void psys_init_effectors(Scene *scene, Object *obsrc, Group *group, ParticleSystem *psys) +static void psys_init_effectors(ParticleSimulationData *sim, Group *group) { - ListBase *listb= &psys->effectors; + ListBase *listb= &sim->psys->effectors; Base *base; listb->first=listb->last=0; @@ -2480,11 +2412,11 @@ void psys_init_effectors(Scene *scene, Object *obsrc, Group *group, ParticleSyst GroupObject *go; for(go= group->gobject.first; go; go= go->next) - psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, 0); + psys_init_effectors_recurs(sim, go->ob, listb, 0); } else { - for(base = scene->base.first; base; base= base->next) - psys_init_effectors_recurs(scene, base->object, obsrc, psys, listb, 0); + for(base = sim->scene->base.first; base; base= base->next) + psys_init_effectors_recurs(sim, base->object, listb, 0); } } @@ -2518,13 +2450,16 @@ void psys_end_effectors(ParticleSystem *psys) BLI_freelistN(&psys->effectors); } -static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +/* precalcs effectors and returns 1 if there were any collision object +/* so collision checks can be avoided as quickly as possible */ +static int precalc_effectors(ParticleSimulationData *sim, float cfra) { + ParticleSystem *psys = sim->psys; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; ParticleSettings *part=psys->part; PARTICLE_P; - int totpart; + int totpart, collision = 0; float vec2[3],loc[3],radius,*co=0; for(ec= lb->first; ec; ec= ec->next) { @@ -2556,9 +2491,9 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa VECCOPY(loc, pa->fuv); } else - psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); + psys_particle_on_emitter(sim->psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); - Mat4MulVecfl(ob->obmat,loc); + Mat4MulVecfl(sim->ob->obmat,loc); ec->distances[p]=VecLenf(loc,vec); VECSUB(loc,loc,vec); VECCOPY(ec->locations+3*p,loc); @@ -2566,11 +2501,10 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa } } else if(ec->type==PSYS_EC_PARTICLE){ - Object *eob = ec->ob; - ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); - ParticleSettings *epart = epsys->part; + ParticleSimulationData esim = {sim->scene, ec->ob, BLI_findlink(&ec->ob->particlesystem, ec->psys_nbr), NULL}; + ParticleSettings *epart = esim.psys->part; ParticleData *epa; - int p, totepart = epsys->totpart; + int p, totepart = esim.psys->totpart; if(psys->part->phystype==PART_PHYS_BOIDS){ ParticleKey state; @@ -2583,8 +2517,8 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa tree=BLI_kdtree_new(totepart); ec->tree=tree; - for(p=0, epa=epsys->particles; palive==PARS_ALIVE && psys_get_particle_state(scene, eob,epsys,p,&state,0)) + for(p=0, epa=esim.psys->particles; palive==PARS_ALIVE && psys_get_particle_state(&esim,p,&state,0)) BLI_kdtree_insert(tree, p, state.co, NULL); BLI_kdtree_balance(tree); @@ -2594,12 +2528,23 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa } else if(ec->type==PSYS_EC_DEFLECT) { CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); - if(collmd) + if(collmd) { collision_move_object(collmd, 1.0, 0.0); + collision = 1; + } } } + + return collision; } +/* updates particle effectors and returns if any collision objects were found */ +int psys_update_effectors(ParticleSimulationData *sim, float cfra, int precalc) +{ + psys_end_effectors(sim->psys); + psys_init_effectors(sim, sim->psys->part->eff_group); + return (precalc ? precalc_effectors(sim, cfra) : 0); +} int effector_find_co(Scene *scene, float *pco, SurfaceModifierData *sur, Object *ob, PartDeflect *pd, float *co, float *nor, float *vel, int *index) { SurfaceModifierData *surmd = NULL; @@ -2679,10 +2624,10 @@ int effector_find_co(Scene *scene, float *pco, SurfaceModifierData *sur, Object return ret; } /* calculate forces that all effectors apply to a particle*/ -void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, Object *ob, ParticleSystem *psys, float *rootco, float *force_field, float *vel,float framestep, float cfra) +void do_effectors(ParticleSimulationData *sim, int pa_no, ParticleData *pa, ParticleKey *state, float *rootco, float *force_field, float *vel,float framestep, float cfra) { Object *eob; - ParticleSystem *epsys; + ParticleSystem *psys = sim->psys; ParticleSettings *epart; ParticleData *epa; ParticleKey estate; @@ -2712,19 +2657,19 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, if(ec->type & PSYS_EC_EFFECTOR){ pd=eob->pd; if(psys->part->type!=PART_HAIR && psys->part->integrator) - where_is_object_time(scene, eob,cfra); + where_is_object_time(sim->scene, eob, cfra); if(pd && pd->flag&PFIELD_SURFACE) { float velocity[3]; /* using velocity corrected location allows for easier sliding over effector surface */ VecCopyf(velocity, state->vel); - VecMulf(velocity, psys_get_timestep(psys->part)); + VecMulf(velocity, psys_get_timestep(sim)); VecAddf(pco, state->co, velocity); } else VECCOPY(pco, state->co); - effector_find_co(scene, pco, NULL, eob, pd, co, NULL, NULL, &face_index); + effector_find_co(sim->scene, pco, NULL, eob, pd, co, NULL, NULL, &face_index); VecSubf(vec_to_part, state->co, co); @@ -2741,68 +2686,69 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat, strength, falloff, force_field); } else { - do_physical_effector(scene, eob, state->co, pd->forcefield,strength,distance, + do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance, falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part, state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); } } if(ec->type & PSYS_EC_PARTICLE){ + ParticleSimulationData esim = {sim->scene, eob, BLI_findlink(&eob->particlesystem,ec->psys_nbr), NULL}; int totepart, i; - epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr); - epart= epsys->part; - pd=epart->pd; - totepart= epsys->totpart; + + epart = esim.psys->part; + pd = epart->pd; + totepart = esim.psys->totpart; if(totepart <= 0) continue; if(pd && pd->forcefield==PFIELD_HARMONIC){ /* every particle is mapped to only one harmonic effector particle */ - p= pa_no%epsys->totpart; + p= pa_no%esim.psys->totpart; totepart= p+1; } else{ p=0; } - epsys->lattice= psys_get_lattice(scene, ob, psys); + esim.psys->lattice= psys_get_lattice(sim); for(; pparticles + p; - estate.time=cfra; - if(psys_get_particle_state(scene, eob,epsys,p,&estate,0)){ + epa = esim.psys->particles + p; + estate.time = cfra; + if(psys_get_particle_state(&esim, p, &estate, 0)){ VECSUB(vec_to_part, state->co, estate.co); distance = VecLength(vec_to_part); for(i=0, pd = epart->pd; i<2; i++,pd = epart->pd2) { if(pd==NULL || pd->forcefield==0) continue; - falloff=effector_falloff(pd,estate.vel,vec_to_part); + falloff = effector_falloff(pd, estate.vel, vec_to_part); strength = pd->f_strength * psys->part->effector_weight[0] * psys->part->effector_weight[pd->forcefield]; if(falloff<=0.0f) ; /* don't do anything */ else - do_physical_effector(scene, eob, state->co, pd->forcefield,strength,distance, + do_physical_effector(sim->scene, eob, state->co, pd->forcefield,strength,distance, falloff,epart->size,pd->f_damp,estate.vel,vec_to_part, state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size); } } else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ - psys_get_particle_state(scene, eob,epsys,p,&estate,1); - VECADD(vel,vel,estate.vel); + psys_get_particle_state(&esim, p, &estate, 1); + VECADD(vel, vel, estate.vel); /* TODO: add rotation handling here too */ } } - if(epsys->lattice){ - end_latt_deform(epsys->lattice); - epsys->lattice= NULL; + if(esim.psys->lattice){ + end_latt_deform(esim.psys->lattice); + esim.psys->lattice= NULL; } } } @@ -2813,11 +2759,14 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, /* Newtonian physics */ /************************************************/ /* gathers all forces that effect particles and calculates a new state for the particle */ -static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra) +static void apply_particle_forces(ParticleSimulationData *sim, int p, float dfra, float cfra) { + ParticleSettings *part = sim->psys->part; + ParticleData *pa = sim->psys->particles + p; ParticleKey states[5], tkey; + float timestep = psys_get_timestep(sim); float force[3],tvel[3],dx[4][3],dv[4][3]; - float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=psys->cfra; + float dtime=dfra*timestep, time, pa_mass=part->mass, fac, fra=sim->psys->cfra; int i, steps=1; /* maintain angular velocity */ @@ -2845,7 +2794,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj tvel[0]=tvel[1]=tvel[2]=0.0; /* add effectors */ if(part->type != PART_HAIR) - do_effectors(pa_no,pa,states+i,scene, ob, psys,states->co,force,tvel,dfra,fra); + do_effectors(sim, p, pa, states+i, states->co, force, tvel, dfra, fra); /* calculate air-particle interaction */ if(part->dragfac!=0.0f){ @@ -2878,7 +2827,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj if(i==0){ VECADDFAC(states[1].co,states->co,states->vel,dtime*0.5f); VECADDFAC(states[1].vel,states->vel,force,dtime*0.5f); - fra=psys->cfra+0.5f*dfra; + fra=sim->psys->cfra+0.5f*dfra; } else{ VECADDFAC(pa->state.co,states->co,states[1].vel,dtime); @@ -2895,7 +2844,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj VECADDFAC(states[1].co,states->co,dx[0],0.5f); VECADDFAC(states[1].vel,states->vel,dv[0],0.5f); - fra=psys->cfra+0.5f*dfra; + fra=sim->psys->cfra+0.5f*dfra; break; case 1: VECADDFAC(dx[1],states->vel,dv[0],0.5f); @@ -2949,7 +2898,7 @@ static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Obj tkey.time=pa->state.time; if(part->type != PART_HAIR) { - if(do_guide(scene, &tkey, pa_no, time, &psys->effectors)) { + if(do_guide(sim->scene, &tkey, p, time, &sim->psys->effectors)) { VECCOPY(pa->state.co,tkey.co); /* guides don't produce valid velocity */ VECSUB(pa->state.vel,tkey.co,pa->prev_state.co); @@ -3213,15 +3162,18 @@ void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, B /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){ +static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, float cfra){ Object *ob = NULL, *skip_ob = NULL; - ListBase *lb=&psys->effectors; + ParticleSettings *part = sim->psys->part; + ListBase *lb=&sim->psys->effectors; ParticleEffectorCache *ec; ParticleKey reaction_state; ParticleCollision col; + ParticleData *pa = sim->psys->particles + p; 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 timestep = psys_get_timestep(sim); int deflections=0, max_deflections=10; VECCOPY(col.co1, pa->prev_state.co); @@ -3258,11 +3210,11 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa continue; /* particles should not collide with emitter at birth */ - if(ob==pob && pa->time < cfra && pa->time >= psys->cfra) + if(ob==sim->ob && pa->time < cfra && pa->time >= sim->psys->cfra) continue; if(part->type!=PART_HAIR) - where_is_object_time(scene,ob,cfra); + where_is_object_time(sim->scene, sim->ob, cfra); col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); col.ob_t = ob; @@ -3399,9 +3351,9 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa } /* store state for reactors */ - VECCOPY(reaction_state.co, co); - VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); - QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); + //VECCOPY(reaction_state.co, co); + //VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); + //QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); /* set coordinates for next iteration */ VECCOPY(col.co1, co); @@ -3423,8 +3375,8 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa } deflections++; - reaction_state.time = cfra - (1.0f - dt) * dfra; - push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); + //reaction_state.time = cfra - (1.0f - dt) * dfra; + //push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); } else return; @@ -3434,29 +3386,30 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa /* Hair */ /************************************************/ /* check if path cache or children need updating and do it if needed */ -static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void psys_update_path_cache(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part=psys->part; - ParticleEditSettings *pset=&scene->toolsettings->particle; - int distr=0,alloc=0,skip=0; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + ParticleEditSettings *pset = &sim->scene->toolsettings->particle; + int distr=0, alloc=0, skip=0; - if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET) + if((psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; - if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (ob && ob->mode & OB_MODE_WEIGHT_PAINT))) + if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT))) distr=1; if(distr){ if(alloc) - realloc_particles(ob,psys,psys->totpart); + realloc_particles(sim, sim->psys->totpart); - if(get_psys_tot_child(scene, psys)) { + if(get_psys_tot_child(sim->scene, psys)) { /* don't generate children while computing the hair keys */ if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + distribute_particles(sim, PART_FROM_CHILD); if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0) - psys_find_parents(ob,psmd,psys); + psys_find_parents(sim); } } } @@ -3470,7 +3423,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif skip = 1; /* draw visualization */ else if(psys->pointcache->flag & PTCACHE_BAKING) skip = 1; /* no need to cache paths while baking dynamics */ - else if(psys_in_edit_mode(scene, psys)) { + else if(psys_in_edit_mode(sim->scene, psys)) { if((pset->flag & PE_DRAW_PART)==0) skip = 1; else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) @@ -3479,7 +3432,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif } if(!skip) { - psys_cache_paths(scene, ob, psys, cfra); + psys_cache_paths(sim, cfra); /* for render, child particle paths are computed on the fly */ if(part->childtype) { @@ -3489,15 +3442,16 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif skip = 1; if(!skip) - psys_cache_child_paths(scene, ob, psys, cfra, 0); + psys_cache_child_paths(sim, cfra, 0); } } else if(psys->pathcache) psys_free_path_cache(psys, NULL); } -static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void do_hair_dynamics(ParticleSimulationData *sim) { + ParticleSystem *psys = sim->psys; DerivedMesh *dm = psys->hair_in_dm; MVert *mvert = NULL; MEdge *medge = NULL; @@ -3520,7 +3474,8 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par LOOP_PARTICLES totpoint += pa->totkey; - totedge = totpoint - psys->totpart; + totedge = totpoint; + totpoint += psys->totpart; if(dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) { dm->release(dm); @@ -3539,14 +3494,39 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par psys->clmd->sim_parms->vgroup_mass = 1; /* make vgroup for pin roots etc.. */ - psys->particles->hair_index = 0; + psys->particles->hair_index = 1; LOOP_PARTICLES { if(p) - pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey; + pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey + 1; - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); for(k=0, key=pa->hair; ktotkey; k++,key++) { + + /* create fake root before actual root to resist bending */ + if(k==0) { + float temp[3]; + VECSUB(temp, key->co, (key+1)->co); + VECCOPY(mvert->co, key->co); + VECADD(mvert->co, mvert->co, temp); + Mat4MulVecfl(hairmat, mvert->co); + mvert++; + + medge->v1 = pa->hair_index - 1; + medge->v2 = pa->hair_index; + medge++; + + if(dvert) { + if(!dvert->totweight) { + dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); + dvert->totweight = 1; + } + + dvert->dw->weight = 1.0f; + dvert++; + } + } + VECCOPY(mvert->co, key->co); Mat4MulVecfl(hairmat, mvert->co); mvert++; @@ -3576,10 +3556,11 @@ static void do_hair_dynamics(Scene *scene, Object *ob, ParticleSystem *psys, Par psys->clmd->point_cache = psys->pointcache; - psys->hair_out_dm = clothModifier_do(psys->clmd, scene, ob, dm, 0, 0); + psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, 0, 0); } -static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void hair_step(ParticleSimulationData *sim, float cfra) { + ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; PARTICLE_P; float disp = (float)get_current_display_percentage(psys)/100.0f; @@ -3587,7 +3568,7 @@ static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd BLI_srandom(psys->seed); LOOP_PARTICLES { - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -3595,36 +3576,33 @@ static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd if(psys->recalc & PSYS_RECALC_RESET) { /* need this for changing subsurf levels */ - psys_calc_dmcache(ob, psmd->dm, psys); + psys_calc_dmcache(sim->ob, sim->psmd->dm, psys); if(psys->clmd) - cloth_free_modifier(ob, psys->clmd); + cloth_free_modifier(sim->ob, psys->clmd); } - if(psys->effectors.first) - psys_end_effectors(psys); - /* dynamics with cloth simulation */ if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) - do_hair_dynamics(scene, ob, psys, psmd); + do_hair_dynamics(sim); - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); + psys_update_effectors(sim, cfra, 1); - psys_update_path_cache(scene, ob,psmd,psys,cfra); + psys_update_path_cache(sim, cfra); psys->flag |= PSYS_HAIR_UPDATED; } -static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){ +static void save_hair(ParticleSimulationData *sim, float cfra){ + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; HairKey *key, *root; PARTICLE_P; int totpart; - Mat4Invert(ob->imat,ob->obmat); + Mat4Invert(ob->imat, ob->obmat); - psys->lattice= psys_get_lattice(scene, ob, psys); + psys->lattice= psys_get_lattice(sim); if(psys->totpart==0) return; @@ -3647,7 +3625,7 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy if(pa->totkey) { VECSUB(key->co, key->co, root->co); - psys_vec_rot_to_face(psmd->dm, pa, key->co); + psys_vec_rot_to_face(sim->psmd->dm, pa, key->co); } key->time = pa->state.time; @@ -3665,17 +3643,17 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy /* System Core */ /************************************************/ /* unbaked particles are calculated dynamically */ -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) +static void dynamics_step(ParticleSimulationData *sim, float cfra) { + ParticleSystem *psys = sim->psys; 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); + Material *ma=give_current_material(sim->ob, part->omat); BoidBrainData bbd; PARTICLE_P; float timestep; - int totpart; + int totpart, check_collisions = 0; /* current time */ float ctime, ipotime; // XXX old animation system /* frame & time changes */ @@ -3687,7 +3665,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic totpart=psys->totpart; - timestep=psys_get_timestep(part); + timestep=psys_get_timestep(sim); dtime= dfra*timestep; ctime= cfra*timestep; ipotime= cfra; // XXX old animation system @@ -3701,12 +3679,10 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic if(dfra<0.0){ float *vg_size=0; - if(part->type==PART_REACTOR) - vg_size=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); - - LOOP_PARTICLES { - if(pa->flag & PARS_UNEXIST) continue; + //if(part->type==PART_REACTOR) + // vg_size=psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); + LOOP_EXISTING_PARTICLES { /* set correct ipo timing */ #if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ @@ -3715,13 +3691,15 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(sim, pa, dtime, cfra); - if(cfra>pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ - pa->loop=(short)((cfra-pa->time)/pa->lifetime); - pa->alive=PARS_UNBORN; + if(cfra > pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){ + pa->loop = (short)((cfra-pa->time)/pa->lifetime); + pa->alive = PARS_UNBORN; } else{ pa->loop = 0; @@ -3742,21 +3720,12 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } else{ BLI_srandom(31415926 + (int)cfra + psys->seed); - - /* update effectors */ - if(psys->effectors.first) - psys_end_effectors(psys); - psys_init_effectors(scene, ob, part->eff_group, psys); - - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); + psys_update_effectors(sim, cfra, 1); if(part->phystype==PART_PHYS_BOIDS){ ParticleTarget *pt = psys->targets.first; - bbd.scene = scene; - bbd.ob = ob; - bbd.psys = psys; + bbd.sim = sim; bbd.part = part; bbd.cfra = cfra; bbd.dfra = dfra; @@ -3773,9 +3742,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } /* main loop: calculate physics for all particles */ - LOOP_PARTICLES { - if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; - + LOOP_SHOWN_PARTICLES { copy_particle_key(&pa->prev_state,&pa->state,1); /* set correct ipo timing */ @@ -3786,23 +3753,19 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + //update_particle_settings(psys, part, &tpart, pa); - /* reactions can change birth time so they need to be checked first */ - if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) - react_to_events(psys,p); + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); + + ///* reactions can change birth time so they need to be checked first */ + //if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) + // react_to_events(psys,p); birthtime = pa->time + pa->loop * pa->lifetime; dietime = birthtime + pa->lifetime; - /* allways reset particles to emitter before birth */ - if(pa->alive==PARS_UNBORN - || pa->alive==PARS_KILLED - || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) - || birthtime >= psys->cfra){ - reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); - } - pa_dfra = dfra; pa_dtime = dtime; @@ -3815,6 +3778,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } else if(birthtime <= cfra && birthtime >= psys->cfra){ /* particle is born some time between this and last step*/ + reset_particle(sim, pa, dtime, cfra); pa->alive = PARS_ALIVE; pa_dfra = cfra - birthtime; pa_dtime = pa_dfra*timestep; @@ -3823,18 +3787,22 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic /* nothing to be done when particle is dead */ } + /* only reset unborn particles if they're shown */ + if(pa->alive==PARS_UNBORN && part->flag & PART_UNBORN) + reset_particle(sim, pa, dtime, cfra); if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ switch(part->phystype){ case PART_PHYS_NEWTON: /* do global forces & effectors */ - apply_particle_forces(scene, p, pa, ob, psys, part, timestep,pa_dfra,cfra); + apply_particle_forces(sim, p, pa_dfra, cfra); /* deflection */ - deflect_particle(scene, ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); + if(check_collisions) + deflect_particle(sim, p, pa_dfra, cfra); /* rotations */ - rotate_particle(part,pa,pa_dfra,timestep); + rotate_particle(part, pa, pa_dfra, timestep); break; case PART_PHYS_BOIDS: { @@ -3844,18 +3812,18 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic boid_body(&bbd, pa); /* deflection */ - deflect_particle(scene,ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); + deflect_particle(sim, p, pa_dfra, cfra); } break; } } if(pa->alive == PARS_DYING){ - push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); + //push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); if(part->flag & PART_LOOP && part->type!=PART_HAIR){ pa->loop++; - reset_particle(scene, pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); + reset_particle(sim, pa, 0.0, cfra); pa->alive=PARS_ALIVE; } else{ @@ -3866,7 +3834,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic else pa->state.time=cfra; - push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); + //push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); } } } @@ -3878,28 +3846,21 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic } /* updates cached particles' alive & other flags etc..*/ -static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) +static void cached_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part=psys->part; - 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); + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + IpoCurve *icu_esize = NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system + Material *ma = give_current_material(sim->ob,part->omat); PARTICLE_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); + vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); - if(psys->effectors.first) - psys_end_effectors(psys); - - //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ - psys_init_effectors(scene, ob, part->eff_group, psys); - if(psys->effectors.first) - precalc_effectors(scene, ob,psys,psmd,cfra); - //} + psys_update_effectors(sim, cfra, 1); disp= (float)get_current_display_percentage(psys)/100.0f; @@ -3911,9 +3872,13 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps execute_ipo((ID *)part, part->ipo); } #endif // XXX old animation system - pa->size= psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + //update_settings_with_particle(psys, part, pa); - psys->lattice= psys_get_lattice(scene, ob, psys); + pa->size = part->size; + if(part->randsize > 0.0) + pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); + + psys->lattice= psys_get_lattice(sim); if(part->flag & PART_LOOP && part->type!=PART_HAIR) pa->loop = (short)((cfra - pa->time) / pa->lifetime); @@ -3924,25 +3889,16 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time); /* update alive status and push events */ - if(pa->time >= cfra) { - pa->alive = pa->time==cfra ? PARS_ALIVE : PARS_UNBORN; - if((psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) - reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL); + if(pa->time > cfra) { + pa->alive = PARS_UNBORN; + if(part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) + reset_particle(sim, pa, 0.0f, cfra); } else if(dietime <= cfra){ - if(dietime > psys->cfra){ - state.time = dietime; - psys_get_particle_state(scene, ob,psys,p,&state,1); - push_reaction(ob,psys,p,PART_EVENT_DEATH,&state); - } pa->alive = PARS_DEAD; } else{ pa->alive = PARS_ALIVE; - state.time = cfra; - psys_get_particle_state(scene, ob,psys,p,&state,1); - state.time = cfra; - push_reaction(ob,psys,p,PART_EVENT_NEAR,&state); } if(psys->lattice){ @@ -3950,43 +3906,41 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps psys->lattice= NULL; } - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; } /* make sure that children are up to date */ - if(psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) { - realloc_particles(ob, psys, psys->totpart); - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + if(psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) { + realloc_particles(sim, psys->totpart); + distribute_particles(sim, PART_FROM_CHILD); } - psys_update_path_cache(scene, ob,psmd,psys,cfra); + psys_update_path_cache(sim, cfra); if(vg_size) MEM_freeN(vg_size); } -static void psys_changed_type(Object *ob, ParticleSystem *psys) +static void psys_changed_type(ParticleSimulationData *sim) { - ParticleSettings *part; + ParticleSettings *part = sim->psys->part; PTCacheID pid; - part= psys->part; - - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); /* system type has changed so set sensible defaults and clear non applicable flags */ if(part->from == PART_FROM_PARTICLE) { - if(part->type != PART_REACTOR) - part->from = PART_FROM_FACE; + //if(part->type != PART_REACTOR) + part->from = PART_FROM_FACE; if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT) part->distr = PART_DISTR_JIT; } if(part->phystype != PART_PHYS_KEYED) - psys->flag &= ~PSYS_KEYED; + sim->psys->flag &= ~PSYS_KEYED; if(part->type == PART_HAIR) { if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) @@ -4001,13 +3955,13 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys) BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_hair(ob, psys, 1); + free_hair(sim->ob, sim->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)); } - psys_reset(psys, PSYS_RESET_ALL); + psys_reset(sim->psys, PSYS_RESET_ALL); } void psys_check_boid_data(ParticleSystem *psys) { @@ -4033,24 +3987,24 @@ void psys_check_boid_data(ParticleSystem *psys) pa->boid = NULL; } } -static void psys_changed_physics(Object *ob, ParticleSystem *psys) +static void psys_changed_physics(ParticleSimulationData *sim) { - ParticleSettings *part = psys->part; + ParticleSettings *part = sim->psys->part; if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) { PTCacheID pid; - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { - free_keyed_keys(psys); - psys->flag &= ~PSYS_KEYED; + free_keyed_keys(sim->psys); + sim->psys->flag &= ~PSYS_KEYED; } if(part->phystype == PART_PHYS_BOIDS && part->boids == NULL) { BoidState *state; - psys_check_boid_data(psys); + psys_check_boid_data(sim->psys); part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings"); boid_default_settings(part->boids); @@ -4065,8 +4019,9 @@ static void psys_changed_physics(Object *ob, ParticleSystem *psys) BLI_addtail(&part->boids->states, state); } } -static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, int cfra) +static void particles_fluid_step(ParticleSimulationData *sim, int cfra) { + ParticleSystem *psys = sim->psys; if(psys->particles){ MEM_freeN(psys->particles); psys->particles = 0; @@ -4076,7 +4031,7 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, /* fluid sim particle import handling, actual loading of particles from file */ #ifndef DISABLE_ELBEEM { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); + FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim); if( fluidmd && fluidmd->fss) { FluidsimSettings *fss= fluidmd->fss; @@ -4086,7 +4041,7 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, char *suffix2 = ".gz"; char filename[256]; char debugStrBuffer[256]; - int curFrame = scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading + int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading int p, j, numFileParts, totpart; int readMask, activeParts = 0, fileParts = 0; gzFile gzf; @@ -4114,11 +4069,11 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, part->totpart= totpart; part->sta=part->end = 1.0f; - part->lifetime = scene->r.efra + 1; + part->lifetime = sim->scene->r.efra + 1; /* initialize particles */ - realloc_particles(ob, psys, part->totpart); - initialize_all_particles(ob, psys, 0); + realloc_particles(sim, part->totpart); + initialize_all_particles(sim); // set up reading mask readMask = fss->typeFlags; @@ -4174,10 +4129,11 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, /* Calculates the next state for all particles of the system */ /* In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)*/ -static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) +static void system_step(ParticleSimulationData *sim, float cfra) { - ParticleSettings *part; - PointCache *cache; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + PointCache *cache = psys->pointcache; PTCacheID pid; PARTICLE_P; int totpart, oldtotpart, totchild, oldtotchild; @@ -4185,20 +4141,17 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0; int framenr, framedelta, startframe, endframe; - part= psys->part; - cache= psys->pointcache; - - framenr= (int)scene->r.cfra; + framenr= (int)sim->scene->r.cfra; framedelta= framenr - cache->simframe; /* set suitable cache range automatically */ if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0 && !(psys->flag & PSYS_HAIR_DYNAMICS)) - psys_get_pointcache_start_end(scene, psys, &cache->startframe, &cache->endframe); + psys_get_pointcache_start_end(sim->scene, sim->psys, &cache->startframe, &cache->endframe); - BKE_ptcache_id_from_particles(&pid, ob, psys); - BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL); + BKE_ptcache_id_from_particles(&pid, sim->ob, psys); + BKE_ptcache_id_time(&pid, sim->scene, 0.0f, &startframe, &endframe, NULL); - psys_clear_temp_pointcache(psys); + psys_clear_temp_pointcache(sim->psys); /* update ipo's */ #if 0 // XXX old animation system @@ -4210,14 +4163,14 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* hair if it's already done is handled separate */ if(part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)) { - hair_step(scene, ob, psmd, psys, cfra); + hair_step(sim, cfra); psys->cfra = cfra; psys->recalc = 0; return; } /* fluid is also handled separate */ else if(part->type == PART_FLUID) { - particles_fluid_step(scene, ob, psys, framenr); + particles_fluid_step(sim, framenr); psys->cfra = cfra; psys->recalc = 0; return; @@ -4254,7 +4207,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle totpart = part->grid_res*part->grid_res*part->grid_res; else totpart = psys->part->totpart; - totchild = get_psys_tot_child(scene, psys); + totchild = get_psys_tot_child(sim->scene, psys); if(oldtotpart != totpart || oldtotchild != totchild) { only_children_changed = (oldtotpart == totpart); @@ -4271,45 +4224,45 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle if(init) { if(distr) { if(alloc) { - realloc_particles(ob, psys, totpart); + realloc_particles(sim, totpart); if(usecache && !only_children_changed) { BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); - BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_from_particles(&pid, sim->ob, psys); } } if(!only_children_changed) - distribute_particles(scene, ob, psys, part->from); + distribute_particles(sim, part->from); if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) /* don't generate children while growing hair - waste of time */ psys_free_children(psys); - else if(get_psys_tot_child(scene, psys)) - distribute_particles(scene, ob, psys, PART_FROM_CHILD); + else if(get_psys_tot_child(sim->scene, psys)) + distribute_particles(sim, PART_FROM_CHILD); } if(!only_children_changed) { free_keyed_keys(psys); - initialize_all_particles(ob, psys, psmd); + initialize_all_particles(sim); if(alloc) { - reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart); + reset_all_particles(sim, 0.0, cfra, oldtotpart); } } /* flag for possible explode modifiers after this system */ - psmd->flag |= eParticleSystemFlag_Pars; + sim->psmd->flag |= eParticleSystemFlag_Pars; } /* try to read from the cache */ if(usecache) { - int result = BKE_ptcache_read_cache(&pid, cfra, scene->r.frs_sec); + int result = BKE_ptcache_read_cache(&pid, cfra, sim->scene->r.frs_sec); if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) { - cached_step(scene, ob, psmd, psys, cfra); + cached_step(sim, cfra); psys->cfra=cfra; psys->recalc = 0; @@ -4333,7 +4286,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle pa->alive = PARS_ALIVE; } } - else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { + else if(sim->ob->id.lib || (cache->flag & PTCACHE_BAKED)) { psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; psys->recalc = 0; @@ -4351,14 +4304,14 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle BKE_ptcache_write_cache(&pid, startframe); if(part->phystype==PART_PHYS_KEYED) - psys_count_keyed_targets(ob,psys); + psys_count_keyed_targets(sim); /* initialize vertex groups */ if(part->from!=PART_FROM_PARTICLE) { - vg_vel= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); - vg_tan= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); - vg_rot= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); - vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); + vg_vel= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_VEL); + vg_tan= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_TAN); + vg_rot= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_ROT); + vg_size= psys_cache_vgroup(sim->psmd->dm,psys,PSYS_VG_SIZE); } /* set particles to be not calculated TODO: can't work with pointcache */ @@ -4366,7 +4319,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle BLI_srandom(psys->seed); LOOP_PARTICLES { - if(BLI_frand() > disp) + if(PSYS_FRAND(p) > disp) pa->flag |= PARS_NO_DISP; else pa->flag &= ~PARS_NO_DISP; @@ -4382,7 +4335,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle for(dframe=-totframesback; dframe<=0; dframe++) { /* ok now we're all set so let's go */ - dynamics_step(scene, ob, psys, psmd, cfra+dframe, vg_vel, vg_tan, vg_rot, vg_size); + dynamics_step(sim, cfra+dframe); psys->cfra = cfra+dframe; } } @@ -4399,8 +4352,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle /* for keyed particles the path is allways known so it can be drawn */ if(part->phystype==PART_PHYS_KEYED) { - set_keyed_keys(scene, ob, psys); - psys_update_path_cache(scene, ob, psmd, psys,(int)cfra); + set_keyed_keys(sim); + psys_update_path_cache(sim,(int)cfra); } else if(psys->pathcache) psys_free_path_cache(psys, NULL); @@ -4430,30 +4383,33 @@ static int hair_needs_recalc(ParticleSystem *psys) /* main particle update call, checks that things are ok on the large scale before actual particle calculations */ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) { - ParticleSystemModifierData *psmd; + ParticleSimulationData sim = {scene, ob, psys, NULL}; float cfra; + /* drawdata is outdated after ANY change */ + if(psys->pdd) psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED; + if(!psys_check_enabled(ob, psys)) return; cfra= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); - psmd= psys_get_modifier(ob, psys); + sim.psmd= psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ - if(psmd->flag & eParticleSystemFlag_psys_updated) { - psmd->flag &= ~eParticleSystemFlag_psys_updated; + if(sim.psmd->flag & eParticleSystemFlag_psys_updated) { + sim.psmd->flag &= ~eParticleSystemFlag_psys_updated; /* make sure it really was updated to cfra */ if(psys->cfra == cfra) return; } - if(!psmd->dm) + if(!sim.psmd->dm) return; if(psys->recalc & PSYS_RECALC_TYPE) - psys_changed_type(ob, psys); + psys_changed_type(&sim); else if(psys->recalc & PSYS_RECALC_PHYS) - psys_changed_physics(ob, psys); + psys_changed_physics(&sim); /* (re-)create hair */ if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) { @@ -4467,15 +4423,15 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) for(i=0; i<=psys->part->hair_step; i++){ hcfra=100.0f*(float)i/(float)psys->part->hair_step; - system_step(scene, ob, psys, psmd, hcfra); - save_hair(scene, ob, psys, psmd, hcfra); + system_step(&sim, hcfra); + save_hair(&sim, hcfra); } psys->flag |= PSYS_HAIR_DONE; } /* the main particle system step */ - system_step(scene, ob, psys, psmd, cfra); + system_step(&sim, cfra); /* save matrix for duplicators */ Mat4Invert(psys->imat, ob->obmat); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index d685bc29568..dfc5b4cd770 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -79,6 +79,20 @@ static void ptcache_data_to(void **data, int type, int index, void *to); static void ptcache_data_from(void **data, int type, void *from); +#define PTCACHE_DATA_FROM(data, type, from) if(data[type]) { memcpy(data[type], from, ptcache_data_size[type]); } +#define PTCACHE_DATA_TO(data, type, index, to) if(data[type]) { memcpy(to, (char*)data[type] + (index ? index * ptcache_data_size[type] : 0), ptcache_data_size[type]); } + +int ptcache_data_size[] = { + sizeof(int), // BPHYS_DATA_INDEX + 3 * sizeof(float), // BPHYS_DATA_LOCATION: + 3 * sizeof(float), // BPHYS_DATA_VELOCITY: + 4 * sizeof(float), // BPHYS_DATA_ROTATION: + 3 * sizeof(float), // BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ + sizeof(float), // BPHYS_DATA_SIZE: + 3 * sizeof(float), // BPHYS_DATA_TIMES: + sizeof(BoidData) // case BPHYS_DATA_BOIDS: +}; + /* Common functions */ static int ptcache_read_basic_header(PTCacheFile *pf) { @@ -110,8 +124,8 @@ static int ptcache_write_softbody(int index, void *soft_v, void **data) SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; - ptcache_data_from(data, BPHYS_DATA_LOCATION, bp->pos); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, bp->vec); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, bp->pos); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, bp->vec); return 1; } @@ -125,8 +139,8 @@ static void ptcache_read_softbody(int index, void *soft_v, void **data, float fr memcpy(bp->vec, data + 3, 3 * sizeof(float)); } else { - ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, bp->pos); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, bp->vec); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, bp->pos); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); } } static void ptcache_interpolate_softbody(int index, void *soft_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -181,25 +195,25 @@ static int ptcache_write_particle(int index, void *psys_v, void **data) return 0; } - ptcache_data_from(data, BPHYS_DATA_INDEX, &index); - ptcache_data_from(data, BPHYS_DATA_LOCATION, pa->state.co); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, pa->state.vel); - ptcache_data_from(data, BPHYS_DATA_ROTATION, pa->state.rot); - ptcache_data_from(data, BPHYS_DATA_AVELOCITY, pa->state.ave); - ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size); - ptcache_data_from(data, BPHYS_DATA_TIMES, times); + PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); + PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); + PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); + PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); + PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); if(boid) - ptcache_data_from(data, BPHYS_DATA_BOIDS, &boid->data); + PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); return 1; } void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) { - ptcache_data_to(data, BPHYS_DATA_LOCATION, index, key->co); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, index, key->vel); - ptcache_data_to(data, BPHYS_DATA_ROTATION, index, key->rot); - ptcache_data_to(data, BPHYS_DATA_AVELOCITY, index, key->ave); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, index, key->co); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, index, key->vel); + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, index, key->rot); + PTCACHE_DATA_TO(data, BPHYS_DATA_AVELOCITY, index, key->ave); key->time = time; } static void ptcache_read_particle(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) @@ -220,18 +234,18 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); if(data[BPHYS_DATA_SIZE]) - ptcache_data_to(data, BPHYS_DATA_SIZE, 0, &pa->size); + PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); if(data[BPHYS_DATA_TIMES]) { float times[3]; - ptcache_data_to(data, BPHYS_DATA_TIMES, 0, ×); + PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); pa->time = times[0]; pa->dietime = times[1]; pa->lifetime = times[2]; } if(boid) - ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &boid->data); + PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); /* determine velocity from previous location */ if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { @@ -307,6 +321,132 @@ static int ptcache_totwrite_particle(void *psys_v) return totwrite; } +//static int ptcache_write_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles; +// BoidParticle *boid = NULL; +// float times[3]; +// int i = 0; +// +// if(!pf && !pm) +// return 0; +// +// for(i=0; itotpart; i++, pa++) { +// +// if(data[BPHYS_DATA_INDEX]) { +// int step = psys->pointcache->step; +// /* No need to store unborn or died particles */ +// if(pa->time - step > pa->state.time || pa->dietime + step < pa->state.time) +// continue; +// } +// +// times[0] = pa->time; +// times[1] = pa->dietime; +// times[2] = pa->lifetime; +// +// PTCACHE_DATA_FROM(data, BPHYS_DATA_INDEX, &index); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, pa->state.co); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, pa->state.vel); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, pa->state.rot); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_AVELOCITY, pa->state.ave); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_SIZE, &pa->size); +// PTCACHE_DATA_FROM(data, BPHYS_DATA_TIMES, times); +// +// boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; +// if(boid) +// PTCACHE_DATA_FROM(data, BPHYS_DATA_BOIDS, &boid->data); +// +// if(pf && !ptcache_file_write_data(pf)) +// return 0; +// +// if(pm) +// BKE_ptcache_mem_incr_pointers(pm); +// } +// +// return 1; +//} +//static void ptcache_read_particle_stream(PTCacheFile *pf, PTCacheMem *pm, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles + index; +// BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL; +// +// if(cfra > pa->state.time) +// memcpy(&pa->prev_state, &pa->state, sizeof(ParticleKey)); +// +// if(old_data){ +// /* old format cache */ +// memcpy(&pa->state, old_data, sizeof(ParticleKey)); +// return; +// } +// +// BKE_ptcache_make_particle_key(&pa->state, 0, data, cfra); +// +// if(data[BPHYS_DATA_SIZE]) +// PTCACHE_DATA_TO(data, BPHYS_DATA_SIZE, 0, &pa->size); +// +// if(data[BPHYS_DATA_TIMES]) { +// float times[3]; +// PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, ×); +// pa->time = times[0]; +// pa->dietime = times[1]; +// pa->lifetime = times[2]; +// } +// +// if(boid) +// PTCACHE_DATA_TO(data, BPHYS_DATA_BOIDS, 0, &boid->data); +// +// /* determine velocity from previous location */ +// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { +// if(cfra > pa->prev_state.time) { +// VecSubf(pa->state.vel, pa->state.co, pa->prev_state.co); +// VecMulf(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); +// } +// else { +// VecSubf(pa->state.vel, pa->prev_state.co, pa->state.co); +// VecMulf(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); +// } +// } +// +// /* determine rotation from velocity */ +// if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_ROTATION]) { +// vectoquat(pa->state.vel, OB_POSX, OB_POSZ, pa->state.rot); +// } +//} +//static void ptcache_interpolate_particle_stream(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +//{ +// ParticleSystem *psys= psys_v; +// ParticleData *pa = psys->particles + index; +// ParticleKey keys[4]; +// float dfra; +// +// cfra = MIN2(cfra, pa->dietime); +// cfra1 = MIN2(cfra1, pa->dietime); +// cfra2 = MIN2(cfra2, pa->dietime); +// +// if(cfra1 == cfra2) +// return; +// +// memcpy(keys+1, &pa->state, sizeof(ParticleKey)); +// if(old_data) +// memcpy(keys+2, old_data, sizeof(ParticleKey)); +// else +// BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); +// +// dfra = cfra2 - cfra1; +// +// VecMulf(keys[1].vel, dfra / frs_sec); +// VecMulf(keys[2].vel, dfra / frs_sec); +// +// psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); +// QuatInterpol(pa->state.rot, keys[1].rot,keys[2].rot, (cfra - cfra1) / dfra); +// +// VecMulf(pa->state.vel, frs_sec / dfra); +// +// pa->state.time = cfra; +//} +// /* Cloth functions */ static int ptcache_write_cloth(int index, void *cloth_v, void **data) { @@ -314,9 +454,9 @@ static int ptcache_write_cloth(int index, void *cloth_v, void **data) Cloth *cloth= clmd->clothObject; ClothVertex *vert = cloth->verts + index; - ptcache_data_from(data, BPHYS_DATA_LOCATION, vert->x); - ptcache_data_from(data, BPHYS_DATA_VELOCITY, vert->v); - ptcache_data_from(data, BPHYS_DATA_XCONST, vert->xconst); + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, vert->x); + PTCACHE_DATA_FROM(data, BPHYS_DATA_VELOCITY, vert->v); + PTCACHE_DATA_FROM(data, BPHYS_DATA_XCONST, vert->xconst); return 1; } @@ -332,9 +472,9 @@ static void ptcache_read_cloth(int index, void *cloth_v, void **data, float frs_ memcpy(vert->v, data + 6, 3 * sizeof(float)); } else { - ptcache_data_to(data, BPHYS_DATA_LOCATION, 0, vert->x); - ptcache_data_to(data, BPHYS_DATA_VELOCITY, 0, vert->v); - ptcache_data_to(data, BPHYS_DATA_XCONST, 0, vert->xconst); + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, vert->x); + PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, vert->v); + PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); } } static void ptcache_interpolate_cloth(int index, void *cloth_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) @@ -987,7 +1127,7 @@ static int ptcache_file_read_data(PTCacheFile *pf) int i; for(i=0; idata_types & (1<cur[i], 1, BKE_ptcache_data_size(i))) + if(pf->data_types & (1<cur[i], 1, ptcache_data_size[i])) return 0; } @@ -998,7 +1138,7 @@ static int ptcache_file_write_data(PTCacheFile *pf) int i; for(i=0; idata_types & (1<cur[i], 1, BKE_ptcache_data_size(i))) + if(pf->data_types & (1<cur[i], 1, ptcache_data_size[i])) return 0; } @@ -1045,38 +1185,7 @@ static int ptcache_file_write_header_begin(PTCacheFile *pf) /* Data pointer handling */ int BKE_ptcache_data_size(int data_type) { - switch(data_type) { - case BPHYS_DATA_INDEX: - return sizeof(int); - case BPHYS_DATA_LOCATION: - case BPHYS_DATA_VELOCITY: - case BPHYS_DATA_AVELOCITY: /* also BPHYS_DATA_XCONST */ - case BPHYS_DATA_TIMES: - return 3 * sizeof(float); - case BPHYS_DATA_ROTATION: - return 4 * sizeof(float); - case BPHYS_DATA_SIZE: - return sizeof(float); - case BPHYS_DATA_BOIDS: - return sizeof(BoidData); - default: - return 0; - } -} -static void ptcache_data_to(void **data, int type, int index, void *to) -{ - if(data[type]) { - if(index) - memcpy(to, (char*)data[type] + index * BKE_ptcache_data_size(type), BKE_ptcache_data_size(type)); - else - memcpy(to, data[type], BKE_ptcache_data_size(type)); - } -} - -static void ptcache_data_from(void **data, int type, void *from) -{ - if(data[type]) - memcpy(data[type], from, BKE_ptcache_data_size(type)); + return ptcache_data_size[data_type]; } static void ptcache_file_init_pointers(PTCacheFile *pf) @@ -1108,7 +1217,7 @@ void BKE_ptcache_mem_incr_pointers(PTCacheMem *pm) for(i=0; icur[i]) - pm->cur[i] = (char*)pm->cur[i] + BKE_ptcache_data_size(i); + pm->cur[i] = (char*)pm->cur[i] + ptcache_data_size[i]; } } static void ptcache_alloc_data(PTCacheMem *pm) @@ -1119,7 +1228,7 @@ static void ptcache_alloc_data(PTCacheMem *pm) for(i=0; idata[i] = MEM_callocN(totpoint * BKE_ptcache_data_size(i), "PTCache Data"); + pm->data[i] = MEM_callocN(totpoint * ptcache_data_size[i], "PTCache Data"); } } static void ptcache_free_data(void *data[]) @@ -1136,7 +1245,7 @@ static void ptcache_copy_data(void *from[], void *to[]) int i; for(i=0; ipathcachebufs.first = psys->pathcachebufs.last = 0; psys->childcachebufs.first = psys->childcachebufs.last = 0; psys->reactevents.first = psys->reactevents.last = 0; + psys->frand = NULL; + psys->pdd = NULL; direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache); diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c index 6d1f2e5057b..cbfcf1508c7 100644 --- a/source/blender/editors/physics/editparticle.c +++ b/source/blender/editors/physics/editparticle.c @@ -1184,6 +1184,9 @@ void PE_update_object(Scene *scene, Object *ob, int useflag) point->flag &= ~PEP_EDIT_RECALC; } + if(edit->psys) + edit->psys->flag &= ~PSYS_HAIR_UPDATED; + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } @@ -1761,6 +1764,7 @@ static void rekey_particle(PEData *data, int pa_index) { PTCacheEdit *edit= data->edit; ParticleSystem *psys= edit->psys; + ParticleSimulationData sim = {data->scene, data->ob, edit->psys, NULL}; ParticleData *pa= psys->particles + pa_index; PTCacheEditPoint *point = edit->points + pa_index; ParticleKey state; @@ -1785,7 +1789,7 @@ static void rekey_particle(PEData *data, int pa_index) /* interpolate new keys from old ones */ for(k=1,key++; ktotrekey-1; k++,key++) { state.time= (float)k / (float)(data->totrekey-1); - psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0); + psys_get_particle_on_path(&sim, pa_index, &state, 0); VECCOPY(key->co, state.co); key->time= sta + k * dval; } @@ -1853,6 +1857,7 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float { PTCacheEdit *edit= PE_get_current(scene, ob); ParticleSystem *psys; + ParticleSimulationData sim = {scene, ob, edit ? edit->psys : NULL, NULL}; ParticleData *pa; ParticleKey state; HairKey *new_keys, *key; @@ -1872,7 +1877,7 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float /* interpolate new keys from old ones (roots stay the same) */ for(k=1, key++; k < pa->totkey; k++, key++) { state.time= path_time * (float)k / (float)(pa->totkey-1); - psys_get_particle_on_path(scene, ob, psys, pa_index, &state, 0); + psys_get_particle_on_path(&sim, pa_index, &state, 0); VECCOPY(key->co, state.co); } @@ -2044,6 +2049,7 @@ static void subdivide_particle(PEData *data, int pa_index) { PTCacheEdit *edit= data->edit; ParticleSystem *psys= edit->psys; + ParticleSimulationData sim = {data->scene, data->ob, edit->psys, NULL}; ParticleData *pa= psys->particles + pa_index; PTCacheEditPoint *point = edit->points + pa_index; ParticleKey state; @@ -2083,7 +2089,7 @@ static void subdivide_particle(PEData *data, int pa_index) if(ekey->flag & PEK_SELECT && (ekey+1)->flag & PEK_SELECT) { nkey->time= (key->time + (key+1)->time)*0.5f; state.time= (endtime != 0.0f)? nkey->time/endtime: 0.0f; - psys_get_particle_on_path(data->scene, data->ob, psys, pa_index, &state, 0); + psys_get_particle_on_path(&sim, pa_index, &state, 0); VECCOPY(nkey->co, state.co); nekey->co= nkey->co; @@ -2875,12 +2881,13 @@ static void brush_add(PEData *data, short number) ParticleSystem *psys= edit->psys; ParticleData *add_pars= MEM_callocN(number*sizeof(ParticleData),"ParticleData add"); ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys); + ParticleSimulationData sim = {scene, ob, psys, psmd}; ParticleEditSettings *pset= PE_settings(scene); int i, k, n= 0, totpart= psys->totpart; short mco[2]; short dmx= 0, dmy= 0; float co1[3], co2[3], min_d, imat[4][4]; - float framestep, timestep= psys_get_timestep(psys->part); + float framestep, timestep= psys_get_timestep(&sim); short size= pset->brush[PE_BRUSH_ADD].size; short size2= size*size; DerivedMesh *dm=0; @@ -2975,8 +2982,8 @@ static void brush_add(PEData *data, short number) } pa->size= 1.0f; - initialize_particle(pa,i,ob,psys,psmd); - reset_particle(scene, pa,psys,psmd,ob,0.0,1.0,0,0,0); + initialize_particle(&sim, pa,i); + reset_particle(&sim, pa, 0.0, 1.0); point->flag |= PEP_EDIT_RECALC; if(pset->flag & PE_X_MIRROR) point->flag |= PEP_TAG; /* signal for duplicate */ @@ -3013,18 +3020,18 @@ static void brush_add(PEData *data, short number) hkey->time= pa->time + k * framestep; key[0].time= hkey->time/ 100.0f; - psys_get_particle_on_path(scene, ob, psys, ptn[0].index, key, 0); + psys_get_particle_on_path(&sim, ptn[0].index, key, 0); VecMulf(key[0].co, weight[0]); if(maxw>1) { key[1].time= key[0].time; - psys_get_particle_on_path(scene, ob, psys, ptn[1].index, key + 1, 0); + psys_get_particle_on_path(&sim, ptn[1].index, key + 1, 0); VecMulf(key[1].co, weight[1]); VECADD(key[0].co, key[0].co, key[1].co); if(maxw>2) { key[2].time= key[0].time; - psys_get_particle_on_path(scene, ob, psys, ptn[2].index, key + 2, 0); + psys_get_particle_on_path(&sim, ptn[2].index, key + 2, 0); VecMulf(key[2].co, weight[2]); VECADD(key[0].co, key[0].co, key[2].co); } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 40eb74e8062..3212d5cee89 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -2974,13 +2974,6 @@ static void view3d_particle_text_draw(View3D *v3d, ARegion *ar) if(pstrings.first) BLI_freelistN(&pstrings); } -typedef struct ParticleDrawData { - float *vdata, *vd; - float *ndata, *nd; - float *cdata, *cd; - float *vedata, *ved; - float *ma_r, *ma_g, *ma_b; -} ParticleDrawData; static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd) { float vec[3], vec2[3]; @@ -3145,7 +3138,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv ParticleData *pars, *pa; ParticleKey state, *states=0; ParticleBillboardData bb; - ParticleDrawData pdd; + ParticleSimulationData sim = {scene, ob, psys, NULL}; + ParticleDrawData *pdd = psys->pdd; Material *ma; float vel[3], imat[4][4]; float timestep, pixsize=1.0, pa_size, r_tilt, r_length; @@ -3176,9 +3170,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(part->draw_as==PART_DRAW_NOT) return; /* 2. */ + sim.psmd = psmd = psys_get_modifier(ob,psys); + if(part->phystype==PART_PHYS_KEYED){ if(psys->flag&PSYS_KEYED){ - psys_count_keyed_targets(ob,psys); + psys_count_keyed_targets(&sim); if(psys->totkeyed==0) return; } @@ -3196,8 +3192,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv totchild=0; else totchild=psys->totchild*part->disp/100; - - memset(&pdd, 0, sizeof(ParticleDrawData)); ma= give_current_material(ob,part->omat); @@ -3212,18 +3206,16 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv ma_g = ma->g; ma_b = ma->b; - pdd.ma_r = &ma_r; - pdd.ma_g = &ma_g; - pdd.ma_b = &ma_b; + pdd->ma_r = &ma_r; + pdd->ma_g = &ma_g; + pdd->ma_b = &ma_b; create_cdata = 1; } else cpack(0); - psmd= psys_get_modifier(ob,psys); - - timestep= psys_get_timestep(part); + timestep= psys_get_timestep(&sim); if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) { float mat[4][4]; @@ -3317,54 +3309,65 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv /* 4. */ if(draw_as && draw_as!=PART_DRAW_PATH) { int tot_vec_size = (totpart + totchild) * 3 * sizeof(float); - + + if(!pdd) + pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticlDrawData"); + if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) { tot_vec_size *= part->trail_count; psys_make_temp_pointcache(ob, psys); } + if(pdd->tot_vec_size != tot_vec_size) + psys_free_pdd(psys); + if(draw_as!=PART_DRAW_CIRC) { switch(draw_as) { case PART_DRAW_AXIS: case PART_DRAW_CROSS: if(draw_as != PART_DRAW_CROSS || create_cdata) - pdd.cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata"); - pdd.vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata"); + if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata"); + if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata"); break; case PART_DRAW_LINE: if(create_cdata) - pdd.cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata"); - pdd.vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata"); + if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata"); + if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata"); break; case PART_DRAW_BB: if(create_cdata) - pdd.cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata"); - pdd.vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); - pdd.ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); + if(!pdd->cdata) pdd->cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata"); + if(!pdd->vdata) pdd->vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); + if(!pdd->ndata) pdd->ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata"); break; default: if(create_cdata) - pdd.cdata=MEM_callocN(tot_vec_size, "particle_cdata"); - pdd.vdata=MEM_callocN(tot_vec_size, "particle_vdata"); + if(!pdd->cdata) pdd->cdata=MEM_callocN(tot_vec_size, "particle_cdata"); + if(!pdd->vdata) pdd->vdata=MEM_callocN(tot_vec_size, "particle_vdata"); } } if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) { - pdd.vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata"); + if(!pdd->vedata) pdd->vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata"); need_v = 1; } - pdd.vd= pdd.vdata; - pdd.ved= pdd.vedata; - pdd.cd= pdd.cdata; - pdd.nd= pdd.ndata; + pdd->vd= pdd->vdata; + pdd->ved= pdd->vedata; + pdd->cd= pdd->cdata; + pdd->nd= pdd->ndata; + pdd->tot_vec_size= tot_vec_size; - psys->lattice= psys_get_lattice(scene, ob, psys); + psys->lattice= psys_get_lattice(&sim); } if(draw_as){ /* 5. */ - for(a=0,pa=pars; aflag & PARTICLE_DRAW_DATA_UPDATED) + && (pdd->vedata || part->draw & (PART_DRAW_SIZE|PART_DRAW_NUM|PART_DRAW_HEALTH))==0) { + totpoint = pdd->totpoint; /* draw data is up to date */ + } + else for(a=0,pa=pars; adraw&PART_DRAW_PARENT)==0) continue; @@ -3374,9 +3377,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pa_birthtime=pa->time; pa_dietime = pa->dietime; pa_size=pa->size; - if(part->phystype==PART_PHYS_BOIDS) { + if(part->phystype==PART_PHYS_BOIDS) pa_health = pa->boid->data.health; - } else pa_health = -1.0; @@ -3411,10 +3413,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv } #endif // XXX old animation system - BLI_srandom(psys->seed+a); - - r_tilt = 2.0f*(BLI_frand() - 0.5f); - r_length = BLI_frand(); + r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); + r_length = PSYS_FRAND(a + 22); } else{ ChildParticle *cpa= &psys->child[a-totpart]; @@ -3445,8 +3445,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pa_health = -1.0; - r_tilt = 2.0f * cpa->rand[2]; - r_length = cpa->rand[1]; + r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); + r_length = PSYS_FRAND(a + 22); } if(draw_as!=PART_DRAW_PATH){ @@ -3468,7 +3468,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv continue; state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime)); - psys_get_particle_on_path(scene,ob,psys,a,&state,need_v); + psys_get_particle_on_path(&sim,a,&state,need_v); if(psys->parent) Mat4MulVecfl(psys->parent->obmat, state.co); @@ -3480,7 +3480,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv bb.time = ct; } - draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd); + draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, psys->pdd); totpoint++; drawn = 1; @@ -3489,7 +3489,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv else { state.time=cfra; - if(psys_get_particle_state(scene,ob,psys,a,&state,0)){ + if(psys_get_particle_state(&sim,a,&state,0)){ if(psys->parent) Mat4MulVecfl(psys->parent->obmat, state.co); @@ -3500,7 +3500,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv bb.time = pa_time; } - draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd); + draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, pdd); totpoint++; drawn = 1; @@ -3510,13 +3510,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(drawn) { /* additional things to draw for each particle */ /* (velocity, size and number) */ - if(pdd.vedata){ - VECCOPY(pdd.ved,state.co); - pdd.ved+=3; + if(pdd->vedata){ + VECCOPY(pdd->ved,state.co); + pdd->ved+=3; VECCOPY(vel,state.vel); VecMulf(vel,timestep); - VECADD(pdd.ved,state.co,vel); - pdd.ved+=3; + VECADD(pdd->ved,state.co,vel); + pdd->ved+=3; totve++; } @@ -3628,17 +3628,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDisableClientState(GL_COLOR_ARRAY); /* setup created data arrays */ - if(pdd.vdata){ + if(pdd->vdata){ glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd.vdata); + glVertexPointer(3, GL_FLOAT, 0, pdd->vdata); } else glDisableClientState(GL_VERTEX_ARRAY); /* billboards are drawn this way */ - if(pdd.ndata && ob_dt>OB_WIRE){ + if(pdd->ndata && ob_dt>OB_WIRE){ glEnableClientState(GL_NORMAL_ARRAY); - glNormalPointer(GL_FLOAT, 0, pdd.ndata); + glNormalPointer(GL_FLOAT, 0, pdd->ndata); glEnable(GL_LIGHTING); } else{ @@ -3646,9 +3646,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDisable(GL_LIGHTING); } - if(pdd.cdata){ + if(pdd->cdata){ glEnableClientState(GL_COLOR_ARRAY); - glColorPointer(3, GL_FLOAT, 0, pdd.cdata); + glColorPointer(3, GL_FLOAT, 0, pdd->cdata); } /* draw created data arrays */ @@ -3670,14 +3670,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv glDrawArrays(GL_POINTS, 0, totpoint); break; } + + pdd->flag |= PARTICLE_DRAW_DATA_UPDATED; + pdd->totpoint = totpoint; } - if(pdd.vedata){ + if(pdd->vedata){ glDisableClientState(GL_COLOR_ARRAY); cpack(0xC0C0C0); glEnableClientState(GL_VERTEX_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, pdd.vedata); + glVertexPointer(3, GL_FLOAT, 0, pdd->vedata); glDrawArrays(GL_LINES, 0, 2*totve); } @@ -3694,14 +3697,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv if(states) MEM_freeN(states); - if(pdd.vdata) - MEM_freeN(pdd.vdata); - if(pdd.vedata) - MEM_freeN(pdd.vedata); - if(pdd.cdata) - MEM_freeN(pdd.cdata); - if(pdd.ndata) - MEM_freeN(pdd.ndata); psys->flag &= ~PSYS_DRAWING; @@ -3728,10 +3723,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Obj float *pathcol = NULL, *pcol; - if(edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) { + if(edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) PE_update_object(scene, ob, 0); - edit->psys->flag &= ~PSYS_HAIR_UPDATED; - } /* create path and child path cache if it doesn't exist already */ if(edit->pathcache==0) diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 6a0a0e1d912..089c1c76bcf 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -67,7 +67,7 @@ typedef struct ChildParticle { int pa[4]; /* nearest particles to the child, used for the interpolation */ float w[4]; /* interpolation weights for the above particles */ float fuv[4], foffset; /* face vertex weights and offset */ - float rand[3]; + float rt; } ChildParticle; typedef struct ParticleTarget { @@ -234,13 +234,17 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in struct ListBase ptcaches; struct KDTree *tree; /* used for interactions with self and other systems */ + + struct ParticleDrawData *pdd; + + float *frand; /* array of 1024 random floats for fast lookups */ }ParticleSystem; /* part->type */ /* hair is allways baked static in object/geometry space */ /* other types (normal particles) are in global space and not static baked */ #define PART_EMITTER 0 -#define PART_REACTOR 1 +//#define PART_REACTOR 1 #define PART_HAIR 2 #define PART_FLUID 3 @@ -325,7 +329,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PART_DRAW_EMITTER 8 /* render emitter also */ #define PART_DRAW_HEALTH 16 #define PART_ABS_PATH_TIME 32 -//#define PART_DRAW_TRAIL 64 +//#define PART_DRAW_TRAIL 64 /* deprecated */ #define PART_DRAW_BB_LOCK 128 #define PART_DRAW_PARENT 256 #define PART_DRAW_NUM 512 @@ -422,13 +426,13 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PSYS_HAIR_DONE 512 #define PSYS_KEYED 1024 #define PSYS_EDITED 2048 -//#define PSYS_PROTECT_CACHE 4096 +//#define PSYS_PROTECT_CACHE 4096 /* deprecated */ #define PSYS_DISABLED 8192 /* pars->flag */ #define PARS_UNEXIST 1 #define PARS_NO_DISP 2 -//#define PARS_STICKY 4 +//#define PARS_STICKY 4 /* deprecated */ #define PARS_REKEY 8 /* pars->alive */ diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 02fa0c25335..5821d30bc3b 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -312,9 +312,10 @@ static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value) if(value > settings->end) value = settings->end; - if(settings->type==PART_REACTOR && value < 1.0) - value = 1.0; - else if (value < MINAFRAMEF) + //if(settings->type==PART_REACTOR && value < 1.0) + // value = 1.0; + //else + if (value < MINAFRAMEF) value = MINAFRAMEF; settings->sta = value; @@ -522,9 +523,9 @@ static EnumPropertyItem *rna_Particle_from_itemf(bContext *C, PointerRNA *ptr, i return item; } - if(part->type==PART_REACTOR) - return part_reactor_from_items; - else + //if(part->type==PART_REACTOR) + // return part_reactor_from_items; + //else return part_from_items; } @@ -767,7 +768,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) static EnumPropertyItem type_items[] = { {PART_EMITTER, "EMITTER", 0, "Emitter", ""}, - {PART_REACTOR, "REACTOR", 0, "Reactor", ""}, + //{PART_REACTOR, "REACTOR", 0, "Reactor", ""}, {PART_HAIR, "HAIR", 0, "Hair", ""}, {0, NULL, 0, NULL, NULL} }; @@ -986,10 +987,10 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Children", "Apply effectors to children."); RNA_def_property_update(prop, 0, "rna_Particle_redo"); - prop= RNA_def_property(srna, "child_seams", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_CHILD_SEAMS); - RNA_def_property_ui_text(prop, "Use seams", "Use seams to determine parents"); - RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); + //prop= RNA_def_property(srna, "child_seams", PROP_BOOLEAN, PROP_NONE); + //RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_CHILD_SEAMS); + //RNA_def_property_ui_text(prop, "Use seams", "Use seams to determine parents"); + //RNA_def_property_update(prop, 0, "rna_Particle_redo_child"); /* TODO: used somewhere? */ prop= RNA_def_property(srna, "child_render", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 99825c0c2ff..0c56841b70d 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1484,6 +1484,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem ParticleKey state; ParticleCacheKey *cache=0; ParticleBillboardData bb; + ParticleSimulationData sim = {re->scene, ob, psys, NULL}; ParticleStrandData sd; StrandBuffer *strandbuf=0; StrandVert *svert=0; @@ -1517,14 +1518,16 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem return 1; /* 2. start initialising things */ - if(part->phystype==PART_PHYS_KEYED) - psys_count_keyed_targets(ob,psys); /* last possibility to bail out! */ - psmd= psys_get_modifier(ob,psys); + sim.psmd = psmd = psys_get_modifier(ob,psys); if(!(psmd->modifier.mode & eModifierMode_Render)) return 0; + if(part->phystype==PART_PHYS_KEYED) + psys_count_keyed_targets(&sim); + + if(G.rendering == 0) { /* preview render */ totchild = (int)((float)totchild * (float)part->disp / 100.0f); } @@ -1611,14 +1614,14 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem #endif // XXX old animation system cfra = bsystem_time(re->scene, 0, (float)re->scene->r.cfra, 0.0); -/* 2.4 setup reactors */ - if(part->type == PART_REACTOR){ - psys_get_reactor_target(ob, psys, &tob, &tpsys); - if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ - psmd = psys_get_modifier(tob,tpsys); - tpart = tpsys->part; - } - } +///* 2.4 setup reactors */ +// if(part->type == PART_REACTOR){ +// psys_get_reactor_target(ob, psys, &tob, &tpsys); +// if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){ +// psmd = psys_get_modifier(tob,tpsys); +// tpart = tpsys->part; +// } +// } /* 2.5 setup matrices */ Mat4MulMat4(mat, ob->obmat, re->viewmat); @@ -1695,7 +1698,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem } if(path_nbr == 0) - psys->lattice = psys_get_lattice(re->scene, ob, psys); + psys->lattice = psys_get_lattice(&sim); /* 3. start creating renderable things */ for(a=0,pa=pars; arand[2]; - r_length = cpa->rand[1]; + r_tilt = 2.0f*(PSYS_FRAND(a + 21) - 0.5f); + r_length = PSYS_FRAND(a + 22); num = cpa->num; @@ -1952,7 +1955,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem continue; state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct; - psys_get_particle_on_path(re->scene,ob,psys,a,&state,1); + psys_get_particle_on_path(&sim,a,&state,1); if(psys->parent) Mat4MulVecfl(psys->parent->obmat, state.co); @@ -1971,7 +1974,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem else { time=0.0f; state.time=cfra; - if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0) + if(psys_get_particle_state(&sim,a,&state,0)==0) continue; if(psys->parent) diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 5f8cf5504fa..b7832e74cd1 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -92,6 +92,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa { DerivedMesh* dm; ParticleKey state; + ParticleSimulationData sim = {re->scene, ob, psys, NULL}; ParticleData *pa=NULL; float cfra = bsystem_time(re->scene, ob, (float)re->scene->r.cfra, 0.0); int i, childexists; @@ -120,7 +121,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa Mat4Invert(ob->imat, ob->obmat); total_particles = psys->totpart+psys->totchild; - psys->lattice=psys_get_lattice(re->scene,ob,psys); + psys->lattice=psys_get_lattice(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); alloc_point_data(pd, total_particles, data_used); @@ -133,7 +134,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa for (i=0, pa=psys->particles; i < total_particles; i++, pa++) { state.time = cfra; - if(psys_get_particle_state(re->scene, ob, psys, i, &state, 0)) { + if(psys_get_particle_state(&sim, i, &state, 0)) { VECCOPY(partco, state.co);