Fix for [#26372] Objects as PS Hair displays and renders differently
authorJanne Karhu <jhkarh@gmail.com>
Wed, 9 Mar 2011 14:18:33 +0000 (14:18 +0000)
committerJanne Karhu <jhkarh@gmail.com>
Wed, 9 Mar 2011 14:18:33 +0000 (14:18 +0000)
* Grid distribution isn't really suited for hair, so this is now disabled.
* Setting a jittered distribution with particles/face = 1 now creates particles on the center of faces.
* Quite a bit of cleanup of the whole particle distribution code.

source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/makesdna/DNA_particle_types.h
source/blender/makesrna/intern/rna_particle.c
source/blender/render/intern/source/convertblender.c

index 507adcc5f2d9c477dd6e952e3969d212edb17397..e4fbd5603f2b0eb27ab18d21cec1bb8b144ddaff 100644 (file)
@@ -242,7 +242,7 @@ void psys_get_particle_on_path(struct ParticleSimulationData *sim, int pa_num, s
 int psys_get_particle_state(struct ParticleSimulationData *sim, int p, struct ParticleKey *state, int always);
 
 /* for anim.c */
-void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco);
+void psys_get_dupli_texture(struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco);
 void psys_get_dupli_path_transform(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale);
 
 ParticleThread *psys_threads_create(struct ParticleSimulationData *sim);
index 39fea333cbc02249f7a735d4d199f16eba19270a..2e1fbf2917a33638e2bff23bc54b5963f6949557 100644 (file)
@@ -1346,8 +1346,6 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
                                /* for groups, pick the object based on settings */
                                if(part->draw&PART_DRAW_RAND_GR)
                                        b= BLI_rand() % totgroup;
-                               else if(part->from==PART_FROM_PARTICLE)
-                                       b= pa_num % totgroup;
                                else
                                        b= a % totgroup;
 
@@ -1402,7 +1400,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
                                        dob= new_dupli_object(lb, go->ob, mat, par->lay, counter, OB_DUPLIPARTS, animated);
                                        copy_m4_m4(dob->omat, obcopylist[b].obmat);
                                        if(G.rendering)
-                                               psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
+                                               psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
                                }
                        }
                        else {
@@ -1434,7 +1432,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
                                dob= new_dupli_object(lb, ob, mat, ob->lay, counter, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, animated);
                                copy_m4_m4(dob->omat, oldobmat);
                                if(G.rendering)
-                                       psys_get_dupli_texture(par, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
+                                       psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
                        }
                }
 
index ebbdb7a8788d983f49abb0240842d3c0c47a394b..e2a23f5bc6c4362eb1a74f867cc3fa1a344906ea 100644 (file)
@@ -2407,7 +2407,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
                steps = (int)pow(2.0, (double)pset->draw_step);
        }
 
-       if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
+       if(totchild && part->childtype==PART_CHILD_FACES){
                totparent=(int)(totchild*part->parents*0.3);
                
                if(G.rendering && part->child_nbr && part->ren_child_nbr)
@@ -2449,16 +2449,14 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
        psys->lattice = psys_get_lattice(&ctx->sim);
 
        /* cache all relevant vertex groups if they exist */
-       if(part->from!=PART_FROM_PARTICLE){
-               ctx->vg_length = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_LENGTH);
-               ctx->vg_clump = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_CLUMP);
-               ctx->vg_kink = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_KINK);
-               ctx->vg_rough1 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH1);
-               ctx->vg_rough2 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH2);
-               ctx->vg_roughe = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGHE);
-               if(psys->part->flag & PART_CHILD_EFFECT)
-                       ctx->vg_effector = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_EFFECTOR);
-       }
+       ctx->vg_length = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_LENGTH);
+       ctx->vg_clump = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_CLUMP);
+       ctx->vg_kink = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_KINK);
+       ctx->vg_rough1 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH1);
+       ctx->vg_rough2 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH2);
+       ctx->vg_roughe = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGHE);
+       if(psys->part->flag & PART_CHILD_EFFECT)
+               ctx->vg_effector = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_EFFECTOR);
 
        /* set correct ipo timing */
 #if 0 // XXX old animation system
@@ -2912,8 +2910,8 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
        if(ma && (psys->part->draw & PART_DRAW_MAT_COL))
                VECCOPY(col, &ma->r)
 
