Some particles cleanup & fixes:
authorJanne Karhu <jhkarh@gmail.com>
Fri, 4 Sep 2009 23:06:15 +0000 (23:06 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Fri, 4 Sep 2009 23:06:15 +0000 (23:06 +0000)
- Some big refresh issues with softbody & cloth point cache usage should now be fixed.
- Removed sticky objects from particles (better stuff will come back when I get to updating reactor particles).
- Some initial easy memory efficiency cleanup for ParticleData struct. The ultimate goal is to get particles less memory hungry -> more particles possible in single scene.
- Wrong path timing clamping caused hair particles to seem disappeared when changing between normal<->hair particles.
- "Calculate to current frame" in cache buttons baked instead of the intended function.
- Boids particle data is now a bit better organized.

19 files changed:
release/ui/buttons_particle.py
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/boids.c
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/object/object_edit.c
source/blender/editors/physics/ed_pointcache.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

index 0b18b7c2072a80916039666272351b678d11f193..f3339049962cc261492f01114046d923a65610a0 100644 (file)
@@ -396,7 +396,6 @@ class PARTICLE_PT_physics(ParticleButtonsPanel):
                if part.physics_type=='NEWTON':
                        sub.itemR(part, "size_deflect")
                        sub.itemR(part, "die_on_collision")
-                       sub.itemR(part, "sticky")
                elif part.physics_type=='KEYED' or part.physics_type=='BOIDS':
                        if part.physics_type=='BOIDS':
                                layout.itemL(text="Relations:")
index e24114cd2190d8c7d6594e30feb36813d3fa2963..15896477a6aee7ab40a17d97011956569462547e 100644 (file)
@@ -59,6 +59,9 @@ struct SurfaceModifierData;
 struct BVHTreeRay;
 struct BVHTreeRayHit; 
 
+#define PARTICLE_P                             ParticleData *pa; int p
+#define LOOP_PARTICLES for(p=0, pa=psys->particles; p<psys->totpart; p++, pa++)
+
 typedef struct ParticleEffectorCache {
        struct ParticleEffectorCache *next, *prev;
        struct Object *ob;
@@ -207,6 +210,7 @@ void free_child_path_cache(struct ParticleSystem *psys);
 void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit);
 void free_hair(struct ParticleSystem *psys, int softbody);
 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);
 
index 5c62e434cb662158dd74590970a86546de16235d..18f065b59d90294f592fe03cb47b733986de7d14 100644 (file)
@@ -74,6 +74,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
        BoidSettings *boids = bbd->part->boids;
        ParticleEffectorCache *ec;
        Object *priority_ob = NULL;
+       BoidParticle *bpa = pa->boid;
        float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
        float mul = (rule->type == eBoidRuleType_Avoid ? 1.0 : -1.0);
        float priority = 0.0f, len = 0.0f;
@@ -81,7 +82,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
 
        /* first find out goal/predator with highest priority */
        /* if rule->ob specified use it */
