Particles cleanup, optimizations and some small new stuff.
authorJanne Karhu <jhkarh@gmail.com>
Thu, 17 Sep 2009 22:00:49 +0000 (22:00 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Thu, 17 Sep 2009 22:00:49 +0000 (22:00 +0000)
New stuff
- Bending springs for hair dynamics.

Code cleanup & optimization
- Disabled reactor particles temporarily for cleanup, it's a clumsy system that will be replaced with something better.
- Removed child seams, something better will come here too :)
- Normal particle drawing data is now saved between redraws if the particles don't move between redraws.
* For example rotating the 3d view is now realtime even with 1M particles.
- Many random values for particles now come from a lookup table making things much faster.
- Most accessed small point cache functions are now much faster as macros.
- Lot's of general code cleanup.
- Nothing big should have changed so if something doesn't work like it used to it's probably just a typo somewhere :)

18 files changed:
release/ui/buttons_particle.py
source/blender/blenkernel/BKE_boids.h
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/boids.c
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/physics/editparticle.c
source/blender/editors/space_view3d/drawobject.c
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_particle.c
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/pointdensity.c

index 1bbd64c9b0fe93d5fa7d59bfa3a3c3e5ed974b88..e72bd38e5632a042a2231708137bbf4a4d04d8c6 100644 (file)
@@ -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")
index acceff863b989f6a5bae4e0647f544e41e7709bf..fb65c9c89204fac499c2be948b8bd567b86f4971 100644 (file)
@@ -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;
index c22778f5a3021f0a3129be4462aba17008d13403..5850ddaca08f38ca0f7ce29f27712b7376fd7b2d 100644 (file)
@@ -61,6 +61,23 @@ struct BVHTreeRayHit;
 
 #define PARTICLE_P                             ParticleData *pa; int p
 #define LOOP_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)
+#define LOOP_EXISTING_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++) if(!(pa->flag & PARS_UNEXIST))
+#define LOOP_SHOWN_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; 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 */
index 8cb88cdb7865a6616df8e06ba634c6b07d79a2bd..e943d92a0b56b350bb0e34296c5824adaa3858ca 100644 (file)
@@ -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);
                        }
                }
 