-       if(psys->part->from!=PART_FROM_PARTICLE && !(psys->flag & PSYS_GLOBAL_HAIR)) {
-               if(!(psys->part->flag & PART_CHILD_EFFECT))
+       if((psys->flag & PSYS_GLOBAL_HAIR)==0) {
+               if((psys->part->flag & PART_CHILD_EFFECT)==0)
                        vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR);
                
                if(!psys->totchild)
@@ -4042,7 +4040,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                if(state->time < 0.0f)
                        t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
                
-               if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
+               if(totchild && part->childtype==PART_CHILD_FACES){
                        /* part->parents could still be 0 so we can't test with totparent */
                        between=1;
                }
@@ -4192,7 +4190,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
                if(!psys->totchild)
                        return 0;
 
-               if(part->from != PART_FROM_PARTICLE && part->childtype == PART_CHILD_FACES){
+               if(part->childtype == PART_CHILD_FACES){
                        if(!(psys->flag & PSYS_KEYED))
                                return 0;
 
@@ -4314,13 +4312,15 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
        }
 }
 
-void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
+void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
 {
        MFace *mface;
        MTFace *mtface;
        float loc[3];
        int num;
 
+       uv[0] = uv[1] = 0.f;
+
        if(cpa) {
                if(part->childtype == PART_CHILD_FACES) {
                        mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
@@ -4329,43 +4329,36 @@ void psys_get_dupli_texture(Object *UNUSED(ob), ParticleSettings *part, Particle
                                mtface += cpa->num;
                                psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
                        }
-                       else
-                               uv[0]= uv[1]= 0.0f;
+               
+                       psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,0,0,0,orco,0);
+                       return;
+               }
+               else {
+                       pa = psys->particles + cpa->pa[0];
                }
-               else
-                       uv[0]= uv[1]= 0.0f;
-
-               psys_particle_on_emitter(psmd,
-                       (part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
-                       cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,0,0,0,orco,0);
        }
-       else {
-               if(part->from == PART_FROM_FACE) {
-                       mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
-                       num= pa->num_dmcache;
 
-                       if(num == DMCACHE_NOTFOUND)
-                               num= pa->num;
+       if(part->from == PART_FROM_FACE) {
+               mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
+               num= pa->num_dmcache;
 
-                       if (num >= psmd->dm->getNumFaces(psmd->dm)) {
-                               /* happens when simplify is enabled
-                                * gives invalid coords but would crash otherwise */
-                               num= DMCACHE_NOTFOUND;
-                       }
+               if(num == DMCACHE_NOTFOUND)
+                       num= pa->num;
 
-                       if(mtface && num != DMCACHE_NOTFOUND) {
-                               mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
-                               mtface += num;
-                               psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
-                       }
-                       else
-                               uv[0]= uv[1]= 0.0f;
+               if (num >= psmd->dm->getNumFaces(psmd->dm)) {
+                       /* happens when simplify is enabled
+                               * gives invalid coords but would crash otherwise */
+                       num= DMCACHE_NOTFOUND;
                }
-               else
-                       uv[0]= uv[1]= 0.0f;
 
-               psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,orco,0);
+               if(mtface && num != DMCACHE_NOTFOUND) {
+                       mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
+                       mtface += num;
+                       psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
+               }
        }
+
+       psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,orco,0);
 }
 
 void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
@@ -4380,7 +4373,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
        len= normalize_v3(vec);
 
        if(psys->part->rotmode) {
-               if(!pa)
+               if(pa == NULL)
                        pa= psys->particles+cpa->pa[0];
 
                vec_to_quat( q,xvec, ob->trackflag, ob->upflag);
@@ -4391,12 +4384,13 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa
                mul_m4_m4m4(mat, obrotmat, qmat);
        }
        else {
+               if(pa == NULL && psys->part->childflat != PART_CHILD_FACES)
+                       pa = psys->particles + cpa->pa[0];
+
                if(pa)
                        psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
                else
-                       psys_particle_on_emitter(psmd,
-                               (psys->part->childtype == PART_CHILD_FACES)? PART_FROM_FACE: PART_FROM_PARTICLE,
-                               cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
+                       psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
                
                copy_m3_m4(nmat, ob->imat);
                transpose_m3(nmat);
index 336b683e26b9b71d9e58743f378fb40fc1df6adc..15c6b30d4e53f4ef6c9ff4e1045c0ec18f34bbd6 100644 (file)
@@ -329,6 +329,10 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
        }
 }
 
+/************************************************/
+/*                     Distribution                                            */
+/************************************************/
+
 void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
 {
        /* use for building derived mesh mapping info:
@@ -405,7 +409,35 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys)
        }
 }
 
-static void distribute_particles_in_grid(DerivedMesh *dm, ParticleSystem *psys)
+static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys)
+{
+       ChildParticle *cpa = psys->child;
+       int i, p;
+       int child_nbr= get_psys_child_number(scene, psys);
+       int totpart= get_psys_tot_child(scene, psys);
+
+       alloc_child_particles(psys, totpart);
+
+       for(i=0; i<child_nbr; i++){
+               for(p=0; p<psys->totpart; p++,cpa++){
+                       float length=2.0;
+                       cpa->parent=p;
+                                       
+                       /* create even spherical distribution inside unit sphere */
+                       while(length>=1.0f){
+                               cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
+                               cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
+                               cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
+                               length=len_v3(cpa->fuv);
+                       }
+
+                       cpa->num=-1;
+               }
+       }
+       /* dmcache must be updated for parent particles if children from faces is used */
+       psys_calc_dmcache(ob, finaldm, psys);
+}
+static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
 {
        ParticleData *pa=NULL;
        float min[3], max[3], delta[3], d;
@@ -686,7 +718,7 @@ static void psys_uv_to_w(float u, float v, int quad, float *w)
 }
 
 /* Find the index in "sum" array before "value" is crossed. */
-static int binary_search_distribution(float *sum, int n, float value)
+static int distribute_binary_search(float *sum, int n, float value)
 {
        int mid, low=0, high=n;
 
@@ -716,13 +748,11 @@ static int binary_search_distribution(float *sum, int n, float value)
 
 /* note: this function must be thread safe, for from == PART_FROM_CHILD */
 #define ONLY_WORKING_WITH_PA_VERTS 0
-static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p)
+static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p)
 {
        ParticleThreadContext *ctx= thread->ctx;
        Object *ob= ctx->sim.ob;
        DerivedMesh *dm= ctx->dm;
-       ParticleData *tpa;
-/*     ParticleSettings *part= ctx->sim.psys->part; */
        float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3];
        float cur_d, min_d, randu, randv;
        int from= ctx->from;