-       if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != pa->stick_ob)) {
+       if(gabr->ob && (rule->type != eBoidRuleType_Goal || gabr->ob != bpa->ground)) {
                PartDeflect *pd = gabr->ob->pd;
                float vec_to_part[3];
 
@@ -104,7 +105,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
                        PartDeflect *pd = eob->pd;
 
                        /* skip current object */
-                       if(rule->type == eBoidRuleType_Goal && eob == pa->stick_ob)
+                       if(rule->type == eBoidRuleType_Goal && eob == bpa->ground)
                                continue;
 
                        if(pd->forcefield == PFIELD_BOID && mul * pd->f_strength > 0.0f) {
@@ -169,10 +170,10 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
                                VECCOPY(bbd->goal_nor, nor);
                        }
                }
-               else if(rule->type == eBoidRuleType_Avoid && pa->boid->mode == eBoidMode_Climbing &&
+               else if(rule->type == eBoidRuleType_Avoid && bpa->data.mode == eBoidMode_Climbing &&
                        priority > 2.0f * gabr->fear_factor) {
                        /* detach from surface and try to fly away from danger */
-                       VECCOPY(vec_to_part, pa->r_ve);
+                       VECCOPY(vec_to_part, bpa->gravity);
                        VecMulf(vec_to_part, -1.0f);
                }
 
@@ -205,6 +206,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
        KDTreeNearest *ptn = NULL;
        ParticleEffectorCache *ec;
        ParticleTarget *pt;
+       BoidParticle *bpa = pa->boid;
        float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f};
        float co1[3], vel1[3], co2[3], vel2[3];
        float  len, t, inp, t_min = 2.0f;
@@ -231,7 +233,7 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues *
                                Object *eob = ec->ob;
 
                                /* don't check with current ground object */
-                               if(eob == pa->stick_ob)
+                               if(eob == bpa->ground)
                                        continue;
 
                                col.md = ( CollisionModifierData * ) ( modifiers_findByType ( eob, eModifierType_Collision ) );
@@ -558,18 +560,19 @@ static int rule_follow_leader(BoidRule *rule, BoidBrainData *bbd, BoidValues *va
 }
 static int rule_average_speed(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, ParticleData *pa)
 {
+       BoidParticle *bpa = pa->boid;
        BoidRuleAverageSpeed *asbr = (BoidRuleAverageSpeed*)rule;
        float vec[3] = {0.0f, 0.0f, 0.0f};
 
        if(asbr->wander > 0.0f) {
                /* abuse pa->r_ave for wandering */
-               pa->r_ave[0] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
-               pa->r_ave[1] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
-               pa->r_ave[2] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
+               bpa->wander[0] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
+               bpa->wander[1] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
+               bpa->wander[2] += asbr->wander * (-1.0f + 2.0f * BLI_frand());
 
-               Normalize(pa->r_ave);
+               Normalize(bpa->wander);
 
-               VECCOPY(vec, pa->r_ave);
+               VECCOPY(vec, bpa->wander);
 
                QuatMulVecf(pa->prev_state.rot, vec);
 
@@ -615,6 +618,7 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
        ParticleTarget *pt;
        ParticleData *epars;
        ParticleData *enemy_pa = NULL;
+       BoidParticle *bpa;
        /* friends & enemies */
        float closest_enemy[3] = {0.0f,0.0f,0.0f};
        float closest_dist = fbr->distance + 1.0f;
@@ -624,8 +628,10 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
 
        /* calculate own group strength */
        int neighbors = BLI_kdtree_range_search(bbd->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn);
-       for(n=0; n<neighbors; n++)
-               health += bbd->psys->particles[ptn[n].index].boid->health;
+       for(n=0; n<neighbors; n++) {
+               bpa = bbd->psys->particles[ptn[n].index].boid;
+               health += bpa->data.health;
+       }
 
        f_strength += bbd->part->boids->strength * health;
 
@@ -642,7 +648,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
                        health = 0.0f;
 
                        for(n=0; n<neighbors; n++) {
-                               health += epars[ptn[n].index].boid->health;
+                               bpa = epars[ptn[n].index].boid;
+                               health += bpa->data.health;
 
                                if(n==0 && pt->mode==PTARGET_MODE_ENEMY && ptn[n].dist < closest_dist) {
                                        VECCOPY(closest_enemy, ptn[n].co);
@@ -674,7 +681,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
 
                        /* must face enemy to fight */
                        if(Inpf(pa->prev_state.ave, enemy_dir)>0.5f) {
-                               enemy_pa->boid->health -= bbd->part->boids->strength * bbd->timestep * ((1.0f-bbd->part->boids->accuracy)*damage + bbd->part->boids->accuracy);
+                               bpa = enemy_pa->boid;
+                               bpa->data.health -= bbd->part->boids->strength * bbd->timestep * ((1.0f-bbd->part->boids->accuracy)*damage + bbd->part->boids->accuracy);
                        }
                }
                else {
@@ -683,7 +691,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti
                }
 
                /* check if boid doesn't want to fight */
-               if(pa->boid->health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) {
+               bpa = pa->boid;
+               if(bpa->data.health/bbd->part->boids->health * bbd->part->boids->aggression < e_strength / f_strength) {
                        /* decide to flee */
                        if(closest_dist < fbr->flee_distance * fbr->distance) {
                                VecMulf(bbd->wanted_co, -1.0f);
@@ -721,18 +730,20 @@ static boid_rule_cb boid_rules[] = {
 
 static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *pa)
 {
-       if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
-               val->max_speed = boids->land_max_speed * pa->boid->health/boids->health;
+       BoidParticle *bpa = pa->boid;
+
+       if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
+               val->max_speed = boids->land_max_speed * bpa->data.health/boids->health;
                val->max_acc = boids->land_max_acc * val->max_speed;
-               val->max_ave = boids->land_max_ave * M_PI * pa->boid->health/boids->health;
+               val->max_ave = boids->land_max_ave * M_PI * bpa->data.health/boids->health;
                val->min_speed = 0.0f; /* no minimum speed on land */
                val->personal_space = boids->land_personal_space;
-               val->jump_speed = boids->land_jump_speed * pa->boid->health/boids->health;
+               val->jump_speed = boids->land_jump_speed * bpa->data.health/boids->health;
        }
        else {
-               val->max_speed = boids->air_max_speed * pa->boid->health/boids->health;
+               val->max_speed = boids->air_max_speed * bpa->data.health/boids->health;
                val->max_acc = boids->air_max_acc * val->max_speed;
-               val->max_ave = boids->air_max_ave * M_PI * pa->boid->health/boids->health;
+               val->max_ave = boids->air_max_ave * M_PI * bpa->data.health/boids->health;
                val->min_speed = boids->air_min_speed * boids->air_max_speed;
                val->personal_space = boids->air_personal_space;
                val->jump_speed = 0.0f; /* no jumping in air */
@@ -740,11 +751,13 @@ static void set_boid_values(BoidValues *val, BoidSettings *boids, ParticleData *
 }
 static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *ground_co, float *ground_nor)
 {
-       if(pa->boid->mode == eBoidMode_Climbing) {
+       BoidParticle *bpa = pa->boid;
+
+       if(bpa->data.mode == eBoidMode_Climbing) {
                SurfaceModifierData *surmd = NULL;
                float x[3], v[3];
 
-               surmd = (SurfaceModifierData *)modifiers_findByType ( pa->stick_ob, eModifierType_Surface );
+               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);
@@ -753,7 +766,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
                /* get actual position on surface */
                effector_find_co(bbd->scene, x, surmd, NULL, NULL, ground_co, ground_nor, NULL, NULL);
 
-               return pa->stick_ob;
+               return bpa->ground;
        }
        else {
                float zvec[3] = {0.0f, 0.0f, 2000.0f};
@@ -803,13 +816,15 @@ static Object *boid_find_ground(BoidBrainData *bbd, ParticleData *pa, float *gro
 }
 static int boid_rule_applies(ParticleData *pa, BoidSettings *boids, BoidRule *rule)
 {
+       BoidParticle *bpa = pa->boid;
+
        if(rule==NULL)
                return 0;
        
-       if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing) && rule->flag & BOIDRULE_ON_LAND)
+       if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing) && rule->flag & BOIDRULE_ON_LAND)
                return 1;
        
-       if(pa->boid->mode==eBoidMode_InAir && rule->flag & BOIDRULE_IN_AIR)
+       if(bpa->data.mode==eBoidMode_InAir && rule->flag & BOIDRULE_IN_AIR)
                return 1;
 
        return 0;
@@ -835,12 +850,13 @@ void boids_precalc_rules(ParticleSettings *part, float cfra)
 }
 static void boid_climb(BoidSettings *boids, ParticleData *pa, float *surface_co, float *surface_nor)
 {
+       BoidParticle *bpa = pa->boid;
        float nor[3], vel[3];
        VECCOPY(nor, surface_nor);
 
-       /* gather apparent gravity to r_ve */
-       VECADDFAC(pa->r_ve, pa->r_ve, surface_nor, -1.0);
-       Normalize(pa->r_ve);
+       /* gather apparent gravity */
+       VECADDFAC(bpa->gravity, bpa->gravity, surface_nor, -1.0);
+       Normalize(bpa->gravity);
 
        /* raise boid it's size from surface */
        VecMulf(nor, pa->size * boids->height);
@@ -877,16 +893,17 @@ static int apply_boid_rule(BoidBrainData *bbd, BoidRule *rule, BoidValues *val,
 }
 static BoidState *get_boid_state(BoidSettings *boids, ParticleData *pa) {
        BoidState *state = boids->states.first;
+       BoidParticle *bpa = pa->boid;
 
        for(; state; state=state->next) {
-               if(state->id==pa->boid->state_id)
+               if(state->id==bpa->data.state_id)
                        return state;
        }
 
        /* for some reason particle isn't at a valid state */
        state = boids->states.first;
        if(state)
-               pa->boid->state_id = state->id;
+               bpa->data.state_id = state->id;
 
        return state;
 }
@@ -902,9 +919,11 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
        BoidSettings *boids = bbd->part->boids;
        BoidValues val;
        BoidState *state = get_boid_state(boids, pa);
+       BoidParticle *bpa = pa->boid;
+       int rand;
        //BoidCondition *cond;
 
-       if(pa->boid->health <= 0.0f) {
+       if(bpa->data.health <= 0.0f) {
                pa->alive = PARS_DYING;
                return;
        }
@@ -922,7 +941,9 @@ 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 + (int)bbd->cfra + (int)(1000*pa->r_rot[0]));
+       BLI_srandom(bbd->psys->seed + p);
+       rand = BLI_rand();
+       BLI_srandom((int)bbd->cfra + rand);
 
        set_boid_values(&val, bbd->part->boids, pa);
 
@@ -939,7 +960,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
                case eBoidRulesetType_Random:
                {
                        /* use random rule for each particle (allways same for same particle though) */
-                       rule = BLI_findlink(&state->rules, (int)(1000.0f * pa->r_rot[1]) % BLI_countlist(&state->rules));
+                       rule = BLI_findlink(&state->rules, rand % BLI_countlist(&state->rules));
 
                        apply_boid_rule(bbd, rule, &val, pa, -1.0);
                }
@@ -969,7 +990,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
        }
 
        /* decide on jumping & liftoff */
-       if(pa->boid->mode == eBoidMode_OnLand) {
+       if(bpa->data.mode == eBoidMode_OnLand) {
                /* fuzziness makes boids capable of misjudgement */
                float mul = 1.0 + state->rule_fuzziness;
                
@@ -983,7 +1004,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
                        Normalize2(cvel);
 
                        if(Inp2f(cvel, dir) > 0.95 / mul)
-                               pa->boid->mode = eBoidMode_Liftoff;
+                               bpa->data.mode = eBoidMode_Liftoff;
                }
                else if(val.jump_speed > 0.0f) {
                        float jump_v[3];
@@ -1036,7 +1057,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
 
                        if(jump) {
                                VECCOPY(pa->prev_state.vel, jump_v);
-                               pa->boid->mode = eBoidMode_Falling;
+                               bpa->data.mode = eBoidMode_Falling;
                        }
                }
        }
@@ -1045,6 +1066,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa)
 void boid_body(BoidBrainData *bbd, ParticleData *pa)
 {
        BoidSettings *boids = bbd->part->boids;
+       BoidParticle *bpa = pa->boid;
        BoidValues val;
        float acc[3] = {0.0f, 0.0f, 0.0f}, tan_acc[3], nor_acc[3];
        float dvec[3], bvec[3];
@@ -1066,10 +1088,10 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                pa_mass*=pa->size;
 
        /* if boids can't fly they fall to the ground */
-       if((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && bbd->part->acc[2] != 0.0f)
-               pa->boid->mode = eBoidMode_Falling;
+       if((boids->options & BOID_ALLOW_FLIGHT)==0 && ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)==0 && bbd->part->acc[2] != 0.0f)
+               bpa->data.mode = eBoidMode_Falling;
 
-       if(pa->boid->mode == eBoidMode_Falling) {
+       if(bpa->data.mode == eBoidMode_Falling) {
                /* Falling boids are only effected by gravity. */
                acc[2] = bbd->part->acc[2];
        }
@@ -1079,14 +1101,14 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                float level = landing_level + 1.0f;
                float new_vel[3];
 
-               if(pa->boid->mode == eBoidMode_Liftoff) {
-                       pa->boid->mode = eBoidMode_InAir;
-                       pa->stick_ob = boid_find_ground(bbd, pa, ground_co, ground_nor);
+               if(bpa->data.mode == eBoidMode_Liftoff) {
+                       bpa->data.mode = eBoidMode_InAir;
+                       bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
                }
-               else if(pa->boid->mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) {
+               else if(bpa->data.mode == eBoidMode_InAir && boids->options & BOID_ALLOW_LAND) {
                        /* auto-leveling & landing if close to ground */
 
-                       pa->stick_ob = boid_find_ground(bbd, pa, ground_co, ground_nor);
+                       bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
                        
                        /* level = how many particle sizes above ground */
                        level = (pa->prev_state.co[2] - ground_co[2])/(2.0f * pa->size) - 0.5;
@@ -1097,7 +1119,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                                if(level < 1.0f) {
                                        bbd->wanted_co[0] = bbd->wanted_co[1] = bbd->wanted_co[2] = 0.0f;
                                        bbd->wanted_speed = 0.0f;
-                                       pa->boid->mode = eBoidMode_Falling;
+                                       bpa->data.mode = eBoidMode_Falling;
                                }
                                else if(level < landing_level) {
                                        bbd->wanted_speed *= (level - 1.0f)/landing_level;
@@ -1188,7 +1210,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);
 
-       if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
+       if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
                float length = Normalize(force);
 
                length = MAX2(0.0f, length - boids->land_stick_force);
@@ -1199,8 +1221,8 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
        VecAddf(acc, acc, force);
 
        /* store smoothed acceleration for nice banking etc. */
-       VECADDFAC(pa->boid->acc, pa->boid->acc, acc, dtime);
-       VecMulf(pa->boid->acc, 1.0f / (1.0f + dtime));
+       VECADDFAC(bpa->data.acc, bpa->data.acc, acc, dtime);
+       VecMulf(bpa->data.acc, 1.0f / (1.0f + dtime));
 
        /* integrate new location & velocity */
 
@@ -1218,32 +1240,32 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
 
        VECADDFAC(pa->state.vel, pa->state.vel, acc, dtime);
 
-       if(pa->boid->mode != eBoidMode_InAir)
-               pa->stick_ob = boid_find_ground(bbd, pa, ground_co, ground_nor);
+       if(bpa->data.mode != eBoidMode_InAir)
+               bpa->ground = boid_find_ground(bbd, pa, ground_co, ground_nor);
 
        /* change modes, constrain movement & keep track of down vector */
-       switch(pa->boid->mode) {
+       switch(bpa->data.mode) {
                case eBoidMode_InAir:
                {
                        float grav[3] = {0.0f, 0.0f, bbd->part->acc[2] < 0.0f ? -1.0f : 0.0f};
 
                        /* don't take forward acceleration into account (better banking) */
-                       if(Inpf(pa->boid->acc, pa->state.vel) > 0.0f) {
-                               Projf(dvec, pa->boid->acc, pa->state.vel);
-                               VecSubf(dvec, pa->boid->acc, dvec);
+                       if(Inpf(bpa->data.acc, pa->state.vel) > 0.0f) {
+                               Projf(dvec, bpa->data.acc, pa->state.vel);
+                               VecSubf(dvec, bpa->data.acc, dvec);
                        }
                        else {
-                               VECCOPY(dvec, pa->boid->acc);
+                               VECCOPY(dvec, bpa->data.acc);
                        }
 
-                       /* gather apparent gravity to r_ve */
-                       VECADDFAC(pa->r_ve, grav, dvec, -boids->banking);
-                       Normalize(pa->r_ve);
+                       /* gather apparent gravity */
+                       VECADDFAC(bpa->gravity, grav, dvec, -boids->banking);
+                       Normalize(bpa->gravity);
 
                        /* stick boid on goal when close enough */
                        if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
-                               pa->boid->mode = eBoidMode_Climbing;
-                               pa->stick_ob = bbd->goal_ob;
+                               bpa->data.mode = eBoidMode_Climbing;
+                               bpa->ground = bbd->goal_ob;
                                boid_find_ground(bbd, pa, ground_co, ground_nor);
                                boid_climb(boids, pa, ground_co, ground_nor);
                        }
@@ -1251,7 +1273,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                        else if(boids->options & BOID_ALLOW_LAND && pa->state.co[2] <= ground_co[2] + pa->size * boids->height) {
                                pa->state.co[2] = ground_co[2] + pa->size * boids->height;
                                pa->state.vel[2] = 0.0f;
-                               pa->boid->mode = eBoidMode_OnLand;
+                               bpa->data.mode = eBoidMode_OnLand;
                        }
                        break;
                }
@@ -1259,15 +1281,15 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                {
                        float grav[3] = {0.0f, 0.0f, bbd->part->acc[2] < 0.0f ? -1.0f : 0.0f};
 
-                       /* gather apparent gravity to r_ve */
-                       VECADDFAC(pa->r_ve, pa->r_ve, grav, dtime);
-                       Normalize(pa->r_ve);
+                       /* gather apparent gravity */
+                       VECADDFAC(bpa->gravity, bpa->gravity, grav, dtime);
+                       Normalize(bpa->gravity);
 
                        if(boids->options & BOID_ALLOW_LAND) {
                                /* stick boid on goal when close enough */
                                if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
-                                       pa->boid->mode = eBoidMode_Climbing;
-                                       pa->stick_ob = bbd->goal_ob;
+                                       bpa->data.mode = eBoidMode_Climbing;
+                                       bpa->ground = bbd->goal_ob;
                                        boid_find_ground(bbd, pa, ground_co, ground_nor);
                                        boid_climb(boids, pa, ground_co, ground_nor);
                                }
@@ -1275,14 +1297,14 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                                else if(pa->state.co[2] <= ground_co[2] + 1.01 * pa->size * boids->height){
                                        pa->state.co[2] = ground_co[2] + pa->size * boids->height;
                                        pa->state.vel[2] = 0.0f;
-                                       pa->boid->mode = eBoidMode_OnLand;
+                                       bpa->data.mode = eBoidMode_OnLand;
                                }
                                /* if we're falling, can fly and want to go upwards lets fly */
                                else if(boids->options & BOID_ALLOW_FLIGHT && bbd->wanted_co[2] > 0.0f)
-                                       pa->boid->mode = eBoidMode_InAir;
+                                       bpa->data.mode = eBoidMode_InAir;
                        }
                        else
-                               pa->boid->mode = eBoidMode_InAir;
+                               bpa->data.mode = eBoidMode_InAir;
                        break;
                }
                case eBoidMode_Climbing:
@@ -1308,14 +1330,14 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                {
                        /* stick boid on goal when close enough */
                        if(bbd->goal_ob && boid_goal_signed_dist(pa->state.co, bbd->goal_co, bbd->goal_nor) <= pa->size * boids->height) {
-                               pa->boid->mode = eBoidMode_Climbing;
-                               pa->stick_ob = bbd->goal_ob;
+                               bpa->data.mode = eBoidMode_Climbing;
+                               bpa->ground = bbd->goal_ob;
                                boid_find_ground(bbd, pa, ground_co, ground_nor);
                                boid_climb(boids, pa, ground_co, ground_nor);
                        }
                        /* ground is too far away so boid falls */
                        else if(pa->state.co[2]-ground_co[2] > 1.1 * pa->size * boids->height)
-                               pa->boid->mode = eBoidMode_Falling;
+                               bpa->data.mode = eBoidMode_Falling;
                        else {
                                /* constrain to surface */
                                pa->state.co[2] = ground_co[2] + pa->size * boids->height;
@@ -1329,17 +1351,17 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
                                VECCOPY(grav, ground_nor);
                                VecMulf(grav, -1.0f);
                                
-                               Projf(dvec, pa->boid->acc, pa->state.vel);
-                               VecSubf(dvec, pa->boid->acc, dvec);
+                               Projf(dvec, bpa->data.acc, pa->state.vel);
+                               VecSubf(dvec, bpa->data.acc, dvec);
 
-                               /* gather apparent gravity to r_ve */
-                               VECADDFAC(pa->r_ve, grav, dvec, -boids->banking);
-                               Normalize(pa->r_ve);
+                               /* gather apparent gravity */
+                               VECADDFAC(bpa->gravity, grav, dvec, -boids->banking);
+                               Normalize(bpa->gravity);
                        }
                        else {
-                               /* gather negative surface normal to r_ve */
-                               VECADDFAC(pa->r_ve, pa->r_ve, ground_nor, -1.0f);
-                               Normalize(pa->r_ve);
+                               /* gather negative surface normal */
+                               VECADDFAC(bpa->gravity, bpa->gravity, ground_nor, -1.0f);
+                               Normalize(bpa->gravity);
                        }
                        break;
                }
@@ -1347,29 +1369,29 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
 
        /* save direction to state.ave unless the boid is falling */
        /* (boids can't effect their direction when falling) */
-       if(pa->boid->mode!=eBoidMode_Falling && VecLength(pa->state.vel) > 0.1*pa->size) {
+       if(bpa->data.mode!=eBoidMode_Falling && VecLength(pa->state.vel) > 0.1*pa->size) {
                VECCOPY(pa->state.ave, pa->state.vel);
                Normalize(pa->state.ave);
        }
 
        /* apply damping */
-       if(ELEM(pa->boid->mode, eBoidMode_OnLand, eBoidMode_Climbing))
+       if(ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing))
                VecMulf(pa->state.vel, 1.0f - 0.2f*bbd->part->dampfac);
 
        /* calculate rotation matrix based on forward & down vectors */
-       if(pa->boid->mode == eBoidMode_InAir) {
+       if(bpa->data.mode == eBoidMode_InAir) {
                VECCOPY(mat[0], pa->state.ave);
 
-               Projf(dvec, pa->r_ve, pa->state.ave);
-               VecSubf(mat[2], pa->r_ve, dvec);
+               Projf(dvec, bpa->gravity, pa->state.ave);
+               VecSubf(mat[2], bpa->gravity, dvec);
                Normalize(mat[2]);
        }
        else {
-               Projf(dvec, pa->state.ave, pa->r_ve);
+               Projf(dvec, pa->state.ave, bpa->gravity);
                VecSubf(mat[0], pa->state.ave, dvec);
                Normalize(mat[0]);
 
-               VECCOPY(mat[2], pa->r_ve);
+               VECCOPY(mat[2], bpa->gravity);
        }
        VecMulf(mat[2], -1.0f);
        Crossf(mat[1], mat[2], mat[0]);
index eafd9eb01feb1e792c748925fb40404bec6b775f..8be8df8e63b165f7629c1a0646af59388d13cc94 100644 (file)
@@ -496,23 +496,30 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        if(!do_init_cloth(ob, clmd, result, framenr))
                return result;
 
+       if(framenr == startframe && cache->flag & PTCACHE_REDO_NEEDED) {
+               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+               cache->simframe= framenr;
+               cache->flag &= ~PTCACHE_REDO_NEEDED;
+               return result;
+       }
+
        /* try to read from cache */
        cache_result = BKE_ptcache_read_cache(&pid, (float)framenr, scene->r.frs_sec);
 
        if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
-               cache->flag |= PTCACHE_SIMULATION_VALID;
-               cache->simframe= framenr;
-
                implicit_set_positions(clmd);
                cloth_to_object (ob, clmd, result);
 
+               cache->simframe= framenr;
+               cache->flag |= PTCACHE_SIMULATION_VALID;
+
+               if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+                       BKE_ptcache_write_cache(&pid, framenr);
+
                return result;
        }
        else if(cache_result==PTCACHE_READ_OLD) {
-               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
-
                implicit_set_positions(clmd);
-
                cache->flag |= PTCACHE_SIMULATION_VALID;
        }
        else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
@@ -524,12 +531,10 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
        }
 
        if(framenr == startframe) {
-               if(cache->flag & PTCACHE_REDO_NEEDED) {
-                       BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
-                       do_init_cloth(ob, clmd, result, framenr);
-               }
-               cache->flag |= PTCACHE_SIMULATION_VALID;
+               implicit_set_positions(clmd);
+
                cache->simframe= framenr;
+               cache->flag |= PTCACHE_SIMULATION_VALID;
 
                /* don't write cache on first frame, but on second frame write
                 * cache for frame 1 and 2 */
index 7a0eb882083a0559efbf9ee7443bddb702fe7165..9c8c43cc8cbc584364abcf2a0ab6b121fbd049dc 100644 (file)
@@ -6696,10 +6696,8 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
                if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
                        float ran = 0.0f;
                        if(pimd->random_position != 0.0f) {
-                               /* just use some static collection of random numbers */
-                               /* TODO: use something else that's unique to each instanced object */
-                               pa = psys->particles + (i/totvert)%totpart;
-                               ran = pimd->random_position * 0.5 * (1.0f + pa->r_ave[0]);
+                               BLI_srandom(psys->seed + (i/totvert)%totpart);
+                               ran = pimd->random_position * BLI_frand();
                        }
 
                        if(pimd->flag & eParticleInstanceFlag_KeepShape) {
index 1cb0abfe21cfa028461ef8ef2717166cac14d1d8..9a137bdb7e6e3bec970e3a0de51d3d812427ef64 100644 (file)
@@ -481,15 +481,15 @@ void unlink_object(Scene *scene, Object *ob)
                                if(tpsys->part->dup_ob==ob)
                                        tpsys->part->dup_ob= NULL;
 
-                               if(tpsys->part->flag&PART_STICKY) {
+                               if(tpsys->part->phystype==PART_PHYS_BOIDS) {
                                        ParticleData *pa;
+                                       BoidParticle *bpa;
                                        int p;
 
                                        for(p=0,pa=tpsys->particles; p<tpsys->totpart; p++,pa++) {
-                                               if(pa->stick_ob==ob) {
-                                                       pa->stick_ob= 0;
-                                                       pa->flag &= ~PARS_STICKY;
-                                               }
+                                               bpa = pa->boid;
+                                               if(bpa->ground == ob)
+                                                       bpa->ground = NULL;
                                        }
                                }
                                if(tpsys->part->boids) {
@@ -1082,19 +1082,35 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
 {
        ParticleSystem *psysn;
        ParticleData *pa;
-       int a;
+       int p;
 
        psysn= MEM_dupallocN(psys);
        psysn->particles= MEM_dupallocN(psys->particles);
        psysn->child= MEM_dupallocN(psys->child);
-       if(psysn->particles->keys)
-               psysn->particles->keys = MEM_dupallocN(psys->particles->keys);
 
-       for(a=0, pa=psysn->particles; a<psysn->totpart; a++, pa++) {
-               if(pa->hair)
-                       pa->hair= MEM_dupallocN(pa->hair);
-               if(a)
-                       pa->keys= (pa-1)->keys + (pa-1)->totkey;
+       if(psys->part->type == PART_HAIR) {
+               for(p=0, pa=psysn->particles; p<psysn->totpart; p++, pa++)
+                       pa->hair = MEM_dupallocN(pa->hair);
+       }
+
+       if(psysn->particles->keys || psysn->particles->boid) {
+               ParticleKey *key = psysn->particles->keys;
+               BoidParticle *boid = psysn->particles->boid;
+
+               if(key)
+                       key = MEM_dupallocN(key);
+               
+               if(boid)
+                       boid = MEM_dupallocN(boid);
+               
+               for(p=0, pa=psysn->particles; p<psysn->totpart; p++, pa++) {
+                       if(boid)
+                               pa->boid = boid++;
+                       if(key) {
+                               pa->keys = key;
+                               key += pa->totkey;
+                       }
+               }
        }
 
        if(psys->soft) {
@@ -1102,14 +1118,7 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
                psysn->soft->particles = psysn;
        }
 
-       if(psys->particles->boid) {
-               psysn->particles->boid = MEM_dupallocN(psys->particles->boid);
-               for(a=1, pa=psysn->particles+1; a<psysn->totpart; a++, pa++)
-                       pa->boid = (pa-1)->boid + 1;
-       }
-
-       if(psys->targets.first)
-               BLI_duplicatelist(&psysn->targets, &psys->targets);
+       BLI_duplicatelist(&psysn->targets, &psys->targets);
        
        psysn->pathcache= NULL;
        psysn->childcache= NULL;
index 1ae3ec5dd5047443bd8fa9a01e93365712f48db0..81eb0b79c400d8e086d18313610b1148db3376ad 100644 (file)
@@ -92,10 +92,10 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P
 /* few helpers for countall etc. */
 int count_particles(ParticleSystem *psys){
        ParticleSettings *part=psys->part;
-       ParticleData *pa;
-       int tot=0,p;
+       PARTICLE_P;
+       int tot=0;
 
-       for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){
+       LOOP_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);
@@ -106,10 +106,10 @@ int count_particles(ParticleSystem *psys){
 }
 int count_particles_mod(ParticleSystem *psys, int totgr, int cur){
        ParticleSettings *part=psys->part;
-       ParticleData *pa;
-       int tot=0,p;
+       PARTICLE_P;
+       int tot=0;
 
-       for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){
+       LOOP_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);
@@ -120,10 +120,10 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){
 }
 int psys_count_keys(ParticleSystem *psys)
 {
-       ParticleData *pa;
-       int i, totpart=psys->totpart, totkey=0;
+       PARTICLE_P;
+       int totkey=0;
 
-       for(i=0, pa=psys->particles; i<totpart; i++, pa++)
+       LOOP_PARTICLES
                totkey += pa->totkey;
 
        return totkey;
@@ -368,13 +368,16 @@ void psys_free_settings(ParticleSettings *part)
 
 void free_hair(ParticleSystem *psys, int softbody)
 {
-       ParticleData *pa;
-       int i, totpart=psys->totpart;
+       PARTICLE_P;
+
+       if(psys->part->type != PART_HAIR)
+               return;
 
-       for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
+       LOOP_PARTICLES {
                if(pa->hair)
                        MEM_freeN(pa->hair);
                pa->hair = NULL;
+               pa->totkey = 0;
        }
 
        psys->flag &= ~PSYS_HAIR_DONE;
@@ -386,13 +389,15 @@ void free_hair(ParticleSystem *psys, int softbody)
 }
 void free_keyed_keys(ParticleSystem *psys)
 {
-       ParticleData *pa;
-       int i;
+       PARTICLE_P;
+
+       if(psys->part->type == PART_HAIR)
+               return;
 
        if(psys->particles && psys->particles->keys) {
                MEM_freeN(psys->particles->keys);
 
-               for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) {
+               LOOP_PARTICLES {
                        if(pa->keys) {
                                pa->keys= NULL;
                                pa->totkey= 0;
@@ -431,6 +436,29 @@ void psys_free_children(ParticleSystem *psys)
 
        free_child_path_cache(psys);
 }
+void psys_free_particles(ParticleSystem *psys)
+{
+       PARTICLE_P;
+
+       if(psys->particles) {
+               if(psys->part->type==PART_HAIR) {
+                       LOOP_PARTICLES {
+                               if(pa->hair)
+                                       MEM_freeN(pa->hair);
+                       }
+               }
+               
+               if(psys->particles->keys)
+                       MEM_freeN(psys->particles->keys);
+               
+               if(psys->particles->boid)
+                       MEM_freeN(psys->particles->boid);
+
+               MEM_freeN(psys->particles);
+               psys->particles= NULL;
+               psys->totpart= 0;
+       }
+}
 /* free everything */
 void psys_free(Object *ob, ParticleSystem * psys)
 {      
@@ -440,22 +468,11 @@ void psys_free(Object *ob, ParticleSystem * psys)
                
                psys_free_path_cache(psys, NULL);
 
-               free_hair(psys, 1);
-
-               free_keyed_keys(psys);
+               psys_free_particles(psys);
 
                if(psys->edit && psys->free_edit)
                        psys->free_edit(psys->edit);
 
-               if(psys->particles){
-                       if(psys->particles->boid)
-                               MEM_freeN(psys->particles->boid);
-
-                       MEM_freeN(psys->particles);
-                       psys->particles = 0;
-                       psys->totpart = 0;
-               }
-
                if(psys->child){
                        MEM_freeN(psys->child);
                        psys->child = 0;
@@ -485,14 +502,11 @@ void psys_free(Object *ob, ParticleSystem * psys)
                        psys->part=0;
                }
 
-               if(psys->reactevents.first)
-                       BLI_freelistN(&psys->reactevents);
-
                BKE_ptcache_free_list(&psys->ptcaches);
                psys->pointcache = NULL;
                
-               if(psys->targets.first)
-                       BLI_freelistN(&psys->targets);
+               BLI_freelistN(&psys->targets);
+               BLI_freelistN(&psys->reactevents);
 
                BLI_kdtree_free(psys->tree);
 
@@ -1015,11 +1029,12 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic
                pind->dietime = *((point->keys + point->totkey - 1)->time);
        }
        else if(pind->keyed) {
-               pind->kkey[0] = pa->keys;
-               pind->kkey[1] = pa->totkey > 1 ? pa->keys + 1 : NULL;
+               ParticleKey *key = pa->keys;
+               pind->kkey[0] = key;
+               pind->kkey[1] = pa->totkey > 1 ? key + 1 : NULL;
 
-               pind->birthtime = pa->keys->time;
-               pind->dietime = (pa->keys + pa->totkey - 1)->time;
+               pind->birthtime = key->time;
+               pind->dietime = (key + pa->totkey - 1)->time;
        }
        else if(pind->cache) {
                get_pointcache_keys_for_time(ob, pind->cache, -1, 0.0f, NULL, NULL);
@@ -1028,17 +1043,18 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic
                pind->dietime = pa ? pa->dietime : pind->cache->endframe;
        }
        else {
-               pind->hkey[0] = pa->hair;
-               pind->hkey[1] = pa->hair + 1;
+               HairKey *key = pa->hair;
+               pind->hkey[0] = key;
+               pind->hkey[1] = key + 1;
 
-               pind->birthtime = pa->hair->time;
-               pind->dietime = (pa->hair + pa->totkey - 1)->time;
+               pind->birthtime = key->time;
+               pind->dietime = (key + pa->totkey - 1)->time;
        }
 
-       if(pind->soft) {
-               pind->bp[0] = pind->soft->bpoint + pa->bpi;
-               pind->bp[1] = pind->soft->bpoint + pa->bpi + 1;
-       }
+       //if(pind->soft) {
+       //      pind->bp[0] = pind->soft->bpoint + pa->bpi;
+       //      pind->bp[1] = pind->soft->bpoint + pa->bpi + 1;
+       //}
 }
 static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey)
 {
@@ -2558,6 +2574,9 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa
        ListBase threads;
        int i, totchild, totparent, totthread;
 
+       if(psys->flag & PSYS_GLOBAL_HAIR)
+               return;
+
        pthreads= psys_threads_create(scene, ob, psys);
 
        if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) {
@@ -2688,7 +2707,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
                }
 
                if(!psys->totchild) {
-                       pa_length = 1.0f - part->randlength * 0.5 * (1.0f + pa->r_ave[0]);
+                       BLI_srandom(psys->seed + i);
+                       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);
                }
@@ -2740,7 +2760,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
                        do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
 
                         /* keyed, baked and softbody are allready in global space */
-                       if(!keyed && !baked && !soft) {
+                       if(!keyed && !baked && !soft && !(psys->flag & PSYS_GLOBAL_HAIR)) {
                                Mat4MulVecfl(hairmat, result.co);
                        }
 
@@ -3574,6 +3594,8 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd,
 {
        ParticleTexture ptex;
        float size=1.0f;
+
+       BLI_srandom(psys->seed + (pa - psys->particles) + 100);
        
        if(ma && part->from!=PART_FROM_PARTICLE){
                ptex.size=size;
@@ -3592,7 +3614,7 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd,
                size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size);
 
        if(part->randsize!=0.0)
-               size*= 1.0f - part->randsize*pa->sizemul;
+               size*= 1.0f - part->randsize * BLI_frand();
 
        return size*part->size;
 }
@@ -3759,13 +3781,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
 
        if(p<totpart){
                pa = psys->particles + p;
-
-               if(pa->alive==PARS_DEAD && part->flag & PART_STICKY && pa->flag & PARS_STICKY && pa->stick_ob){
-                       copy_particle_key(state,&pa->state,0);
-                       key_from_object(pa->stick_ob,state);
-                       return;
-               }
-
                pind.keyed = keyed;
                pind.cache = cached ? psys->pointcache : NULL;
                pind.soft = NULL;
@@ -3981,20 +3996,11 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
                        return 0; /* currently not supported */
                else if(psys->totchild && p>=psys->totpart){
                        ChildParticle *cpa=psys->child+p-psys->totpart;
-                       ParticleKey *key1, skey;
+                       ParticleKey *key1;
                        float t = (cfra - pa->time + pa->loop * pa->lifetime) / pa->lifetime;
 
                        pa = psys->particles + cpa->parent;
-
-                       if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob) {
-                               key1 = &skey;
-                               copy_particle_key(key1,&pa->state,0);
-                               key_from_object(pa->stick_ob,key1);
-                       }
-                       else {
-                               key1=&pa->state;
-                       }
-                       
+                       key1=&pa->state;
                        offset_child(cpa, key1, state, part->childflat, part->childrad);
                        
                        CLAMP(t,0.0,1.0);
@@ -4051,10 +4057,6 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
                                }
                        }
 
-                       if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){
-                               key_from_object(pa->stick_ob,state);
-                       }
-
                        if(psys->lattice)
                                calc_latt_deform(psys->lattice, state->co,1.0f);
                }
index 0f72c1c5866b45ee2054be2a7e29f1386a20ad35..eb570ba287c187e3ed0a8c1d2d10fe05ff302eb2 100644 (file)
@@ -123,21 +123,11 @@ static int get_current_display_percentage(ParticleSystem *psys)
 void psys_reset(ParticleSystem *psys, int mode)
 {
        ParticleSettings *part= psys->part;
-       ParticleData *pa;
-       int i;
+       PARTICLE_P;
 
        if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) {
                if(mode == PSYS_RESET_ALL || !(part->type == PART_HAIR && (psys->edit && psys->edit->edited))) {
-                       if(psys->particles) {
-                               if(psys->particles->keys)
-                                       MEM_freeN(psys->particles->keys);
-
-                               for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++)
-                                       if(pa->hair) MEM_freeN(pa->hair);
-
-                               MEM_freeN(psys->particles);
-                               psys->particles= NULL;
-                       }
+                       psys_free_particles(psys);
 
                        psys->totpart= 0;
                        psys->totkeyed= 0;
@@ -155,10 +145,7 @@ void psys_reset(ParticleSystem *psys, int mode)
        }
        else if(mode == PSYS_RESET_CACHE_MISS) {
                /* set all particles to be skipped */
-               ParticleData *pa = psys->particles;
-               int p=0;
-
-               for(; p<psys->totpart; p++, pa++)
+               LOOP_PARTICLES
                        pa->flag |= PARS_NO_DISP;
        }
 
@@ -180,9 +167,10 @@ void psys_reset(ParticleSystem *psys, int mode)
 
 static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
 {
-       ParticleData *newpars = 0, *pa;
-       BoidData *newboids = 0;
-       int i, totpart, totsaved = 0;
+       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) {
@@ -195,47 +183,46 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
        else
                totpart=new_totpart;
 
-       if(totpart) {
+       if(totpart && totpart != psys->totpart) {
                newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles");
+       
+               if(psys->particles) {
+                       totsaved=MIN2(psys->totpart,totpart);
+                       /*save old pars*/
+                       if(totsaved) {
+                               memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData));
+
+                               if(psys->particles->boid)
+                                       memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidParticle));
+                       }
 
-               if(psys->part->phystype == PART_PHYS_BOIDS)
-                       newboids = MEM_callocN(totpart*sizeof(BoidData), "Boid Data");
-       }
-       if(psys->particles) {
-               totsaved=MIN2(psys->totpart,totpart);
-               /*save old pars*/
-               if(totsaved) {
-                       memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData));
-
-                       if(newboids)
-                               memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidData));
-               }
-
-               if(psys->particles->keys)
-                       MEM_freeN(psys->particles->keys);
+                       if(psys->particles->keys)
+                               MEM_freeN(psys->particles->keys);
 
-               if(psys->particles->boid)
-                       MEM_freeN(psys->particles->boid);
+                       if(psys->particles->boid)
+                               MEM_freeN(psys->particles->boid);
 
-               for(i=0, pa=newpars; i<totsaved; i++, pa++) {
-                       if(pa->keys) {
-                               pa->keys= NULL;
-                               pa->totkey= 0;
+                       for(p=0, pa=newpars; p<totsaved; p++, pa++) {
+                               if(pa->keys) {
+                                       pa->keys= NULL;
+                                       pa->totkey= 0;
+                               }
                        }
-               }
 
-               for(i=totsaved, pa=psys->particles+totsaved; i<psys->totpart; i++, pa++)
-                       if(pa->hair) MEM_freeN(pa->hair);
+                       for(p=totsaved, pa=psys->particles+totsaved; p<psys->totpart; p++, pa++)
+                               if(pa->hair) MEM_freeN(pa->hair);
 
-               MEM_freeN(psys->particles);
-       }
-       psys->particles=newpars;
+                       MEM_freeN(psys->particles);
+               }
+               
+               psys->particles=newpars;
 
-       if(newboids) {
-               pa = psys->particles;
-               pa->boid = newboids;
-               for(i=1, pa++; i<totpart; i++,pa++)
-                       pa->boid = (pa-1)->boid + 1;
+               if(newboids) {
+                       LOOP_PARTICLES
+                               pa->boid = newboids++;
+               }
+               
+               psys->totpart=totpart;
        }
 
        if(psys->child) {
@@ -243,8 +230,6 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
                psys->child=0;
                psys->totchild=0;
        }
-
-       psys->totpart=totpart;
 }
 
 static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys)
@@ -291,8 +276,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                      each original elements can reference its derived elements
        */
        Mesh *me= (Mesh*)ob->data;
-       ParticleData *pa= 0;
-       int p;
+       PARTICLE_P;
        
        /* CACHE LOCATIONS */
        if(!dm->deformedOnly) {
@@ -329,7 +313,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                }
                
                /* cache the verts/faces! */
-               for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++) {
+               LOOP_PARTICLES {
                        if(psys->part->from == PART_FROM_VERT) {
                                if(nodearray[pa->num])
                                        pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link);
@@ -349,7 +333,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
                 * should know to use the num or num_dmcache, set the num_dmcache to
                 * an invalid value, just incase */
                
-               for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++)
+               LOOP_PARTICLES
                        pa->num_dmcache = -1;
        }
 }
@@ -1449,12 +1433,11 @@ 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)
 {
-       ParticleData *pa;
-       int totpart=psys->totpart, p;
+       PARTICLE_P;
 
        fprintf(stderr,"Shape emission not yet possible!\n");
 
-       for(p=0,pa=psys->particles; p<totpart; p++,pa++){
+       LOOP_PARTICLES {
                pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0;
                pa->foffset= 0.0f;
                pa->num= -1;
@@ -1476,12 +1459,11 @@ static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys,
                distribute_particles_on_shape(ob,psys,from);
 
        if(distr_error){
-               ParticleData *pa;
-               int totpart=psys->totpart, p;
+               PARTICLE_P;
 
                fprintf(stderr,"Particle distribution error!\n");
 
-               for(p=0,pa=psys->particles; p<totpart; p++,pa++){
+               LOOP_PARTICLES {
                        pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0;
                        pa->foffset= 0.0f;
                        pa->num= -1;
@@ -1576,7 +1558,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
        Material *ma=0;
        //IpoCurve *icu=0; // XXX old animation system
        int totpart;
-       float rand,length;
+       float rand;
 
        part=psys->part;
 
@@ -1631,40 +1613,8 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
 
        pa->dietime= pa->time+pa->lifetime;
 
-       pa->sizemul= BLI_frand();
-
-       rand= BLI_frand();
-
-       /* while loops are to have a spherical distribution (avoid cubic distribution) */
-       if(part->phystype != PART_PHYS_BOIDS) {
-               /* boids store gravity in r_ve, so skip here */
-               length=2.0f;
-               while(length>1.0){
-                       pa->r_ve[0]=2.0f*(BLI_frand()-0.5f);
-                       pa->r_ve[1]=2.0f*(BLI_frand()-0.5f);
-                       pa->r_ve[2]=2.0f*(BLI_frand()-0.5f);
-                       length=VecLength(pa->r_ve);
-               }
-       }
-
-       length=2.0f;
-       while(length>1.0){
-               pa->r_ave[0]=2.0f*(BLI_frand()-0.5f);
-               pa->r_ave[1]=2.0f*(BLI_frand()-0.5f);
-               pa->r_ave[2]=2.0f*(BLI_frand()-0.5f);
-               length=VecLength(pa->r_ave);
-       }
-
-       pa->r_rot[0]=2.0f*(BLI_frand()-0.5f);
-       pa->r_rot[1]=2.0f*(BLI_frand()-0.5f);
-       pa->r_rot[2]=2.0f*(BLI_frand()-0.5f);
-       pa->r_rot[3]=2.0f*(BLI_frand()-0.5f);
-
-       NormalQuat(pa->r_rot);
-
        if(part->type!=PART_HAIR && part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){
-               /* any unique random number will do (r_ave[0]) */
-               if(ptex.exist < 0.5*(1.0+pa->r_ave[0]))
+               if(ptex.exist < BLI_frand())
                        pa->flag |= PARS_UNEXIST;
                else
                        pa->flag &= ~PARS_UNEXIST;
@@ -1678,10 +1628,9 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
 static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd)
 {
        //IpoCurve *icu=0; // XXX old animation system
-       ParticleData *pa;
-       int p, totpart=psys->totpart;
+       PARTICLE_P;
 
-       for(p=0, pa=psys->particles; p<totpart; p++, pa++)
+       LOOP_PARTICLES
                initialize_particle(pa,p,ob,psys,psmd);
        
        if(psys->part->type != PART_FLUID) {
@@ -1749,10 +1698,39 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic
        float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4];
        float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
        float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
-       float q_phase[4];
+       float q_phase[4], length, r_phase;
        part=psys->part;
 
        ptex.ivel=1.0;
+
+       BLI_srandom(psys->seed + (pa - psys->particles));
+
+       /* we need to get every random even if they're not used so that they don't effect eachother */
+       /* while loops are to have a spherical distribution (avoid cubic distribution) */
+       length=2.0f;
+       while(length>1.0){
+               r_vel[0]=2.0f*(BLI_frand()-0.5f);
+               r_vel[1]=2.0f*(BLI_frand()-0.5f);
+               r_vel[2]=2.0f*(BLI_frand()-0.5f);
+               length=VecLength(r_vel);
+       }
+
+       length=2.0f;
+       while(length>1.0){
+               r_ave[0]=2.0f*(BLI_frand()-0.5f);
+               r_ave[1]=2.0f*(BLI_frand()-0.5f);
+               r_ave[2]=2.0f*(BLI_frand()-0.5f);
+               length=VecLength(r_ave);
+       }
+
+       r_rot[0]=2.0f*(BLI_frand()-0.5f);
+       r_rot[1]=2.0f*(BLI_frand()-0.5f);
+       r_rot[2]=2.0f*(BLI_frand()-0.5f);
+       r_rot[3]=2.0f*(BLI_frand()-0.5f);
+
+       NormalQuat(r_rot);
+
+       r_phase = BLI_frand();
        
        if(part->from==PART_FROM_PARTICLE){
                Object *tob;
@@ -1763,29 +1741,26 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic
                if(tob==0)
                        tob=ob;
 
-               tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1);
+               tpsys=BLI_findlink(&tob->particlesystem, psys->target_psys-1);
 
                state.time = pa->time;
                if(pa->num == -1)
                        memset(&state, 0, sizeof(state));
                else
                        psys_get_particle_state(scene, tob,tpsys,pa->num,&state,1);
-               psys_get_from_key(&state,loc,nor,rot,0);
+               psys_get_from_key(&state, loc, nor, rot, 0);
 
-               QuatMulVecf(rot,vtan);
-               QuatMulVecf(rot,utan);
-               VECCOPY(r_vel,pa->r_ve);
-               VECCOPY(r_rot,pa->r_rot);
-               VECCOPY(r_ave,pa->r_ave);
+               QuatMulVecf(rot, vtan);
+               QuatMulVecf(rot, utan);
 
-               VECCOPY(p_vel,state.vel);
+               VECCOPY(p_vel, state.vel);
                speed=Normalize(p_vel);
-               VecMulf(p_vel,Inpf(pa->r_ve,p_vel));
-               VECSUB(p_vel,pa->r_ve,p_vel);
+               VecMulf(p_vel, Inpf(r_vel, p_vel));
+               VECSUB(p_vel, r_vel, p_vel);
                Normalize(p_vel);
-               VecMulf(p_vel,speed);
+               VecMulf(p_vel, speed);
 
-               VECCOPY(pa->fuv,loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */
+               VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */
        }
        else{
                /* get precise emitter matrix if particle is born */
@@ -1839,29 +1814,25 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic
 
                /* -velocity                                                    */
                if(part->randfac!=0.0){
-                       VECADD(r_vel,tloc,pa->r_ve);
-                       Mat4MulVecfl(ob->obmat,r_vel);
-                       VECSUB(r_vel,r_vel,loc);
+                       Mat4Mul3Vecfl(ob->obmat,r_vel);
                        Normalize(r_vel);
                }
 
                /* -angular velocity                                    */
                if(part->avemode==PART_AVE_RAND){
-                       VECADD(r_ave,tloc,pa->r_ave);
-                       Mat4MulVecfl(ob->obmat,r_ave);
-                       VECSUB(r_ave,r_ave,loc);
+                       Mat4Mul3Vecfl(ob->obmat,r_ave);
                        Normalize(r_ave);
                }
                
                /* -rotation                                                    */
                if(part->randrotfac != 0.0f){
-                       QUATCOPY(r_rot,pa->r_rot);
                        Mat4ToQuat(ob->obmat,rot);
                        QuatMul(r_rot,r_rot,rot);
                }
        }
 
        if(part->phystype==PART_PHYS_BOIDS) {
+               BoidParticle *bpa = pa->boid;
                float dvec[3], q[4], mat[3][3];
 
                VECCOPY(pa->state.co,loc);
@@ -1878,16 +1849,21 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic
                        VECCOPY(pa->state.ave, nor);
                }
                /* and gravity in r_ve */
-               pa->r_ve[0] = pa->r_ve[1] = 0.0f;
-               pa->r_ve[2] = -1.0f;
+               bpa->gravity[0] = bpa->gravity[1] = 0.0f;
+               bpa->gravity[2] = -1.0f;
                if(part->acc[2]!=0.0f)
-                       pa->r_ve[2] = part->acc[2];
+                       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, pa->r_ve, pa->state.ave);
+               Projf(dvec, r_vel, pa->state.ave);
                VecSubf(mat[0], pa->state.ave, dvec);
                Normalize(mat[0]);
-               VECCOPY(mat[2], pa->r_ve);
+               VECCOPY(mat[2], r_vel);
                VecMulf(mat[2], -1.0f);
                Normalize(mat[2]);
                Crossf(mat[1], mat[2], mat[0]);
@@ -1896,10 +1872,10 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic
                Mat3ToQuat_is_ok(mat, q);
                QuatCopy(pa->state.rot, q);
 
-               pa->boid->health = part->boids->health;
-               pa->boid->mode = eBoidMode_InAir;
-               pa->boid->state_id = ((BoidState*)part->boids->states.first)->id;
-               pa->boid->acc[0]=pa->boid->acc[1]=pa->boid->acc[2]=0.0f;
+               bpa->data.health = part->boids->health;
+               bpa->data.mode = eBoidMode_InAir;
+               bpa->data.state_id = ((BoidState*)part->boids->states.first)->id;
+               bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f;
        }
        else {
                /* conversion done so now we apply new: */
@@ -1988,8 +1964,8 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic
 
                        /* rotation phase */
                        phasefac = part->phasefac;
-                       if(part->randphasefac != 0.0f) /* abuse r_ave[0] as a random number */
-                               phasefac += part->randphasefac * pa->r_ave[0];
+                       if(part->randphasefac != 0.0f)
+                               phasefac += part->randphasefac * r_phase;
                        VecRotToQuat(x_vec, phasefac*(float)M_PI, q_phase);
 
                        /* combine base rotation & phase */
@@ -2027,8 +2003,7 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic
 
        pa->state.time = cfra;
 
-       pa->stick_ob = 0;
-       pa->flag &= ~PARS_STICKY;
+//     pa->flag &= ~PARS_STICKY;
 }
 static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from)
 {
@@ -2094,8 +2069,9 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys)
 {
        ParticleSystem *kpsys = psys;
        ParticleTarget *pt;
-       ParticleData *pa;
-       int totpart = psys->totpart, i, k, totkeys = psys->totkeyed;
+       PARTICLE_P;
+       ParticleKey *key;
+       int totpart = psys->totpart, k, totkeys = psys->totkeyed;
 
        /* no proper targets so let's clear and bail out */
        if(psys->totkeyed==0) {
@@ -2107,12 +2083,12 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys)
        if(totpart && psys->particles->totkey != totkeys) {
                free_keyed_keys(psys);
                
-               psys->particles->keys = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys");
-               psys->particles->totkey = totkeys;
+               key = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys");
                
-               for(i=1, pa=psys->particles+1; i<totpart; i++,pa++){
-                       pa->keys = (pa-1)->keys + totkeys;
+               LOOP_PARTICLES {
+                       pa->keys = key;
                        pa->totkey = totkeys;
+                       key += totkeys;
                }
        }
        
@@ -2126,22 +2102,23 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys)
                else
                        kpsys = BLI_findlink(&ob->particlesystem, pt->psys - 1);
 
-               for(i=0,pa=psys->particles; i<totpart; i++, pa++) {
-                       (pa->keys + k)->time = -1.0; /* use current time */
+               LOOP_PARTICLES {
+                       key = pa->keys + k;
+                       key->time = -1.0; /* use current time */
 
-                       psys_get_particle_state(scene, pt->ob, kpsys, i%kpsys->totpart, pa->keys + k, 1);
+                       psys_get_particle_state(scene, pt->ob, kpsys, p%kpsys->totpart, key, 1);
 
                        if(psys->flag & PSYS_KEYED_TIMING){
-                               (pa->keys+k)->time = pa->time + pt->time;
+                               key->time = pa->time + pt->time;
                                if(pt->duration != 0.0f && k+1 < totkeys) {
-                                       copy_particle_key(pa->keys+k+1, pa->keys+k, 1);
-                                       (pa->keys+k+1)->time = pa->time + pt->time + pt->duration;
+                                       copy_particle_key(key+1, key, 1);
+                                       (key+1)->time = pa->time + pt->time + pt->duration;
                                }
                        }
                        else if(totkeys > 1)
-                               (pa->keys+k)->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime;
+                               key->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime;
                        else
-                               pa->keys->time = pa->time;
+                               key->time = pa->time;
                }
 
                if(psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f)
@@ -2296,16 +2273,15 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
 static void update_particle_tree(ParticleSystem *psys)
 {
        if(psys) {
-               ParticleData *pa = psys->particles;
-               int p, totpart = psys->totpart;
+               PARTICLE_P;
 
                if(!psys->tree || psys->tree_frame != psys->cfra) {
                        
                        BLI_kdtree_free(psys->tree);
 
-                       psys->tree = BLI_kdtree_new(totpart);
+                       psys->tree = BLI_kdtree_new(psys->totpart);
                        
-                       for(p=0, pa=psys->particles; p<totpart; p++,pa++){
+                       LOOP_PARTICLES {
                                if(pa->flag & (PARS_NO_DISP+PARS_UNEXIST) || pa->alive != PARS_ALIVE)
                                        continue;
 
@@ -2548,9 +2524,9 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa
        ListBase *lb=&psys->effectors;
        ParticleEffectorCache *ec;
        ParticleSettings *part=psys->part;
-       ParticleData *pa;
+       PARTICLE_P;
+       int totpart;
        float vec2[3],loc[3],*co=0;
-       int p,totpart;
        
        for(ec= lb->first; ec; ec= ec->next) {
                PartDeflect *pd= ec->ob->pd;
@@ -2574,7 +2550,7 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa
                                ec->distances=MEM_callocN(totpart*sizeof(float),"particle distances");
                                ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations");
 
-                               for(p=0,pa=psys->particles; p<totpart; p++, pa++){
+                               LOOP_PARTICLES {
                                        if(part->from == PART_FROM_PARTICLE) {
                                                VECCOPY(loc, pa->fuv);
                                        }
@@ -3253,9 +3229,10 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa
 
        /* override for boids */
        if(part->phystype == PART_PHYS_BOIDS) {
+               BoidParticle *bpa = pa->boid;
                radius = pa->size;
                boid_z = pa->state.co[2];
-               skip_ob = pa->stick_ob;
+               skip_ob = bpa->ground;
        }
 
        /* 10 iterations to catch multiple deflections */
@@ -3325,12 +3302,7 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa
                                deflections=max_deflections;
 
                                /* store for reactors */
-                               copy_particle_key(&reaction_state,&pa->state,0);
-
-                               if(part->flag & PART_STICKY){
-                                       pa->stick_ob=ob;
-                                       pa->flag |= PARS_STICKY;
-                               }
+                               copy_particle_key(&reaction_state, &pa->state, 0);
                        }
                        else {
                                float nor_vec[3], tan_vec[3], tan_vel[3], vel[3];
@@ -3418,7 +3390,8 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa
                                VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f));
 
                                if(part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) {
-                                       if(pa->boid->mode == eBoidMode_OnLand || co[2] <= boid_z) {
+                                       BoidParticle *bpa = pa->boid;
+                                       if(bpa->data.mode == eBoidMode_OnLand || co[2] <= boid_z) {
                                                co[2] = boid_z;
                                                vel[2] = 0.0f;
                                        }
@@ -3460,10 +3433,9 @@ static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierDa
 /*                     Hair                                                            */
 /************************************************/
 static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){
-       ParticleData *pa;
-       HairKey *key;
+       HairKey *key, *root;
+       PARTICLE_P;
        int totpart;
-       int i;
 
        Mat4Invert(ob->imat,ob->obmat);
        
@@ -3474,21 +3446,22 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy
        totpart=psys->totpart;
        
        /* save new keys for elements if needed */
-       for(i=0,pa=psys->particles; i<totpart; i++,pa++) {
+       LOOP_PARTICLES {
                /* first time alloc */
                if(pa->totkey==0 || pa->hair==NULL) {
                        pa->hair = MEM_callocN((psys->part->hair_step + 1) * sizeof(HairKey), "HairKeys");
                        pa->totkey = 0;
                }
 
-               key = pa->hair + pa->totkey;
+               key = root = pa->hair;
+               key += pa->totkey;
 
                /* convert from global to geometry space */
                VecCopyf(key->co, pa->state.co);
                Mat4MulVecfl(ob->imat, key->co);
 
                if(pa->totkey) {
-                       VECSUB(key->co, key->co, pa->hair->co);
+                       VECSUB(key->co, key->co, root->co);
                        psys_vec_rot_to_face(psmd->dm, pa, key->co);
                }
 
@@ -3500,7 +3473,7 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy
 
                /* root is always in the origin of hair space so we set it to be so after the last key is saved*/
                if(pa->totkey == psys->part->hair_step + 1)
-                       pa->hair->co[0] = pa->hair->co[1] = pa->hair->co[2] = 0.0f;
+                       root->co[0] = root->co[1] = root->co[2] = 0.0f;
        }
 }
 /************************************************/
@@ -3510,14 +3483,14 @@ static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSy
 static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra,
                                                  float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size)
 {
-       ParticleData *pa;
        ParticleSettings *part=psys->part;
        KDTree *tree=0;
        IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
        Material *ma=give_current_material(ob,part->omat);
        BoidBrainData bbd;
+       PARTICLE_P;
        float timestep;
-       int p, totpart;
+       int totpart;
        /* current time */
        float ctime, ipotime; // XXX old animation system
        /* frame & time changes */
@@ -3546,7 +3519,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
                if(part->type==PART_REACTOR)
                        vg_size=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE);
 
-               for(p=0, pa=psys->particles; p<totpart; p++,pa++){
+               LOOP_PARTICLES {
                        if(pa->flag & PARS_UNEXIST) continue;
 
                        /* set correct ipo timing */
@@ -3615,7 +3588,7 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
                }
 
                /* main loop: calculate physics for all particles */
-               for(p=0, pa=psys->particles; p<totpart; p++,pa++){
+               LOOP_PARTICLES {
                        if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue;
 
                        copy_particle_key(&pa->prev_state,&pa->state,1);
@@ -3703,9 +3676,6 @@ static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, Partic
                                        else{
                                                pa->alive=PARS_DEAD;
                                                pa->state.time=pa->dietime;
-
-                                               if(pa->flag&PARS_STICKY)
-                                                       psys_key_to_object(pa->stick_ob,&pa->state,0);
                                        }
                                }
                                else
@@ -3769,12 +3739,13 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif
 static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
 {
        ParticleSettings *part = psys->part;
-       ParticleData *pa;
-       int p;
-       float disp = (float)get_current_display_percentage(psys)/50.0f-1.0f;
+       PARTICLE_P;
+       float disp = (float)get_current_display_percentage(psys)/100.0f;
+
+       BLI_srandom(psys->seed);
 
-       for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){
-               if(pa->r_rot[0] > disp)
+       LOOP_PARTICLES {
+               if(BLI_frand() > disp)
                        pa->flag |= PARS_NO_DISP;
                else
                        pa->flag &= ~PARS_NO_DISP;
@@ -3798,13 +3769,14 @@ static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd
 static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
 {
        ParticleSettings *part=psys->part;
-       ParticleData *pa;
        ParticleKey state;
        IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
        Material *ma=give_current_material(ob,part->omat);
-       int p;
+       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);
 
@@ -3817,9 +3789,9 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
                        precalc_effectors(scene, ob,psys,psmd,cfra);
        //}
        
-       disp= (float)get_current_display_percentage(psys)/50.0f-1.0f;
+       disp= (float)get_current_display_percentage(psys)/100.0f;
 
-       for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){
+       LOOP_PARTICLES {
 #if 0 // XXX old animation system
                if((part->flag&PART_ABS_TIME)==0 && part->ipo){
                        ipotime=100.0f*(cfra-pa->time)/pa->lifetime;
@@ -3866,7 +3838,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
                        psys->lattice= NULL;
                }
 
-               if(pa->r_rot[0] > disp)
+               if(BLI_frand() > disp)
                        pa->flag |= PARS_NO_DISP;
                else
                        pa->flag &= ~PARS_NO_DISP;
@@ -3919,8 +3891,8 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys)
        else {
                free_hair(psys, 1);
 
-               CLAMP(part->path_start, part->sta, part->end + part->lifetime);
-               CLAMP(part->path_end, part->sta, part->end + part->lifetime);
+               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->softflag= 0;
@@ -3929,23 +3901,25 @@ static void psys_changed_type(Object *ob, ParticleSystem *psys)
 }
 void psys_check_boid_data(ParticleSystem *psys)
 {
-               ParticleData *pa = psys->particles;
-               int p = 1;
+               BoidParticle *bpa;
+               PARTICLE_P;
+
+               pa = psys->particles;
 
                if(!pa)
                        return;
 
                if(psys->part && psys->part->phystype==PART_PHYS_BOIDS) {
                        if(!pa->boid) {
-                               pa->boid = MEM_callocN(psys->totpart * sizeof(BoidData), "Boid Data");
+                               bpa = MEM_callocN(psys->totpart * sizeof(BoidParticle), "Boid Data");
 
-                               for(pa++; p<psys->totpart; p++, pa++)
-                                       pa->boid = (pa-1)->boid + 1;
+                               LOOP_PARTICLES
+                                       pa->boid = bpa++;
                        }
                }
                else if(pa->boid){
                        MEM_freeN(pa->boid);
-                       for(; p<psys->totpart; p++, pa++)
+                       LOOP_PARTICLES
                                pa->boid = NULL;
                }
 }
@@ -4093,10 +4067,10 @@ static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys,
 static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra)
 {
        ParticleSettings *part;
-       ParticleData *pa;
        PointCache *cache;
        PTCacheID pid;
-       int totpart, oldtotpart, totchild, oldtotchild, p;
+       PARTICLE_P;
+       int totpart, oldtotpart, totchild, oldtotchild;
        float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0;
        int init= 0, distr= 0, alloc= 0, usecache= 0, only_children_changed= 0;
        int framenr, framedelta, startframe, endframe;
@@ -4239,7 +4213,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
                }
                else if(result==PTCACHE_READ_OLD) {
                        psys->cfra = (float)cache->simframe;
-                       for(p=0, pa=psys->particles; p<totpart; p++, pa++) {
+                       LOOP_PARTICLES {
                                /* update alive status */
                                if(pa->time > psys->cfra)
                                        pa->alive = PARS_UNBORN;
@@ -4278,10 +4252,11 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
        }
 
        /* set particles to be not calculated TODO: can't work with pointcache */
-       disp= (float)get_current_display_percentage(psys)/50.0f-1.0f;
+       disp= (float)get_current_display_percentage(psys)/100.0f;
 
-       for(p=0, pa=psys->particles; p<totpart; p++,pa++){
-               if(pa->r_rot[0] > disp)
+       BLI_srandom(psys->seed);
+       LOOP_PARTICLES {
+               if(BLI_frand() > disp)
                        pa->flag |= PARS_NO_DISP;
                else
                        pa->flag &= ~PARS_NO_DISP;
index 7a156f56d725727c1e964a82d7a95ed094408a38..3e4297499530ba87c35cfdcd4c8adc059ed86f04 100644 (file)
@@ -181,6 +181,7 @@ static int ptcache_write_particle(int index, void *psys_v, void **data)
 {
        ParticleSystem *psys= psys_v;
        ParticleData *pa = psys->particles + index;
+       BoidParticle *boid = (psys->part->phystype == PART_PHYS_BOIDS) ? pa->boid : NULL;
        float times[3] = {pa->time, pa->dietime, pa->lifetime};
 
        if(data[BPHYS_DATA_INDEX]) {
@@ -198,8 +199,8 @@ static int ptcache_write_particle(int index, void *psys_v, void **data)
        ptcache_data_from(data, BPHYS_DATA_SIZE, &pa->size);
        ptcache_data_from(data, BPHYS_DATA_TIMES, times);
 
-       if(pa->boid)
-               ptcache_data_from(data, BPHYS_DATA_TIMES, &pa->boid);
+       if(boid)
+               ptcache_data_from(data, BPHYS_DATA_BOIDS, &boid->data);
 
        return 1;
 }
@@ -215,6 +216,7 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr
 {
        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));
@@ -238,8 +240,8 @@ static void ptcache_read_particle(int index, void *psys_v, void **data, float fr
                pa->lifetime = times[2];
        }
 
-       if(pa->boid)
-               ptcache_data_to(data, BPHYS_DATA_BOIDS, 0, &pa->boid);
+       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]) {
index 40a282514955e6811a021a06d4544f6872054fee..fdbfe154faea146d95b447de107ac44b750e5024 100644 (file)
@@ -3623,9 +3623,9 @@ static void particles_to_softbody(Scene *scene, Object *ob)
 
        /* find first BodyPoint index for each particle */
        if(psys->totpart > 0) {
-               psys->particles->bpi = 0;
-               for(a=1, pa=psys->particles+1; a<psys->totpart; a++, pa++)
-                       pa->bpi = (pa-1)->bpi + (pa-1)->totkey;
+//             psys->particles->bpi = 0;
+//             for(a=1, pa=psys->particles+1; a<psys->totpart; a++, pa++)
+//                     pa->bpi = (pa-1)->bpi + (pa-1)->totkey;
        }
 
        /* we always make body points */
@@ -4079,7 +4079,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        if(framenr < startframe) {
                cache->flag &= ~PTCACHE_SIMULATION_VALID;
                cache->simframe= 0;
-               cache->last_exact= 0;
+               //cache->last_exact= 0;
 
                return;
        }
@@ -4141,20 +4141,29 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
                pa= sb->particles->particles;
        }
 
+       if(framenr == startframe && cache->flag & PTCACHE_REDO_NEEDED) {
+               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+               cache->simframe= framenr;
+               cache->flag &= ~PTCACHE_REDO_NEEDED;
+               return;
+       }
+
        /* try to read from cache */
        cache_result = BKE_ptcache_read_cache(&pid, framenr, scene->r.frs_sec);
 
        if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
-               cache->flag |= PTCACHE_SIMULATION_VALID;
-               cache->simframe= framenr;
-
                if(sb->particles==0)
                        softbody_to_object(ob, vertexCos, numVerts, sb->local);
 
+               cache->simframe= framenr;
+               cache->flag |= PTCACHE_SIMULATION_VALID;
+
+               if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+                       BKE_ptcache_write_cache(&pid, framenr);
+
                return;
        }
        else if(cache_result==PTCACHE_READ_OLD) {
-               BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
                cache->flag |= PTCACHE_SIMULATION_VALID;
        }
        else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
@@ -4166,16 +4175,11 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
        }
 
        if(framenr == startframe) {
-               if(cache->flag & PTCACHE_REDO_NEEDED) {
-                       softbody_update_positions(ob, sb, vertexCos, numVerts);
-                       softbody_reset(ob, sb, vertexCos, numVerts);
-                       cache->flag &= ~PTCACHE_REDO_NEEDED;
-               }
                /* first frame, no simulation to do, just set the positions */
                softbody_update_positions(ob, sb, vertexCos, numVerts);
 
-               cache->flag |= PTCACHE_SIMULATION_VALID;
                cache->simframe= framenr;
+               cache->flag |= PTCACHE_SIMULATION_VALID;
 
                /* don't write cache on first frame, but on second frame write
                 * cache for frame 1 and 2 */
@@ -4187,10 +4191,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
 
                softbody_update_positions(ob, sb, vertexCos, numVerts);
 
-               /* do simulation */
-               cache->flag |= PTCACHE_SIMULATION_VALID;
-               cache->simframe= framenr;
-
                /* checking time: */
                dtime = framedelta*timescale;
 
@@ -4199,6 +4199,10 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
                if(sb->particles==0)
                        softbody_to_object(ob, vertexCos, numVerts, 0);
 
+               /* do simulation */
+               cache->simframe= framenr;
+               cache->flag |= PTCACHE_SIMULATION_VALID;
+
                BKE_ptcache_write_cache(&pid, framenr);
        }
 }
index 5a628192af61763e1c4f821fce68bda3d1410fb3..6a26a71ee3dc766717c3149526d22326522f10b1 100644 (file)
@@ -3055,11 +3055,8 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part)
 static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase *particles)
 {
        ParticleSystem *psys, *psysnext;
-       int a;
 
        for(psys=particles->first; psys; psys=psysnext){
-               ParticleData *pa;
-               
                psysnext= psys->next;
                
                psys->part = newlibadr_us(fd, id->lib, psys->part);
@@ -3070,12 +3067,6 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase
                                pt->ob=newlibadr(fd, id->lib, pt->ob);
 
                        psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
-
-                       for(a=0,pa=psys->particles; a<psys->totpart; a++,pa++){
-                               pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob);
-                       }
-
-
                }
                else {
                        /* particle modifier must be removed before particle system */
index 88c6f205d15a47f69eae6ee999c03dafc544ee95..c4a94660932b869d7287fef31a1d3b2c0bcc3349 100644 (file)
@@ -653,7 +653,7 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
                        }
 
                        if(psys->particles->boid && psys->part->phystype == PART_PHYS_BOIDS)
-                               writestruct(wd, DATA, "BoidData", psys->totpart, psys->particles->boid);
+                               writestruct(wd, DATA, "BoidParticle", psys->totpart, psys->particles->boid);
                }
                pt = psys->targets.first;
                for(; pt; pt=pt->next)
index 0ae987f23080d7aa07be320f7b155d175920e570..a5d365cafd4f2ce8248a9bf39aa0505381033c02 100644 (file)
 #include "BKE_object.h"
 #include "BKE_paint.h"
 #include "BKE_particle.h"
+#include "BKE_pointcache.h"
 #include "BKE_property.h"
 #include "BKE_report.h"
 #include "BKE_sca.h"
@@ -3883,6 +3884,8 @@ void ED_object_exit_editmode(bContext *C, int flag)
                /* for example; displist make is different in editmode */
                scene->obedit= NULL; // XXX for context
                
+               BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_DEPSGRAPH);
+
                /* also flush ob recalc, doesn't take much overhead, but used for particles */
                DAG_id_flush_update(&obedit->id, OB_RECALC_OB|OB_RECALC_DATA);
        
index 22316290c7b9811ab5be8f82d76a394b545cfad8..f2c7b64032f737605ec1117fb4b1ee7466c34a5e 100644 (file)
@@ -226,7 +226,7 @@ void PTCACHE_OT_bake(wmOperatorType *ot)
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 
-       RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
+       RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
 }
 void PTCACHE_OT_free_bake(wmOperatorType *ot)
 {
index 3ddc143b5a38c827827ce8bc19adf1651d0681aa..bc48d8f4f55579eaeb58dc3683bf5a94a578195b 100644 (file)
@@ -102,8 +102,6 @@ static void PTCacheUndo_clear(PTCacheEdit *edit);
 #define LOOP_SELECTED_KEYS             for(k=0, key=point->keys; k<point->totkey; k++, key++) if((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
 #define LOOP_TAGGED_KEYS               for(k=0, key=point->keys; k<point->totkey; k++, key++) if(key->flag & PEK_TAG)
 
-#define LOOP_PARTICLES(i, pa)  for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++)
-
 #define KEY_WCO                                        (key->flag & PEK_USE_WCO ? key->world_co : key->co)
 
 /**************************** utilities *******************************/
@@ -642,12 +640,13 @@ static int count_selected_keys(Scene *scene, PTCacheEdit *edit)
 static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
 {
        PTCacheEdit *edit;
-       ParticleData *pa;
        ParticleSystemModifierData *psmd;
        KDTree *tree;
        KDTreeNearest nearest;
+       HairKey *key;
+       PARTICLE_P;
        float mat[4][4], co[3];
-       int i, index, totpart;
+       int index, totpart;
 
        edit= psys->edit;
        psmd= psys_get_modifier(ob, psys);
@@ -656,11 +655,12 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        tree= BLI_kdtree_new(totpart);
 
        /* insert particles into kd tree */
-       LOOP_PARTICLES(i, pa) {
+       LOOP_PARTICLES {
+               key = pa->hair;
                psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
-               VECCOPY(co, pa->hair[0].co);
+               VECCOPY(co, key->co);
                Mat4MulVecfl(mat, co);
-               BLI_kdtree_insert(tree, i, co, NULL);
+               BLI_kdtree_insert(tree, p, co, NULL);
        }
 
        BLI_kdtree_balance(tree);
@@ -669,27 +669,28 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        if(!edit->mirror_cache)
                edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache");
        
-       LOOP_PARTICLES(i, pa) {
+       LOOP_PARTICLES {
+               key = pa->hair;
                psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat);
-               VECCOPY(co, pa->hair[0].co);
+               VECCOPY(co, key->co);
                Mat4MulVecfl(mat, co);
                co[0]= -co[0];
 
                index= BLI_kdtree_find_nearest(tree, co, NULL, &nearest);
 
                /* this needs a custom threshold still, duplicated for editmode mirror */
-               if(index != -1 && index != i && (nearest.dist <= 0.0002f))
-                       edit->mirror_cache[i]= index;
+               if(index != -1 && index != p && (nearest.dist <= 0.0002f))
+                       edit->mirror_cache[p]= index;
                else
-                       edit->mirror_cache[i]= -1;
+                       edit->mirror_cache[p]= -1;
        }
 
        /* make sure mirrors are in two directions */
-       LOOP_PARTICLES(i, pa) {
-               if(edit->mirror_cache[i]) {
-                       index= edit->mirror_cache[i];
-                       if(edit->mirror_cache[index] != i)
-                               edit->mirror_cache[i]= -1;
+       LOOP_PARTICLES {
+               if(edit->mirror_cache[p]) {
+                       index= edit->mirror_cache[p];
+                       if(edit->mirror_cache[index] != p)
+                               edit->mirror_cache[p]= -1;
                }
        }
 
@@ -1735,7 +1736,7 @@ static void rekey_particle(PEData *data, int pa_index)
        ParticleData *pa= psys->particles + pa_index;
        PTCacheEditPoint *point = edit->points + pa_index;
        ParticleKey state;
-       HairKey *key, *new_keys;
+       HairKey *key, *new_keys, *okey;
        PTCacheEditKey *ekey;
        float dval, sta, end;
        int k;
@@ -1744,12 +1745,13 @@ static void rekey_particle(PEData *data, int pa_index)
 
        key= new_keys= MEM_callocN(data->totrekey * sizeof(HairKey),"Hair re-key keys");
 
+       okey = pa->hair;
        /* root and tip stay the same */
-       VECCOPY(key->co, pa->hair->co);
-       VECCOPY((key + data->totrekey - 1)->co, (pa->hair + pa->totkey - 1)->co);
+       VECCOPY(key->co, okey->co);
+       VECCOPY((key + data->totrekey - 1)->co, (okey + pa->totkey - 1)->co);
 
-       sta= key->time= pa->hair->time;
-       end= (key + data->totrekey - 1)->time= (pa->hair + pa->totkey - 1)->time;
+       sta= key->time= okey->time;
+       end= (key + data->totrekey - 1)->time= (okey + pa->totkey - 1)->time;
        dval= (end - sta) / (float)(data->totrekey - 1);
 
        /* interpolate new keys from old ones */
@@ -2034,9 +2036,11 @@ static void subdivide_particle(PEData *data, int pa_index)
 
        nkey= new_keys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(HairKey)),"Hair subdivide keys");
        nekey= new_ekeys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(PTCacheEditKey)),"Hair subdivide edit keys");
-       endtime= pa->hair[pa->totkey-1].time;
+       
+       key = pa->hair;
+       endtime= key[pa->totkey-1].time;
 
-       for(k=0, key=pa->hair, ekey=point->keys; k<pa->totkey-1; k++, key++, ekey++) {
+       for(k=0, ekey=point->keys; k<pa->totkey-1; k++, key++, ekey++) {
 
                memcpy(nkey,key,sizeof(HairKey));
                memcpy(nekey,ekey,sizeof(PTCacheEditKey));
@@ -2461,7 +2465,6 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                        *newpa= *pa;
                        *newpoint= *point;
                        if(pa->hair) newpa->hair= MEM_dupallocN(pa->hair);
-                       if(pa->keys) newpa->keys= MEM_dupallocN(pa->keys);
                        if(point->keys) newpoint->keys= MEM_dupallocN(point->keys);
 
                        /* rotate weights according to vertex index rotation */
@@ -2966,7 +2969,7 @@ static void brush_add(PEData *data, short number)
                                        weight[w] /= totw;
 
                                for(k=0; k<pset->totaddkey; k++) {
-                                       hkey= pa->hair + k;
+                                       hkey= (HairKey*)pa->hair + k;
                                        hkey->time= pa->time + k * framestep;
 
                                        key[0].time= hkey->time/ 100.0f;
@@ -2990,15 +2993,15 @@ static void brush_add(PEData *data, short number)
                                        if(k==0)
                                                VECSUB(co1, pa->state.co, key[0].co);
 
-                                       VECADD(pa->hair[k].co, key[0].co, co1);
+                                       VECADD(hkey->co, key[0].co, co1);
 
-                                       pa->hair[k].time= key[0].time;
+                                       hkey->time= key[0].time;
                                }
                        }
                        else {
                                for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
                                        VECADDFAC(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
-                                       pa->hair[k].time += k * framestep;
+                                       hkey->time += k * framestep;
                                }
                        }
                        for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
index e49616fc7408933fd1ccc69ab232cbd6f4c9b6bc..25ff12442546e36c91a94d2a56d3397dab05a40c 100644 (file)
@@ -3373,8 +3373,9 @@ 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)
-                                       pa_health = pa->boid->health;
+                               if(part->phystype==PART_PHYS_BOIDS) {
+                                       pa_health = pa->boid->data.health;
+                               }
                                else
                                        pa_health = -1.0;
 
@@ -3409,8 +3410,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
                                }
 #endif // XXX old animation system
 
-                               r_tilt = 1.0f + pa->r_ave[0];
-                               r_length = 0.5f * (1.0f + pa->r_ave[1]);
+                               BLI_srandom(psys->seed+a);
+
+                               r_tilt = 2.0f*(BLI_frand() - 0.5f);
+                               r_length = BLI_frand();
                        }
                        else{
                                ChildParticle *cpa= &psys->child[a-totpart];
index 12c253a7cb87a5e6a1f654d4a94600b44ec0ee07..d4dc3df09658aa0d7e0b798fd3198a4bc75bccde 100644 (file)
@@ -33,6 +33,7 @@
 #define DNA_PARTICLE_TYPES_H
 
 #include "DNA_ID.h"
+#include "DNA_boid_types.h"
 
 struct AnimData;
 
@@ -52,6 +53,14 @@ typedef struct ParticleKey { /* when changed update size of struct to copy_parti
        float time;             /* when this key happens */
 } ParticleKey;
 
+typedef struct BoidParticle {
+       struct Object *ground;
+       struct BoidData data;
+       float gravity[3];
+       float wander[3];
+       float rt;
+} BoidParticle;
+
 /* Child particles are created around or between parent particles */
 typedef struct ChildParticle {
        int num, parent;        /* num is face index on the final derived mesh */
@@ -69,42 +78,34 @@ typedef struct ParticleTarget {
        float time, duration;
 } ParticleTarget;
 
-/* Everything that's non dynamic for a particle:                       */
 typedef struct ParticleData {
-       struct Object *stick_ob;/* object that particle sticks to when dead */
-
-       ParticleKey state;              /* normally current global coordinates or       */
-                                                       /* in sticky object space if dead & sticky      */
+       ParticleKey state;              /* current global coordinates */
 
        ParticleKey prev_state; /* previous state */
-
+       
        HairKey *hair;                  /* hair vertices */
 
-       ParticleKey *keys;              /* keyed states */
+       ParticleKey *keys;              /* keyed keys */
 
-       struct BoidData *boid;  /* boids data */
+       BoidParticle *boid;             /* boids data */
 
-       float r_rot[4];                 /* random values */
-       float r_ave[3],r_ve[3];
-
-       float fuv[4], foffset;  /* coordinates on face/edge number "num" and depth along*/
-                                                       /* face normal for volume emission                                              */
+       int totkey;                             /* amount of hair or keyed keys*/
 
        float time, lifetime;   /* dietime is not nescessarily time+lifetime as */
        float dietime;                  /* particles can die unnaturally (collision)    */
 
-       float size, sizemul;    /* size and multiplier so that we can update size when ever */
-
        int num;                                /* index to vert/edge/face */
        int num_dmcache;                /* index to derived mesh data (face) to avoid slow lookups */
 
-       int totkey;
-       int bpi;                                /* softbody body point start index */
+       float fuv[4], foffset;  /* coordinates on face/edge number "num" and depth along*/
+                                                       /* face normal for volume emission                                              */
+
+       float size;                             /* size and multiplier so that we can update size when ever */
 
        short flag;
-       short alive;                            /* the life state of a particle */
+       short alive;                    /* the life state of a particle */
        short loop;                             /* how many times particle life has looped */
-       short rt2;
+       short rt;
 } ParticleData;
 
 typedef struct ParticleSettings {
@@ -258,7 +259,7 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 #define PART_TRAND                     128     
 #define PART_EDISTR                    256     /* particle/face from face areas */
 
-#define PART_STICKY                    512     /*collided particles can stick to collider*/
+//#define PART_STICKY                  512     /*collided particles can stick to collider*/
 #define PART_DIE_ON_COL                (1<<12)
 #define PART_SIZE_DEFL         (1<<13) /* swept sphere deflections */
 #define PART_ROT_DYN           (1<<14) /* dynamic rotation */
@@ -409,7 +410,7 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 
 /* psys->flag */
 #define PSYS_CURRENT           1
-//#define PSYS_BAKING                  2
+#define PSYS_GLOBAL_HAIR       2
 //#define PSYS_BAKE_UI         4
 #define        PSYS_KEYED_TIMING       8
 #define PSYS_ENABLED           16      /* deprecated */
@@ -426,7 +427,7 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 /* pars->flag */
 #define PARS_UNEXIST           1
 #define PARS_NO_DISP           2
-#define PARS_STICKY                    4
+//#define PARS_STICKY                  4
 #define PARS_REKEY                     8
 
 /* pars->alive */
index 2525209c3be5608c5a810dd23115c7da478bb9c4..4a23605c717604adcf82a8343dd9256498e93b60 100644 (file)
@@ -643,12 +643,6 @@ static void rna_def_particle(BlenderRNA *brna)
        RNA_def_struct_sdna(srna, "ParticleData");
        RNA_def_struct_ui_text(srna, "Particle", "Particle in a particle system.");
 
-       prop= RNA_def_property(srna, "stick_object", PROP_POINTER, PROP_NONE);
-       RNA_def_property_pointer_sdna(prop, NULL, "stick_ob");
-       RNA_def_property_struct_type(prop, "Object");
-       RNA_def_property_flag(prop, PROP_EDITABLE);
-       RNA_def_property_ui_text(prop, "Stick Object", "Object that particle sticks to when dead");
-
        /* Particle State & Previous State */
        prop= RNA_def_property(srna, "location", PROP_FLOAT, PROP_TRANSLATION);
        RNA_def_property_float_sdna(prop, NULL, "state.co");
@@ -693,24 +687,6 @@ static void rna_def_particle(BlenderRNA *brna)
        RNA_def_property_collection_sdna(prop, NULL, "keys", "totkey");
        RNA_def_property_struct_type(prop, "ParticleKey");
        RNA_def_property_ui_text(prop, "Keyed States", "");
-
-       /* Random variables */
-
-       prop= RNA_def_property(srna, "random_rotation", PROP_FLOAT, PROP_QUATERNION);
-       RNA_def_property_float_sdna(prop, NULL, "r_rot");
-//     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
-       RNA_def_property_ui_text(prop, "Random Rotation", "");
-
-       prop= RNA_def_property(srna, "random_a_velocity", PROP_FLOAT, PROP_VELOCITY);
-       RNA_def_property_float_sdna(prop, NULL, "r_ave");
-//     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
-       RNA_def_property_ui_text(prop, "Random Angular Velocity", "");
-
-       prop= RNA_def_property(srna, "random_velocity", PROP_FLOAT, PROP_VELOCITY);
-       RNA_def_property_float_sdna(prop, NULL, "r_ve");
-//     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
-       RNA_def_property_ui_text(prop, "Random Velocity", "");
-
 //
 //     float fuv[4], foffset;  /* coordinates on face/edge number "num" and depth along*/
 //                                                     /* face normal for volume emission                                              */
@@ -733,18 +709,12 @@ static void rna_def_particle(BlenderRNA *brna)
 //     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
        RNA_def_property_ui_text(prop, "Size", "");
 
-       prop= RNA_def_property(srna, "size_multiplier", PROP_FLOAT, PROP_NONE);
-       RNA_def_property_float_sdna(prop, NULL, "sizemul");
-//     RNA_def_property_range(prop, lowerLimitf, upperLimitf);
-       RNA_def_property_ui_text(prop, "Size Multiplier", "");
-
 //
 //     int num;                                /* index to vert/edge/face */
 //     int num_dmcache;                /* index to derived mesh data (face) to avoid slow lookups */
 //     int pad;
 //
 //     int totkey;
-//     int bpi;                                /* softbody body point start index */
 
        /* flag */
        prop= RNA_def_property(srna, "unexist", PROP_BOOLEAN, PROP_NONE);
@@ -755,10 +725,6 @@ static void rna_def_particle(BlenderRNA *brna)
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PARS_NO_DISP);
        RNA_def_property_ui_text(prop, "no_disp", "");
 
-       prop= RNA_def_property(srna, "sticky", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", PARS_STICKY);
-       RNA_def_property_ui_text(prop, "sticky", "");
-
        prop= RNA_def_property(srna, "rekey", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PARS_REKEY);
        RNA_def_property_ui_text(prop, "rekey", "");
@@ -942,13 +908,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
        RNA_def_property_ui_text(prop, "Even Distribution", "Use even distribution from faces based on face areas or edge lengths.");
        RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
-       prop= RNA_def_property(srna, "sticky", PROP_BOOLEAN, PROP_NONE);
-       RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_STICKY);
-       RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
-       RNA_def_property_ui_text(prop, "Sticky", "Particles stick to collided objects if they die in the collision.");
-       RNA_def_property_update(prop, 0, "rna_Particle_reset");
-
        prop= RNA_def_property(srna, "die_on_collision", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_DIE_ON_COL);
        RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
index cf6246e3641d6373e513b9b2a42d905ebfaab313..df99d5f284345b1516b8f65cfd0139553f7f6e28 100644 (file)
@@ -1743,8 +1743,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
 
                        pa_size = pa->size;
 
-                       r_tilt = 1.0f + pa->r_ave[0];
-                       r_length = 0.5f * (1.0f + pa->r_ave[1]);
+                       BLI_srandom(psys->seed+a);
+
+                       r_tilt = 2.0f*(BLI_frand() - 0.5f);
+                       r_length = BLI_frand();
 
                        if(path_nbr) {
                                cache = psys->pathcache[a];