index 18f065b59d90294f592fe03cb47b733986de7d14..7c3f3a7876f1c0222b85bb4c78bfa7976a333a21 100644 (file)
@@ -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; n<neighbors; n++) {
                        VECCOPY(co1, pa->prev_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; n<neighbors; n++) {
-                       VecAddf(loc, loc, bbd->psys->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; n<neighbors; n++) {
-               bpa = bbd->psys->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);
index 9ee6be903fa7ceb338ffba306bc3a0bf851fcd33..5cfbd5c18dc2ad5752e629bdd8e4988c78a66f7a 100644 (file)
@@ -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 )
+                       {
+                               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;
+                                       }
 
-               tspring2 = search2->link;
-               search = edgelist[tspring2->kl];
-               while ( search )
+                                       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) */
index 58f3db50d0fc5e97f00122a017e534b241d3080f..4c2b2f3ec125b9e2f9fb958b60500dbf03899572 100644 (file)
@@ -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;
index c64c48b9ce74e5a63991d2d82b55835804966649..b9b9ea6b4f39382c403b845a91fdd0bd1491f0fe 100644 (file)
@@ -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;
index cce18e991576c1e8e5c512572feef9abb5e2f81f..0dc041bfc6a7efb6f8f863c9452f7d02175cdcb0 100644 (file)
@@ -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; a<totorigface; a++, elem++) {
-               area = psys_render_projected_area(ctx->psys, 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; p<totparent; p++,cpa++){
-               psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
+       for(p=0,cpa=sim->psys->child; p<totparent; p++,cpa++){
+               psys_particle_on_emitter(sim->psmd,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(; p<totchild; p++,cpa++){
-               psys_particle_on_emitter(psmd,from,cpa->num,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; i<totpart; i++, pa++){
-               if(pa->flag & 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;
+       if(p>=totpart){
+               if(!psys->totchild)
+                       return 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
-                       pa=psys->particles+(psys->child+p-totpart)->parent;
        }
-       else
-               pa=psys->particles+p;
+       else {
+               pa = sim->psys->particles + p;
+       }
 
-       if(between){
-               state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL);
+       if(pa) {
+               if(pa->alive == PARS_KILLED) return 0;
 
-               if(always==0)
-                       if((state->time<0.0 && (part->flag & PART_UNBORN)==0)
-                               || (state->time>1.0 && (part->flag & PART_DIED)==0))
-                               return 0;
-       }
-       else{
-               if(pa->alive==PARS_KILLED) return 0;
-               if(always==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,
index 26d23399316a730e2f673b5d0fb6790a258bcaba..9cd897e4bcdd4cca9d4457c9565ece446aa9e48c 100644 (file)
@@ -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; w<maxw; w++){
                                parent[w]=ptn[w].index;
                                pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd));
-                               //pweight[w]= (1.0f - ptn[w].dist*ptn[w].dist/(maxd*maxd));
-                               //pweight[w] *= pweight[w];
                        }
                        for(;w<10; w++){
                                parent[w]=-1;
                                pweight[w]=0.0f;
                        }
-                       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; i<ctx->totseam; 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_len<min_len){
-                                               min_len=cur_len;
-                                               min_seam=i;
-                                               if(inp<0.0f) near_vert=-1;
-                                               else if(inp>1.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; i<ctx->totseam; 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_len<min_len){
+                       //                      min_len=cur_len;
+                       //                      min_seam=i;
+                       //                      if(inp<0.0f) near_vert=-1;
+                       //                      else if(inp>1.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; w<maxw; w++){
+                       //              VecSubf(temp2,ptn[w].co,temp);
+                       //              if(Inpf(tan,temp2)<0.0f){
+                       //                      parent[w]=-1;
+                       //                      pweight[w]=0.0f;
+                       //              }
+                       //      }
 
-                                       Normalize(tan);
-                               }
-                               else{
-                                       VecCopyf(tan,seam->tan);
-                                       VecSubf(temp2,co1,temp);
-                                       if(Inpf(tan,temp2)<0.0f)
-                                               VecNegf(tan);
-                               }
-                               for(w=0; w<maxw; w++){
-                                       VecSubf(temp2,ptn[w].co,temp);
-                                       if(Inpf(tan,temp2)<0.0f){
-                                               parent[w]=-1;
-                                               pweight[w]=0.0f;
-                                       }
-                               }
-
-                       }
+                       //}
 
                        for(w=0,i=0; w<maxw && i<4; w++){
                                if(parent[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; p<totedge; p++,ed++)
-                                       if(ed->flag&ME_SEAM)
-                                               totseam++;
+                       //      for(p=0, ed=medge; p<totedge; p++,ed++)
+                       //              if(ed->flag&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; p<totedge; p++,ed++){
-                                               if(ed->flag&ME_SEAM){
-                                                       VecCopyf(cur_seam->v0,(mvert+ed->v1)->co);
-                                                       VecCopyf(cur_seam->v1,(mvert+ed->v2)->co);
+                       //              for(p=0, ed=medge; p<totedge; p++,ed++){
+                       //                      if(ed->flag&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; i<totthread; i++) {
                threads[i].rng= rng_new(seed);
                threads[i].tot= totthread;
@@ -1394,16 +1366,17 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive
        return 1;
 }
 
-static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Object *ob, ParticleSystem *psys, int from)
+static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
 {
+       DerivedMesh *finaldm = sim->psmd->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);
-       }
-
-       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_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);
+
+       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; p<totpart; p++, pa++)
-               reset_particle(scene, pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot);
+       for(p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++)
+               reset_particle(sim, pa, dtime, cfra);
 
-       if(vg_vel)
-               MEM_freeN(vg_vel);
+       //if(vg_vel)
+       //      MEM_freeN(vg_vel);
 }
 /************************************************/
 /*                     Particle targets                                        */
@@ -2041,15 +1978,15 @@ ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt)
 /*                     Keyed particles                                         */
 /************************************************/
 /* Counts valid keyed targets */
-void psys_count_keyed_targets(Object *ob, ParticleSystem *psys)
+void psys_count_keyed_targets(ParticleSimulationData *sim)
 {
-       ParticleSystem *kpsys;
+       ParticleSystem *psys = sim->psys, *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; k<totkeys; k++) {
-               if(pt->ob)
-                       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; p<totepart; p++,epa++)
-                                               if(epa->alive==PARS_ALIVE && psys_get_particle_state(scene, eob,epsys,p,&state,0))
+                                       for(p=0, epa=esim.psys->particles; p<totepart; p++,epa++)
+                                               if(epa->alive==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(; p<totepart; p++){
                                        /* particle skips itself as effector */
-                                       if(epsys==psys && p == pa_no) continue;
+                                       if(esim.psys == psys && p == pa_no) continue;
 
-                                       epa = epsys->particles + 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; k<pa->totkey; 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);
+
+                       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);
+                       ///* 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);
+
+               pa->size = part->size;
+               if(part->randsize > 0.0)
+                       pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1);
 