@@ -760,9 +790,17 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
                
                switch(distr){
                case PART_DISTR_JIT:
-                       ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel);
-                       psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv);
-                       ctx->jitoff[i]++;
+                       if(ctx->jitlevel == 1) {
+                               if(mface->v4)
+                                       psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv);
+                               else
+                                       psys_uv_to_w(0.33333f, 0.33333f, mface->v4, pa->fuv);
+                       }
+                       else {
+                               ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel);
+                               psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv);
+                               ctx->jitoff[i]++;
+                       }
                        break;
                case PART_DISTR_RAND:
                        randu= rng_getFloat(thread->rng);
@@ -828,15 +866,6 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
                        }
                }
        }
-       else if(from == PART_FROM_PARTICLE) {
-               tpa=ctx->tpars+ctx->index[p];
-               pa->num=ctx->index[p];
-               pa->fuv[0]=tpa->fuv[0];
-               pa->fuv[1]=tpa->fuv[1];
-               /* abusing foffset a little for timing in near reaction */
-               pa->foffset=ctx->weight[ctx->index[p]];
-               ctx->weight[ctx->index[p]]+=ctx->maxweight;
-       }
        else if(from == PART_FROM_CHILD) {
                MFace *mf;
 
@@ -870,7 +899,6 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
 
                        maxd=ptn[maxw-1].dist;
                        mind=ptn[0].dist;
-                       /*dd=maxd-mind;*/ /*UNUSED*/
                        
                        /* the weights here could be done better */
                        for(w=0; w<maxw; w++){
@@ -906,7 +934,7 @@ static void psys_thread_distribute_particle(ParticleThread *thread, ParticleData
                rng_skip(thread->rng, rng_skip_tot);
 }
 
-static void *exec_distribution(void *data)
+static void *distribute_threads_exec_cb(void *data)
 {
        ParticleThread *thread= (ParticleThread*)data;
        ParticleSystem *psys= thread->ctx->sim.psys;
@@ -923,7 +951,7 @@ static void *exec_distribution(void *data)
                                rng_skip(thread->rng, PSYS_RND_DIST_SKIP * thread->ctx->skip[p]);
 
                        if((p+thread->num) % thread->tot == 0)
-                               psys_thread_distribute_particle(thread, NULL, cpa, p);
+                               distribute_threads_exec(thread, NULL, cpa, p);
                        else /* thread skip */
                                rng_skip(thread->rng, PSYS_RND_DIST_SKIP);
                }
@@ -932,7 +960,7 @@ static void *exec_distribution(void *data)
                totpart= psys->totpart;
                pa= psys->particles + thread->num;
                for(p=thread->num; p<totpart; p+=thread->tot, pa+=thread->tot)
-                       psys_thread_distribute_particle(thread, pa, NULL, p);
+                       distribute_threads_exec(thread, pa, NULL, p);
        }
 
        return 0;
@@ -940,7 +968,7 @@ static void *exec_distribution(void *data)
 
 /* not thread safe, but qsort doesn't take userdata argument */
 static int *COMPARE_ORIG_INDEX = NULL;
-static int compare_orig_index(const void *p1, const void *p2)
+static int distribute_compare_orig_index(const void *p1, const void *p2)
 {
        int index1 = COMPARE_ORIG_INDEX[*(const int*)p1];
        int index2 = COMPARE_ORIG_INDEX[*(const int*)p2];
@@ -961,44 +989,54 @@ static int compare_orig_index(const void *p1, const void *p2)
                return 1;
 }
 
-/* creates a distribution of coordinates on a DerivedMesh      */
-/*                                                                                                                     */
-/* 1. lets check from what we are emitting                                     */
-/* 2. now we know that we have something to emit from so       */
-/*       let's calculate some weights                                                  */
-/* 2.1 from even distribution                                                          */
-/* 2.2 and from vertex groups                                                          */
-/* 3. next we determine the indexes of emitting thing that     */
-/*       the particles will have                                                               */
-/* 4. let's do jitter if we need it                                                    */
-/* 5. now we're ready to set the indexes & distributions to    */
-/*       the particles                                                                                 */
-/* 6. and we're done!                                                                          */
+static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
+{
+       if(from == PART_FROM_CHILD) {
+               ChildParticle *cpa;
+               int p, totchild = get_psys_tot_child(scene, psys);
+
+               if(psys->child && totchild) {
+                       for(p=0,cpa=psys->child; p<totchild; p++,cpa++){
+                               cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0;
+                               cpa->foffset= 0.0f;
+                               cpa->parent=0;
+                               cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
+                               cpa->num= -1;
+                       }
+               }
+       }
+       else {
+               PARTICLE_P;
+               LOOP_PARTICLES {
+                       pa->fuv[0]=pa->fuv[1]=pa->fuv[2]= pa->fuv[3]= 0.0;
+                       pa->foffset= 0.0f;
+                       pa->num= -1;
+               }
+       }
+}
 
+/* Creates a distribution of coordinates on a DerivedMesh      */
 /* This is to denote functionality that does not yet work with mesh - only derived mesh */
-static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from)
+static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from)
 {
        ParticleThreadContext *ctx= threads[0].ctx;
        Object *ob= ctx->sim.ob;
        ParticleSystem *psys= ctx->sim.psys;
-       Object *tob;
        ParticleData *pa=0, *tpars= 0;
        ParticleSettings *part;
-       ParticleSystem *tpsys;
        ParticleSeam *seams= 0;
        ChildParticle *cpa=0;
        KDTree *tree=0;
        DerivedMesh *dm= NULL;
        float *jit= NULL;
        int i, seed, p=0, totthread= threads[0].tot;
-       int /*no_distr=0,*/ cfrom=0;
-       int tot=0, totpart, *index=0, children=0, totseam=0;
-       //int *vertpart=0;
+       int cfrom=0;
+       int totelem=0, totpart, *particle_element=0, children=0, totseam=0;
        int jitlevel= 1, distr;
-       float *weight=0,*sum=0,*jitoff=0;
-       float cur, maxweight=0.0, tweight, totweight, co[3], nor[3], orco[3], ornor[3];
+       float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL;
+       float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3], ornor[3];
        
