diff options
Diffstat (limited to 'source/blender/blenkernel/intern/particle_system.c')
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 928730fb1f0..f8b1852b728 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1,7 +1,7 @@ /* particle_system.c * * - * $Id: particle_system.c $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -75,6 +75,7 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_scene.h" +#include "BKE_bvhutils.h" #include "PIL_time.h" @@ -1294,7 +1295,8 @@ int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, Derive 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); @@ -1611,7 +1613,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps NormalQuat(pa->r_rot); - if(part->distr!=PART_DISTR_GRID && part->from != PART_FROM_VERT){ + 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])) pa->flag |= PARS_UNEXIST; @@ -1733,6 +1735,8 @@ void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, Partic VECSUB(p_vel,pa->r_ve,p_vel); Normalize(p_vel); VecMulf(p_vel,speed); + + 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 */ @@ -2447,7 +2451,6 @@ void psys_end_effectors(ParticleSystem *psys) if(ec->rng) rng_free(ec->rng); - } BLI_freelistN(lb); @@ -2486,7 +2489,12 @@ static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, Pa ec->locations=MEM_callocN(totpart*3*sizeof(float),"particle locations"); for(p=0,pa=psys->particles; p<totpart; p++, pa++){ - psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); + if(part->from == PART_FROM_PARTICLE) { + VECCOPY(loc, pa->fuv); + } + else + psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,0,0); + Mat4MulVecfl(ob->obmat,loc); ec->distances[p]=VecLenf(loc,vec); VECSUB(loc,loc,vec); @@ -2539,6 +2547,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, ParticleData *epa; ParticleKey estate; PartDeflect *pd; + SurfaceModifierData *surmd = NULL; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; float distance, vec_to_part[3]; @@ -2566,8 +2575,34 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, if(psys->part->type!=PART_HAIR && psys->part->integrator) where_is_object_time(scene, eob,cfra); - /* use center of object for distance calculus */ - VecSubf(vec_to_part, state->co, eob->obmat[3]); + if(pd && pd->flag&PFIELD_SURFACE) { + surmd = (SurfaceModifierData *)modifiers_findByType ( eob, eModifierType_Surface ); + } + if(surmd) { + /* closest point in the object surface is an effector */ + BVHTreeNearest nearest; + float velocity[3]; + + nearest.index = -1; + nearest.dist = FLT_MAX; + + /* using velocity corrected location allows for easier sliding over effector surface */ + VecCopyf(velocity, state->vel); + VecMulf(velocity, psys_get_timestep(psys->part)); + VecAddf(vec_to_part, state->co, velocity); + + BLI_bvhtree_find_nearest(surmd->bvhtree->tree, vec_to_part, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree); + + if(nearest.index != -1) { + VecSubf(vec_to_part, state->co, nearest.co); + } + else + vec_to_part[0] = vec_to_part[1] = vec_to_part[2] = 0.0f; + } + else + /* use center of object for distance calculus */ + VecSubf(vec_to_part, state->co, eob->obmat[3]); + distance = VecLength(vec_to_part); falloff=effector_falloff(pd,eob->obmat[2],vec_to_part); |