-               psys->lattice= psys_get_lattice(scene, ob, psys);
+               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);
index d685bc29568fc66ae3b76b0193feb40df19a8d84..dfc5b4cd7701bbc2e4cee79c343ca7060094fdde 100644 (file)
 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, &times);
+               PTCACHE_DATA_TO(data, BPHYS_DATA_TIMES, 0, &times);
                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; i<psys->totpart; 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, &times);
+//             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; i<BPHYS_TOT_DATA; i++) {
-               if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
+               if(pf->data_types & (1<<i) && !ptcache_file_read(pf, pf->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; i<BPHYS_TOT_DATA; i++) {
-               if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->cur[i], 1, BKE_ptcache_data_size(i)))
+               if(pf->data_types & (1<<i) && !ptcache_file_write(pf, pf->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; i<BPHYS_TOT_DATA; i++) {
                if(pm->cur[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; i<BPHYS_TOT_DATA; i++) {
                if(data_types & (1<<i))
-                       pm->data[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; i<BPHYS_TOT_DATA; i++) {
                if(from[i])
-                       memcpy(to[i], from[i], BKE_ptcache_data_size(i));
+                       memcpy(to[i], from[i], ptcache_data_size[i]);
        }
 }
 
index 6518db2dc91314fa9f014ed19f4dcbbacab03733..0cbbc1051e73a0e80ce5b1b1669bf487e344e609 100644 (file)
@@ -3163,6 +3163,8 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
                psys->pathcachebufs.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);
 
index 6d1f2e5057b24a66a147c5ece9b40544dc9f62b6..cbfcf1508c780ea6c1659a7074dd16edf411c161 100644 (file)
@@ -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++; k<data->totrekey-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);
                                                }
index 40eb74e8062d845b2e46a25e209d90b13b05a45c..3212d5cee89a34e19edb7ddd3ac5645a387c9657 100644 (file)
@@ -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; a<totpart+totchild; a++, pa++){
+               if((pdd->flag & 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; a<totpart+totchild; a++, pa++){
                        /* setup per particle individual stuff */
                        if(a<totpart){
                                if(totchild && (part->draw&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)
index 6a0a0e1d9121d399593c6d686e54d96e24c45dff..089c1c76bcf0828ed8b44c005556320bb6b02dae 100644 (file)
@@ -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 */
index 02fa0c253350bc2cb10556f6105501f1c9bf44f3..5821d30bc3bb9882d54ece3980f61f9b2452766c 100644 (file)
@@ -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);
index 99825c0c2ff179184968aaef7a7e8a1c2de683ae..0c56841b70dba2a716236c43ad4f6757d5a32a4d 100644 (file)
@@ -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&