-       if(ob==0 || psys==0 || psys->part==0)
+       if(ELEM3(NULL, ob, psys, psys->part))
                return 0;
 
        part=psys->part;
@@ -1012,81 +1050,63 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
                return 0;
        }
 
-       BLI_srandom(31415926 + psys->seed);
+       /* First handle special cases */
+       if(from == PART_FROM_CHILD) {
+               /* Simple children */
+               if(part->childtype != PART_CHILD_FACES) {
+                       BLI_srandom(31415926 + psys->seed + psys->child_seed);
+                       distribute_simple_children(scene, ob, finaldm, psys);
+                       return 0;
+               }
+       }
+       else {
+               /* Grid distribution */
+               if(part->distr==PART_DISTR_GRID && from != PART_FROM_VERT){
+                       BLI_srandom(31415926 + psys->seed);
+                       dm= CDDM_from_mesh((Mesh*)ob->data, ob);
+                       distribute_grid(dm,psys);
+                       dm->release(dm);
+                       return 0;
+               }
+       }
        
-       if(from==PART_FROM_CHILD){
+       /* Create trees and original coordinates if needed */
+       if(from == PART_FROM_CHILD) {
                distr=PART_DISTR_RAND;
                BLI_srandom(31415926 + psys->seed + psys->child_seed);
+               dm= finaldm;
+               children=1;
 
-               if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
-                       dm= finaldm;
-                       children=1;
-
-                       tree=BLI_kdtree_new(totpart);
-
-                       for(p=0,pa=psys->particles; p<totpart; p++,pa++){
-                               psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,ornor);
-                               transform_mesh_orco_verts((Mesh*)ob->data, &orco, 1, 1);
-                               BLI_kdtree_insert(tree, p, orco, ornor);
-                       }
+               totpart = get_psys_tot_child(scene, psys);
+               cfrom = from = PART_FROM_FACE;
 
-                       BLI_kdtree_balance(tree);
+               tree=BLI_kdtree_new(totpart);
 
-                       totpart=get_psys_tot_child(scene, psys);
-                       cfrom=from=PART_FROM_FACE;
+               for(p=0,pa=psys->particles; p<totpart; p++,pa++){
+                       psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,ornor);
+                       transform_mesh_orco_verts((Mesh*)ob->data, &orco, 1, 1);
+                       BLI_kdtree_insert(tree, p, orco, ornor);
                }
-               else{
-                       /* no need to figure out distribution */
-                       int child_nbr= get_psys_child_number(scene, psys);
-
-                       totpart= get_psys_tot_child(scene, psys);
-                       alloc_child_particles(psys, totpart);
-                       cpa=psys->child;
-                       for(i=0; i<child_nbr; i++){
-                               for(p=0; p<psys->totpart; p++,cpa++){
-                                       float length=2.0;
-                                       cpa->parent=p;
-                                       
-                                       /* create even spherical distribution inside unit sphere */
-                                       while(length>=1.0f){
-                                               cpa->fuv[0]=2.0f*BLI_frand()-1.0f;
-                                               cpa->fuv[1]=2.0f*BLI_frand()-1.0f;
-                                               cpa->fuv[2]=2.0f*BLI_frand()-1.0f;
-                                               length=len_v3(cpa->fuv);
-                                       }
 
-                                       cpa->num=-1;
-                               }
-                       }
-                       /* dmcache must be updated for parent particles if children from faces is used */
-                       psys_calc_dmcache(ob, finaldm, psys);
-
-                       return 0;
-               }
+               BLI_kdtree_balance(tree);
        }
-       else{
+       else {
+               distr = part->distr;
+               BLI_srandom(31415926 + psys->seed);
+               
                dm= CDDM_from_mesh((Mesh*)ob->data, ob);
 
-               /* special handling of grid distribution */
-               if(part->distr==PART_DISTR_GRID && from != PART_FROM_VERT){
-                       distribute_particles_in_grid(dm,psys);
-                       dm->release(dm);
-                       return 0;
-               }
-
                /* we need orco for consistent distributions */
                DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob));
 
