diff options
author | Janne Karhu <jhkarh@gmail.com> | 2009-04-06 04:10:52 +0400 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2009-04-06 04:10:52 +0400 |
commit | 58b1e04fe0a026d57c3f456393468bd0d596054b (patch) | |
tree | ba247e46739d9692950fcad6e159ad6f7432a5a7 /source | |
parent | 9a1e1912e173262436598efe62f4ff0134ea04a7 (diff) |
Fix for: [#18371] VParent breaks fur effects.
-Virtual parents were not randomly selected due to optimization in child particle distribution code.
-Wave-kink had a wrong matrix multiplication.
-Amount of virtual parents wasn't scaled properly to the amount of children rendered.
-Calculating virtual parents is now thread safe.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 56 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 3 |
3 files changed, 48 insertions, 13 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 5dbfe2fe520..5f5635bae1f 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -173,7 +173,7 @@ typedef struct ParticleThreadContext { /* path caching */ int editupdate, between, steps; - int totchild, totparent; + int totchild, totparent, parent_pass; float cfra; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 4eabb82f6cb..3fea9e44acb 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1461,7 +1461,7 @@ static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, flo case PART_KINK_WAVE: vec[axis]=1.0; if(obmat) - Mat4MulVecfl(obmat,vec); + Mat4Mul3Vecfl(obmat,vec); if(par_rot) QuatMulVecf(par_rot,vec); @@ -1805,10 +1805,13 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys int from=PART_FROM_FACE; totparent=(int)(totchild*part->parents*0.3); + if(G.rendering && part->child_nbr && part->ren_child_nbr) + totparent*=(float)part->child_nbr/(float)part->ren_child_nbr; + tree=BLI_kdtree_new(totparent); for(p=0,cpa=psys->child; p<totparent; p++,cpa++){ - psys_particle_on_emitter(psmd,from,cpa->num,-1,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); + psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0); BLI_kdtree_insert(tree, p, orco, NULL); } @@ -1872,6 +1875,10 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ totparent=(int)(totchild*part->parents*0.3); + + if(G.rendering && part->child_nbr && part->ren_child_nbr) + totparent*=(float)part->child_nbr/(float)part->ren_child_nbr; + /* part->parents could still be 0 so we can't test with totparent */ between=1; } @@ -1904,6 +1911,7 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) ctx->steps= steps; ctx->totchild= totchild; ctx->totparent= totparent; + ctx->parent_pass= 0; ctx->cfra= cfra; psys->lattice = psys_get_lattice(ob, psys); @@ -1941,14 +1949,14 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *state, *par = NULL, *key[4]; ParticleData *pa=NULL; ParticleTexture ptex; - float *cpa_fuv=0; + float *cpa_fuv=0, *par_rot=0; float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3]; float branch_begin, branch_end, branch_prob, branchfac, rough_rand; float pa_rough1, pa_rough2, pa_roughe; float length, pa_length, pa_clump, pa_kink, pa_effector; float max_length = 1.0f, cur_length = 0.0f; float eff_length, eff_vec[3]; - int k, cpa_num, guided=0; + int k, cpa_num, guided = 0; short cpa_from; if(part->flag & PART_BRANCHING) { @@ -2138,15 +2146,16 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, t=(float)k/(float)ctx->steps; if(ctx->totparent){ - if(i>=ctx->totparent) - /* this is not threadsafe, but should only happen for - * branching particles particles, which are not threaded */ + if(i>=ctx->totparent) { + /* this is now threadsafe, virtual parents are calculated before rest of children */ par = cache[cpa->parent] + k; + } else par=0; } else if(cpa->parent>=0){ par=pcache[cpa->parent]+k; + par_rot = par->rot; } /* apply different deformations to the child path */ @@ -2156,7 +2165,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, if(guided==0){ if(part->kink) - do_prekink((ParticleKey*)state, (ParticleKey*)par, par->rot, t, + do_prekink((ParticleKey*)state, (ParticleKey*)par, par_rot, t, part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat); do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump); @@ -2255,10 +2264,15 @@ static void *exec_child_path_cache(void *data) ParticleSystem *psys= ctx->psys; ParticleCacheKey **cache= psys->childcache; ChildParticle *cpa; - int i, totchild= ctx->totchild; + int i, totchild= ctx->totchild, first= 0; + + if(thread->tot > 1){ + first= ctx->parent_pass? 0 : ctx->totparent; + totchild= ctx->parent_pass? ctx->totparent : ctx->totchild; + } - cpa= psys->child + thread->num; - for(i=thread->num; i<totchild; i+=thread->tot, cpa+=thread->tot) + cpa= psys->child + first + thread->num; + for(i=first+thread->num; i<totchild; i+=thread->tot, cpa+=thread->tot) psys_thread_create_path(thread, cpa, cache[i], i); return 0; @@ -2297,6 +2311,22 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed totthread= pthreads[0].tot; if(totthread > 1) { + + /* make virtual child parents thread safe by calculating them first */ + if(totparent) { + BLI_init_threads(&threads, exec_child_path_cache, totthread); + + for(i=0; i<totthread; i++) { + pthreads[i].ctx->parent_pass = 1; + BLI_insert_thread(&threads, &pthreads[i]); + } + + BLI_end_threads(&threads); + + for(i=0; i<totthread; i++) + pthreads[i].ctx->parent_pass = 0; + } + BLI_init_threads(&threads, exec_child_path_cache, totthread); for(i=0; i<totthread; i++) @@ -3495,6 +3525,10 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ totparent=(int)(totchild*part->parents*0.3); + + if(G.rendering && part->child_nbr && part->ren_child_nbr) + totparent*=(float)part->child_nbr/(float)part->ren_child_nbr; + /* part->parents could still be 0 so we can't test with totparent */ between=1; } diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 2728addeddd..8720edf6c24 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1301,7 +1301,8 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm MEM_freeN(sum); /* for hair, sort by origindex, allows optimizations in rendering */ - if(part->type == PART_HAIR) { + /* 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)) { COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX); if(COMPARE_ORIG_INDEX) qsort(index, totpart, sizeof(int), compare_orig_index); |