-               distr=part->distr;
-
-               if(from==PART_FROM_VERT){
+               if(from == PART_FROM_VERT) {
                        MVert *mv= dm->getVertDataArray(dm, CD_MVERT);
                        float (*orcodata)[3]= dm->getVertDataArray(dm, CD_ORCO);
                        int totvert = dm->getNumVerts(dm);
 
                        tree=BLI_kdtree_new(totvert);
 
-                       for(p=0; p<totvert; p++){
+                       for(p=0; p<totvert; p++) {
                                if(orcodata) {
                                        VECCOPY(co,orcodata[p])
                                        transform_mesh_orco_verts((Mesh*)ob->data, &co, 1, 1);
@@ -1100,73 +1120,33 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
                }
        }
 
-       /* 1. */
-       switch(from){
-               case PART_FROM_VERT:
-                       tot = dm->getNumVerts(dm);
-                       break;
-               case PART_FROM_VOLUME:
-               case PART_FROM_FACE:
-                       tot = dm->getNumFaces(dm);
-                       break;
-               case PART_FROM_PARTICLE:
-                       if(psys->target_ob)
-                               tob=psys->target_ob;
-                       else
-                               tob=ob;
+       /* Get total number of emission elements and allocate needed arrays */
+       totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumFaces(dm);
 
-                       if((tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1))){
-                               tpars=tpsys->particles;
-                               tot=tpsys->totpart;
-                       }
-                       break;
-       }
+       if(totelem == 0){
+               distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
 
-       if(tot==0){
-               /*no_distr=1;*/ /*UNUSED*/
-               if(children){
-                       if(G.f & G_DEBUG)
-                               fprintf(stderr,"Particle child distribution error: Nothing to emit from!\n");
-                       if(psys->child) {
-                               for(p=0,cpa=psys->child; p<totpart; p++,cpa++){
-                                       cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0;
-                                       cpa->foffset= 0.0f;
-                                       cpa->parent=0;
-                                       cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0;
-                                       cpa->num= -1;
-                               }
-                       }
-               }
-               else {
-                       if(G.f & G_DEBUG)
-                               fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
-                       for(p=0,pa=psys->particles; p<totpart; p++,pa++){
-                               pa->fuv[0]=pa->fuv[1]=pa->fuv[2]= pa->fuv[3]= 0.0;
-                               pa->foffset= 0.0f;
-                               pa->num= -1;
-                       }
-               }
+               if(G.f & G_DEBUG)
+                       fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
 
                if(dm != finaldm) dm->release(dm);
                return 0;
        }
 
-       /* 2. */
-
-       weight=MEM_callocN(sizeof(float)*tot, "particle_distribution_weights");
-       index=MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
-       sum=MEM_callocN(sizeof(float)*(tot+1), "particle_distribution_sum");
-       jitoff=MEM_callocN(sizeof(float)*tot, "particle_distribution_jitoff");
+       element_weight  = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
+       particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
+       element_sum             = MEM_callocN(sizeof(float)*(totelem+1), "particle_distribution_sum");
+       jitter_offset   = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
 
-       /* 2.1 */
-       if((part->flag&PART_EDISTR || children) && ELEM(from,PART_FROM_PARTICLE,PART_FROM_VERT)==0){
+       /* Calculate weights from face areas */
+       if((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT){
                MVert *v1, *v2, *v3, *v4;
-               float totarea=0.0, co1[3], co2[3], co3[3], co4[3];
+               float totarea=0.f, co1[3], co2[3], co3[3], co4[3];
                float (*orcodata)[3];
                
                orcodata= dm->getVertDataArray(dm, CD_ORCO);
 
-               for(i=0; i<tot; i++){
+               for(i=0; i<totelem; i++){
                        MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
 
                        if(orcodata) {
@@ -1176,6 +1156,10 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
                                transform_mesh_orco_verts((Mesh*)ob->data, &co1, 1, 1);
                                transform_mesh_orco_verts((Mesh*)ob->data, &co2, 1, 1);
                                transform_mesh_orco_verts((Mesh*)ob->data, &co3, 1, 1);
+                               if(mf->v4) {
+                                       VECCOPY(co4, orcodata[mf->v4]);
+                                       transform_mesh_orco_verts((Mesh*)ob->data, &co4, 1, 1);
+                               }
                        }
                        else {
                                v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT);
@@ -1184,156 +1168,133 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
                                VECCOPY(co1, v1->co);
                                VECCOPY(co2, v2->co);
                                VECCOPY(co3, v3->co);
-                       }
-
-                       if (mf->v4){
-                               if(orcodata) {
-                                       VECCOPY(co4, orcodata[mf->v4]);
-                                       transform_mesh_orco_verts((Mesh*)ob->data, &co4, 1, 1);
-                               }
-                               else {
+                               if(mf->v4) {
                                        v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT);
                                        VECCOPY(co4, v4->co);
                                }
-                               cur= area_quad_v3(co1, co2, co3, co4);
                        }
-                       else
-                               cur= area_tri_v3(co1, co2, co3);
+
+                       cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3);
                        
-                       if(cur>maxweight)
-                               maxweight=cur;
+                       if(cur > maxweight)
+                               maxweight = cur;
 
-                       weight[i]= cur;
-                       totarea+=cur;
+                       element_weight[i] = cur;
+                       totarea += cur;
                }
 
-               for(i=0; i<tot; i++)
-                       weight[i] /= totarea;
+               for(i=0; i<totelem; i++)
+                       element_weight[i] /= totarea;
 
                maxweight /= totarea;
        }
-       else if(from==PART_FROM_PARTICLE){
-               float val=(float)tot/(float)totpart;
-               for(i=0; i<tot; i++)
-                       weight[i]=val;
-               maxweight=val;
-       }
        else{
-               float min=1.0f/(float)(MIN2(tot,totpart));
-               for(i=0; i<tot; i++)
-                       weight[i]=min;
+               float min=1.0f/(float)(MIN2(totelem,totpart));
+               for(i=0; i<totelem; i++)
+                       element_weight[i]=min;
                maxweight=min;
        }
 
-       /* 2.2 */
-       if(ELEM3(from,PART_FROM_VERT,PART_FROM_FACE,PART_FROM_VOLUME)){
-               float *vweight= psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
+       /* Calculate weights from vgroup */
+       vweight = psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY);
 
-               if(vweight){
-                       if(from==PART_FROM_VERT) {
-                               for(i=0;i<tot; i++)
-                                       weight[i]*=vweight[i];
-                       }
-                       else { /* PART_FROM_FACE / PART_FROM_VOLUME */
-                               for(i=0;i<tot; i++){
-                                       MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
-                                       tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
+       if(vweight){
+               if(from==PART_FROM_VERT) {
+                       for(i=0;i<totelem; i++)
+                               element_weight[i]*=vweight[i];
+               }
+               else { /* PART_FROM_FACE / PART_FROM_VOLUME */
+                       for(i=0;i<totelem; i++){
+                               MFace *mf=dm->getFaceData(dm,i,CD_MFACE);
+                               tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3];
                                
-                                       if(mf->v4) {
-                                               tweight += vweight[mf->v4];
-                                               tweight /= 4.0;
-                                       }
-                                       else {
-                                               tweight /= 3.0;
-                                       }
-
-                                       weight[i]*=tweight;
+                               if(mf->v4) {
+                                       tweight += vweight[mf->v4];
+                                       tweight /= 4.0;
+                               }
+                               else {
+                                       tweight /= 3.0;
                                }
+
+                               element_weight[i]*=tweight;
                        }
-                       MEM_freeN(vweight);
                }
+               MEM_freeN(vweight);
        }
 
-       /* 3. */
+       /* Calculate total weight of all elements */
        totweight= 0.0f;
-       for(i=0;i<tot; i++)
-               totweight += weight[i];
+       for(i=0;i<totelem; i++)
+               totweight += element_weight[i];
 
-       if(totweight > 0.0f)
-               totweight= 1.0f/totweight;
+       inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f);
 
-       sum[0]= 0.0f;
-       for(i=0;i<tot; i++)
-               sum[i+1]= sum[i]+weight[i]*totweight;
+       /* Calculate cumulative weights */
+       element_sum[0]= 0.0f;
+       for(i=0; i<totelem; i++)
+               element_sum[i+1]= element_sum[i] + element_weight[i] * inv_totweight;
        
+       /* Finally assign elements to particles */
        if((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) {
                float pos;
 
                for(p=0; p<totpart; p++) {
-                       /* In theory sys[tot] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
-                       pos= BLI_frand() * sum[tot];
-                       index[p]= binary_search_distribution(sum, tot, pos);
-                       index[p]= MIN2(tot-1, index[p]);
-                       jitoff[index[p]]= pos;
+                       /* In theory element_sum[totelem] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */
+                       pos= BLI_frand() * element_sum[totelem];
+                       particle_element[p]= distribute_binary_search(element_sum, totelem, pos);
+                       particle_element[p]= MIN2(totelem-1, particle_element[p]);
+                       jitter_offset[particle_element[p]]= pos;
                }
        }
        else {
                double step, pos;
                
-               step= (totpart <= 1)? 0.5: 1.0/(totpart-1);
-               pos= 1e-16f; /* tiny offset to avoid zero weight face */
+               step= (totpart < 2) ? 0.5 : 1.0/(double)totpart;
+               pos= 1e-16; /* tiny offset to avoid zero weight face */
                i= 0;
 
                for(p=0; p<totpart; p++, pos+=step) {
-                       while((i < tot) && (pos > sum[i+1]))
+                       while((i < totelem) && (pos > element_sum[i+1]))
                                i++;
 
-                       index[p]= MIN2(tot-1, i);
+                       particle_element[p]= MIN2(totelem-1, i);
 
                        /* avoid zero weight face */
-                       if(p == totpart-1 && weight[index[p]] == 0.0f)
-                               index[p]= index[p-1];
+                       if(p == totpart-1 && element_weight[particle_element[p]] == 0.0f)
+                               particle_element[p]= particle_element[p-1];
 
-                       jitoff[index[p]]= pos;
+                       jitter_offset[particle_element[p]]= pos;
                }
        }
 
-       MEM_freeN(sum);
+       MEM_freeN(element_sum);
 
-       /* for hair, sort by origindex, allows optimizations in rendering */
-       /* however with virtual parents the children need to be in random order */
+       /* For hair, sort by origindex (allows optimizations in rendering), */
+       /* however with virtual parents the children need to be in random order. */
        if(part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0)) {
-               if(from != PART_FROM_PARTICLE) {
-                       COMPARE_ORIG_INDEX = NULL;
+               COMPARE_ORIG_INDEX = NULL;
 
-                       if(from == PART_FROM_VERT) {
-                               if(dm->numVertData)
-                                       COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX);
-                       }
-                       else {
-                               if(dm->numFaceData)
-                                       COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
-                       }
-
-                       if(COMPARE_ORIG_INDEX) {
-                               qsort(index, totpart, sizeof(int), compare_orig_index);
-                               COMPARE_ORIG_INDEX = NULL;
-                       }
+               if(from == PART_FROM_VERT) {
+                       if(dm->numVertData)
+                               COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX);
+               }
+               else {
+                       if(dm->numFaceData)
+                               COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX);
                }
-       }
 
-       /* weights are no longer used except for FROM_PARTICLE, which needs them zeroed for indexing */
-       if(from==PART_FROM_PARTICLE){
-               for(i=0; i<tot; i++)
-                       weight[i]=0.0f;
+               if(COMPARE_ORIG_INDEX) {
+                       qsort(particle_element, totpart, sizeof(int), distribute_compare_orig_index);
+                       COMPARE_ORIG_INDEX = NULL;
+               }
        }
 
-       /* 4. */
+       /* Create jittering if needed */
        if(distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) {
                jitlevel= part->userjit;
                
                if(jitlevel == 0) {
-                       jitlevel= totpart/tot;
+                       jitlevel= totpart/totelem;
                        if(part->flag & PART_EDISTR) jitlevel*= 2;      /* looks better in general, not very scietific */
                        if(jitlevel<3) jitlevel= 3;
                }
@@ -1350,16 +1311,16 @@ static int psys_threads_init_distribution(ParticleThread *threads, Scene *scene,
                BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */
        }
 
-       /* 5. */
+       /* Setup things for threaded distribution */
        ctx->tree= tree;
        ctx->seams= seams;
        ctx->totseam= totseam;
        ctx->sim.psys= psys;
-       ctx->index= index;
+       ctx->index= particle_element;
        ctx->jit= jit;
        ctx->jitlevel= jitlevel;
-       ctx->jitoff= jitoff;
-       ctx->weight= weight;
+       ctx->jitoff= jitter_offset;
+       ctx->weight= element_weight;
        ctx->maxweight= maxweight;
        ctx->from= (children)? PART_FROM_CHILD: from;
        ctx->cfrom= cfrom;
@@ -1394,14 +1355,14 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
 
        pthreads= psys_threads_create(sim);
 
-       if(!psys_threads_init_distribution(pthreads, sim->scene, finaldm, from)) {
+       if(!distribute_threads_init_data(pthreads, sim->scene, finaldm, from)) {
                psys_threads_free(pthreads);
                return;
        }
 
        totthread= pthreads[0].tot;
        if(totthread > 1) {
-               BLI_init_threads(&threads, exec_distribution, totthread);
+               BLI_init_threads(&threads, distribute_threads_exec_cb, totthread);
 
                for(i=0; i<totthread; i++)
                        BLI_insert_thread(&threads, &pthreads[i]);
@@ -1409,7 +1370,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
                BLI_end_threads(&threads);
        }
        else
-               exec_distribution(&pthreads[0]);
+               distribute_threads_exec_cb(&pthreads[0]);
 
        psys_calc_dmcache(sim->ob, finaldm, sim->psys);
 
@@ -1423,17 +1384,11 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
 /* ready for future use, to emit particles without geometry */
 static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
 {
-       ParticleSystem *psys = sim->psys;
-       PARTICLE_P;
+       distribute_invalid(sim->scene, sim->psys, 0);
 
        fprintf(stderr,"Shape emission not yet possible!\n");
-
-       LOOP_PARTICLES {
-               pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0;
-               pa->foffset= 0.0f;
-               pa->num= -1;
-       }
 }
+
 static void distribute_particles(ParticleSimulationData *sim, int from)
 {
        PARTICLE_PSMD;
@@ -1449,16 +1404,9 @@ static void distribute_particles(ParticleSimulationData *sim, int from)
                distribute_particles_on_shape(sim, from);
 
        if(distr_error){
-               ParticleSystem *psys = sim->psys;
-               PARTICLE_P;
+               distribute_invalid(sim->scene, sim->psys, from);
 
                fprintf(stderr,"Particle distribution error!\n");
-
-               LOOP_PARTICLES {
-                       pa->fuv[0]=pa->fuv[1]=pa->fuv[2]=pa->fuv[3]= 0.0;
-                       pa->foffset= 0.0f;
-                       pa->num= -1;
-               }
        }
 }
 
@@ -1547,7 +1495,7 @@ void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p)
 
        pa->flag &= ~PARS_UNEXIST;
 
-       if(part->from != PART_FROM_PARTICLE && part->type != PART_FLUID) {
+       if(part->type != PART_FLUID) {
                psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f);
                
                if(ptex.exist < PSYS_FRAND(p+125))
@@ -1628,34 +1576,6 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
        int p = pa - psys->particles;
        part=psys->part;
        
-#if 0 /* deprecated code */
-       if(part->from==PART_FROM_PARTICLE){
-               float speed;
-               ParticleSimulationData tsim= {0};
-               tsim.scene= sim->scene;
-               tsim.ob= psys->target_ob ? psys->target_ob : ob;
-               tsim.psys = BLI_findlink(&tsim.ob->particlesystem, sim->psys->target_psys-1);
-
-               state.time = pa->time;
-               if(pa->num == -1)
-                       memset(&state, 0, sizeof(state));
-               else
-                       psys_get_particle_state(&tsim, pa->num, &state, 1);
-               psys_get_from_key(&state, loc, nor, rot, 0);
-
-               mul_qt_v3(rot, vtan);
-               mul_qt_v3(rot, utan);
-
-               speed= normalize_v3_v3(p_vel, state.vel);
-               mul_v3_fl(p_vel, dot_v3v3(r_vel, p_vel));
-               VECSUB(p_vel, r_vel, p_vel);
-               normalize_v3(p_vel);
-               mul_v3_fl(p_vel, speed);
-
-               VECCOPY(pa->fuv, loc); /* abusing pa->fuv (not used for "from particle") for storing emit location */
-       }
-       else{
-#endif
        /* get precise emitter matrix if particle is born */
        if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= sim->psys->cfra) {
                /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
@@ -3156,7 +3076,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
                        if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
                                distribute_particles(sim, PART_FROM_CHILD);
 
-                               if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
+                               if(part->childtype==PART_CHILD_FACES && part->parents!=0.0)
                                        psys_find_parents(sim);
                        }
                }
@@ -3923,13 +3843,6 @@ static void psys_changed_type(ParticleSimulationData *sim)
 
        BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys);
 
-       if(part->from == PART_FROM_PARTICLE) {
-               //if(part->type != PART_REACTOR)
-               part->from = PART_FROM_FACE;
-               if(part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT)
-                       part->distr = PART_DISTR_JIT;
-       }
-
        if(part->phystype != PART_PHYS_KEYED)
                sim->psys->flag &= ~PSYS_KEYED;
 
@@ -3937,6 +3850,9 @@ static void psys_changed_type(ParticleSimulationData *sim)
                if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
                        part->ren_as = PART_DRAW_PATH;
 
+               if(part->distr == PART_DISTR_GRID)
+                       part->distr = PART_DISTR_JIT;
+
                if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
                        part->draw_as = PART_DRAW_REND;
 
index ae97b023e5883588500386c882f769e3e081bc19..b146d49365c52f68e49d013c6b5ed79699ec7528 100644 (file)
@@ -339,7 +339,7 @@ typedef struct ParticleSystem{                              /* note, make sure all (runtime) are NULL's in
 #define PART_FROM_VERT         0
 #define PART_FROM_FACE         1
 #define PART_FROM_VOLUME       2
-#define PART_FROM_PARTICLE     3
+/* #define PART_FROM_PARTICLE  3  deprecated! */ 
 #define PART_FROM_CHILD                4
 
 /* part->distr */
index f1142e16e8e79843ca5d0dca09796927c9fc3b9f..57d6e72a102f5aed4e355f36365f24a7bbbf44b6 100644 (file)
@@ -60,7 +60,19 @@ EnumPropertyItem part_reactor_from_items[] = {
        {PART_FROM_VERT, "VERT", 0, "Verts", ""},
        {PART_FROM_FACE, "FACE", 0, "Faces", ""},
        {PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
-       {PART_FROM_PARTICLE, "PARTICLE", 0, "Particle", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem part_dist_items[] = {
+       {PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
+       {PART_DISTR_RAND, "RAND", 0, "Random", ""},
+       {PART_DISTR_GRID, "GRID", 0, "Grid", ""},
+       {0, NULL, 0, NULL, NULL}
+};
+
+EnumPropertyItem part_hair_dist_items[] = {
+       {PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
+       {PART_DISTR_RAND, "RAND", 0, "Random", ""},
        {0, NULL, 0, NULL, NULL}
 };
 
@@ -665,6 +677,16 @@ static EnumPropertyItem *rna_Particle_from_itemf(bContext *C, PointerRNA *ptr, i
                return part_from_items;
 }
 
+static EnumPropertyItem *rna_Particle_dist_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+       ParticleSettings *part = ptr->id.data;
+
+       if(part->type==PART_HAIR)
+               return part_hair_dist_items;
+       else
+               return part_dist_items;
+}
+
 static EnumPropertyItem *rna_Particle_draw_as_itemf(bContext *C, PointerRNA *ptr, int *free)
 {
        ParticleSettings *part = ptr->id.data;
@@ -1361,13 +1383,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}
        };
 
-       static EnumPropertyItem dist_items[] = {
-               {PART_DISTR_JIT, "JIT", 0, "Jittered", ""},
-               {PART_DISTR_RAND, "RAND", 0, "Random", ""},
-               {PART_DISTR_GRID, "GRID", 0, "Grid", ""},
-               {0, NULL, 0, NULL, NULL}
-       };
-
        static EnumPropertyItem phys_type_items[] = {
                {PART_PHYS_NO, "NO", 0, "No", ""},
                {PART_PHYS_NEWTON, "NEWTON", 0, "Newtonian", ""},
@@ -1609,7 +1624,9 @@ static void rna_def_particle_settings(BlenderRNA *brna)
        prop= RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "distr");
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
-       RNA_def_property_enum_items(prop, dist_items);
+       RNA_def_property_enum_items(prop, part_dist_items);
+       RNA_def_property_enum_items(prop, part_draw_as_items);
+       RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_dist_itemf");
        RNA_def_property_ui_text(prop, "Distribution", "How to distribute particles on selected element");
        RNA_def_property_update(prop, 0, "rna_Particle_reset");
 
index bbf41f7ac6d63389df5ade32c403fd4a04749349..81652f5a290c1b0dbd3593520fc325aa5a878ea9 100644 (file)
@@ -1713,25 +1713,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                bb.totnum = totpart+totchild;
                bb.uv_split = part->bb_uv_split;
        }
-
-#if 0 // XXX old animation system
-/* 2.3 setup time */
-       if(part->flag&PART_ABS_TIME && part->ipo) {
-               calc_ipo(part->ipo, cfra);
-               execute_ipo((ID *)part, part->ipo);
-       }
-
-       if(part->flag & PART_GLOB_TIME)
-#endif // XXX old animation system
-
-///* 2.4 setup reactors */
-//     if(part->type == PART_REACTOR){
-//             psys_get_reactor_target(ob, psys, &tob, &tpsys);
-//             if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
-//                     psmd = psys_get_modifier(tob,tpsys);
-//                     tpart = tpsys->part;
-//             }
-//     }
        
 /* 2.5 setup matrices */
        mul_m4_m4m4(mat, ob->obmat, re->viewmat);
@@ -1828,7 +1809,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                        hasize = ma->hasize;
 
                        /* get orco */
-                       if(tpsys && (part->from==PART_FROM_PARTICLE || part->phystype==PART_PHYS_NO)){
+                       if(tpsys && part->phystype==PART_PHYS_NO){
                                tpa=tpsys->particles+pa->num;
                                psys_particle_on_emitter(psmd,tpart->from,tpa->num,pa->num_dmcache,tpa->fuv,tpa->foffset,co,nor,0,0,sd.orco,0);
                        }
@@ -1892,7 +1873,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
                        }
 
                        /* get uvco & mcol */
-                       if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES) {
+                       if(part->childtype==PART_CHILD_FACES) {
                                get_particle_uvco_mcol(PART_FROM_FACE, psmd->dm, cpa->fuv, cpa->num, &sd);
                        }
                        else {