diff options
Diffstat (limited to 'source/blender/blenkernel/intern/particle.c')
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 284 |
1 files changed, 206 insertions, 78 deletions
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 44ee5c236fa..7d998a481f6 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1,7 +1,7 @@ /* particle.c * * - * $Id: particle.c $ + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -46,7 +46,7 @@ #include "DNA_object_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" -#include "DNA_ipo_types.h" +#include "DNA_ipo_types.h" // XXX old animation system stuff to remove! #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -65,20 +65,17 @@ #include "BKE_displist.h" #include "BKE_particle.h" #include "BKE_DerivedMesh.h" -#include "BKE_ipo.h" #include "BKE_object.h" #include "BKE_softbody.h" #include "BKE_material.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_depsgraph.h" -#include "BKE_bad_level_calls.h" #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_cdderivedmesh.h" #include "BKE_pointcache.h" -#include "blendef.h" #include "RE_render_ext.h" static void key_from_object(Object *ob, ParticleKey *key); @@ -242,11 +239,11 @@ void psys_change_act(void *ob_v, void *act_v) npsys->flag |= PSYS_CURRENT; } } -Object *psys_get_lattice(Object *ob, ParticleSystem *psys) +Object *psys_get_lattice(Scene *scene, Object *ob, ParticleSystem *psys) { Object *lattice=0; - if(psys_in_edit_mode(psys)==0){ + if(psys_in_edit_mode(scene, psys)==0){ ModifierData *md = (ModifierData*)psys_get_modifier(ob,psys); @@ -287,9 +284,9 @@ int psys_ob_has_hair(Object *ob) return 0; } -int psys_in_edit_mode(ParticleSystem *psys) +int psys_in_edit_mode(Scene *scene, ParticleSystem *psys) { - return ((G.f & G_PARTICLEEDIT) && psys==psys_get_current(OBACT) && psys->edit); + return ((G.f & G_PARTICLEEDIT) && psys==psys_get_current((scene->basact)->object) && psys->edit); } int psys_check_enabled(Object *ob, ParticleSystem *psys) { @@ -394,7 +391,8 @@ void psys_free(Object *ob, ParticleSystem * psys) free_keyed_keys(psys); - PE_free_particle_edit(psys); + if(psys->edit && psys->free_edit) + psys->free_edit(psys); if(psys->particles){ MEM_freeN(psys->particles); @@ -1410,6 +1408,7 @@ static float vert_weight(MDeformVert *dvert, int group) } return 0.0; } + static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, short type, short axis, float obmat[][4]) { float vec[3]={0.0,0.0,0.0}, q1[4]={1,0,0,0},q2[4]; @@ -1461,7 +1460,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); @@ -1544,6 +1543,7 @@ static void do_prekink(ParticleKey *state, ParticleKey *par, float *par_rot, flo break; } } + static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump) { if(par && clumpfac!=0.0){ @@ -1561,7 +1561,8 @@ static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clu VecLerpf(state->co,state->co,par->co,clump); } } -int do_guide(ParticleKey *state, int pa_num, float time, ListBase *lb) + +int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase *lb) { PartDeflect *pd; ParticleEffectorCache *ec; @@ -1644,7 +1645,7 @@ int do_guide(ParticleKey *state, int pa_num, float time, ListBase *lb) /* curve taper */ if(cu->taperobj) - VecMulf(pa_loc,calc_taper(cu->taperobj,(int)(f_force*guidetime*100.0),100)); + VecMulf(pa_loc, calc_taper(scene, cu->taperobj, (int)(f_force*guidetime*100.0), 100)); /* TODO */ //else{ ///* curve size*/ @@ -1719,7 +1720,7 @@ static void do_rough_end(float *loc, float t, float fac, float shape, ParticleKe VECADD(state->co,state->co,rough); } -static void do_path_effectors(Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) +static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec) { float force[3] = {0.0f,0.0f,0.0f}, vel[3] = {0.0f,0.0f,0.0f}; ParticleKey eff_key; @@ -1730,7 +1731,7 @@ static void do_path_effectors(Object *ob, ParticleSystem *psys, int i, ParticleC QUATCOPY(eff_key.rot,(ca-1)->rot); pa= psys->particles+i; - do_effectors(i, pa, &eff_key, ob, psys, rootco, force, vel, dfra, cfra); + do_effectors(i, pa, &eff_key, scene, ob, psys, rootco, force, vel, dfra, cfra); VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps); @@ -1805,10 +1806,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); } @@ -1853,25 +1857,29 @@ static void get_strand_normal(Material *ma, float *surfnor, float surfdist, floa VECCOPY(nor, vnor); } -int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) +int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate) { ParticleThreadContext *ctx= threads[0].ctx; Object *ob= ctx->ob; ParticleSystem *psys= ctx->psys; ParticleSettings *part = psys->part; - ParticleEditSettings *pset = &G.scene->toolsettings->particle; + ParticleEditSettings *pset = &scene->toolsettings->particle; int totparent=0, between=0; int steps = (int)pow(2.0,(double)part->draw_step); int totchild = psys->totchild; int i, seed, totthread= threads[0].tot; /*---start figuring out what is actually wanted---*/ - if(psys_in_edit_mode(psys)) + if(psys_in_edit_mode(scene, psys)) if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_SHOW_CHILD)==0) totchild=0; 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,9 +1912,10 @@ 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); + psys->lattice = psys_get_lattice(scene, ob, psys); /* cache all relevant vertex groups if they exist */ if(part->from!=PART_FROM_PARTICLE){ @@ -1921,10 +1930,12 @@ int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate) } /* set correct ipo timing */ +#if 0 // XXX old animation system if(part->flag&PART_ABS_TIME && part->ipo){ calc_ipo(part->ipo, cfra); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system return 1; } @@ -1941,14 +1952,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) { @@ -2039,20 +2050,23 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, keys->steps = ctx->steps; /* correct child ipo timing */ +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ float dsta=part->end-part->sta; calc_ipo(part->ipo, 100.0f*(ctx->cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0]))); execute_ipo((ID *)part, part->ipo); } +#endif // XXX old animation system /* get different child parameters from textures & vgroups */ ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]); ptex.clump=1.0; ptex.kink=1.0; ptex.rough= 1.0; + ptex.exist= 1.0; get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,&ptex, - MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); + MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH); pa_length=ptex.length; pa_clump=ptex.clump; @@ -2062,6 +2076,11 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, pa_roughe=ptex.rough; pa_effector= 1.0f; + if(ptex.exist < cpa->rand[1]) { + keys->steps = -1; + return; + } + if(ctx->vg_length) pa_length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length); if(ctx->vg_clump) @@ -2119,7 +2138,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, if(part->flag & PART_CHILD_EFFECT) { for(k=0,state=keys; k<=ctx->steps; k++,state++) { if(k) { - do_path_effectors(ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, pa_effector, 0.0f, ctx->cfra, &eff_length, eff_vec); + do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, pa_effector, 0.0f, ctx->cfra, &eff_length, eff_vec); } else { VecSubf(eff_vec,(state+1)->co,state->co); @@ -2132,25 +2151,26 @@ 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 */ if(part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ - guided = do_guide((ParticleKey*)state, cpa->parent, t, &(psys->effectors)); + guided = do_guide(ctx->scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors)); 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); @@ -2249,16 +2269,21 @@ 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; } -void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) { ParticleSettings *part = psys->part; ParticleThread *pthreads; @@ -2267,9 +2292,9 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed ListBase threads; int i, totchild, totparent, totthread; - pthreads= psys_threads_create(ob, psys); + pthreads= psys_threads_create(scene, ob, psys); - if(!psys_threads_init_path(pthreads, cfra, editupdate)) { + if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) { psys_threads_free(pthreads); return; } @@ -2291,6 +2316,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++) @@ -2308,11 +2349,11 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed /* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */ /* -Makes child strands possible and creates them too into the cache. */ /* -Cached path data is also used to determine cut position for the editmode tool. */ -void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupdate) +void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate) { ParticleCacheKey *ca, **cache=psys->pathcache; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - ParticleEditSettings *pset = &G.scene->toolsettings->particle; + ParticleEditSettings *pset = &scene->toolsettings->particle; ParticleSettings *part = psys->part; ParticleData *pa; @@ -2328,13 +2369,12 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda Material *ma; float birthtime = 0.0, dietime = 0.0; - float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = G.scene->r.frs_sec; + float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec; float col[3] = {0.5f, 0.5f, 0.5f}; float prev_tangent[3], hairmat[4][4]; int k,i; int steps = (int)pow(2.0, (double)psys->part->draw_step); int totpart = psys->totpart; - char nosel[4], sel[4]; float sel_col[3]; float nosel_col[3]; float length, vec[3]; @@ -2346,25 +2386,25 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) return; - if(psys->renderdata) + if(psys->renderdata) { steps = (int)pow(2.0, (double)psys->part->ren_step); - else if(psys_in_edit_mode(psys)){ + } + else if(psys_in_edit_mode(scene, psys)) { edit=psys->edit; //timed = edit->draw_timed; - PE_get_colors(sel,nosel); - if(pset->brushtype == PE_BRUSH_WEIGHT){ + if(pset->brushtype == PE_BRUSH_WEIGHT) { sel_col[0] = sel_col[1] = sel_col[2] = 1.0f; nosel_col[0] = nosel_col[1] = nosel_col[2] = 0.0f; } else{ - sel_col[0] = (float)sel[0] / 255.0f; - sel_col[1] = (float)sel[1] / 255.0f; - sel_col[2] = (float)sel[2] / 255.0f; - nosel_col[0] = (float)nosel[0] / 255.0f; - nosel_col[1] = (float)nosel[1] / 255.0f; - nosel_col[2] = (float)nosel[2] / 255.0f; + sel_col[0] = (float)edit->sel_col[0] / 255.0f; + sel_col[1] = (float)edit->sel_col[1] / 255.0f; + sel_col[2] = (float)edit->sel_col[2] / 255.0f; + nosel_col[0] = (float)edit->nosel_col[0] / 255.0f; + nosel_col[1] = (float)edit->nosel_col[1] / 255.0f; + nosel_col[2] = (float)edit->nosel_col[2] / 255.0f; } } @@ -2384,7 +2424,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda soft= NULL; } - psys->lattice = psys_get_lattice(ob, psys); + psys->lattice = psys_get_lattice(scene, ob, psys); ma= give_current_material(ob, psys->part->omat); if(ma && (psys->part->draw & PART_DRAW_MAT_COL)) VECCOPY(col, &ma->r) @@ -2577,16 +2617,16 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda for(k=0, ca=cache[i]; k<=steps; k++, ca++) { /* apply effectors */ if(!(psys->part->flag & PART_CHILD_EFFECT) && edit==0 && k) - do_path_effectors(ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); + do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec); /* apply guide curves to path data */ if(edit==0 && psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0) /* ca is safe to cast, since only co and vel are used */ - do_guide((ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); + do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors); /* apply lattice */ if(psys->lattice && edit==0) - calc_latt_deform(ca->co, 1.0f); + calc_latt_deform(psys->lattice, ca->co, 1.0f); /* figure out rotation */ @@ -2666,8 +2706,8 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda psys->totcached = totpart; if(psys && psys->lattice){ - end_latt_deform(); - psys->lattice=0; + end_latt_deform(psys->lattice); + psys->lattice= NULL; } if(vg_effector) @@ -2921,7 +2961,9 @@ static void default_particle_settings(ParticleSettings *part) part->boidfac[i]=0.5; } +#if 0 // XXX old animation system part->ipo = NULL; +#endif // XXX old animation system part->simplify_refsize= 1920; part->simplify_rate= 1.0f; @@ -3011,7 +3053,7 @@ void make_local_particlesettings(ParticleSettings *part) } /* should be integrated to depgraph signals */ -void psys_flush_settings(ParticleSettings *part, int event, int hair_recalc) +void psys_flush_settings(struct Scene *scene, ParticleSettings *part, int event, int hair_recalc) { Base *base; Object *ob, *tob; @@ -3019,7 +3061,7 @@ void psys_flush_settings(ParticleSettings *part, int event, int hair_recalc) int flush; /* update all that have same particle settings */ - for(base = G.scene->base.first; base; base= base->next) { + for(base = scene->base.first; base; base= base->next) { if(base->object->particlesystem.first) { ob=base->object; flush=0; @@ -3044,12 +3086,12 @@ void psys_flush_settings(ParticleSettings *part, int event, int hair_recalc) } } if(flush) - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } } } -LinkNode *psys_using_settings(ParticleSettings *part, int flush_update) +LinkNode *psys_using_settings(struct Scene *scene, ParticleSettings *part, int flush_update) { Object *ob, *tob; ParticleSystem *psys, *tpsys; @@ -3077,7 +3119,7 @@ LinkNode *psys_using_settings(ParticleSettings *part, int flush_update) } if(flush_update && found) - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + DAG_object_flush_update(scene, ob, OB_RECALC_DATA); } return node; @@ -3165,6 +3207,8 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_KINK); if((event & mtex->pmapto) & MAP_PA_ROUGH) ptex->rough= texture_value_blend(def,ptex->rough,value,var,blend,neg & MAP_PA_ROUGH); + if((event & mtex->pmapto) & MAP_PA_DENS) + ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS); } } if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); } @@ -3172,6 +3216,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); } if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); } if(event & MAP_PA_ROUGH) { CLAMP(ptex->rough,0.0,1.0); } + if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); } } void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event) { @@ -3256,10 +3301,12 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, size=ptex.size; } +#if 0 // XXX old animation system if(icu_size){ calc_icu(icu_size,pa->time); size*=icu_size->curval; } +#endif // XXX old animation system if(vg_size) size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size); @@ -3292,11 +3339,12 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra) float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time) { ParticleSettings *part = psys->part; - float size, time; + float size; // time XXX if(part->childtype==PART_CHILD_FACES){ size=part->size; +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ IpoCurve *icu; @@ -3313,6 +3361,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, size = icu->curval; } } +#endif // XXX old animation system } else size=psys->particles[cpa->parent].size; @@ -3325,7 +3374,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, return size; } /* get's hair (or keyed) particles state at the "path time" specified in state->time */ -void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) +void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel) { ParticleSettings *part = psys->part; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); @@ -3337,7 +3386,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle HairKey *hkey[2] = {NULL, NULL}; ParticleKey *par=0, keys[4]; - float t, real_t, dfra, keytime, frs_sec = G.scene->r.frs_sec; + float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec; float co[3], orco[3]; float hairmat[4][4]; float pa_clump = 0.0, pa_kink = 0.0; @@ -3348,7 +3397,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle float *cpa_fuv; int cpa_num; short cpa_from; - //if(psys_in_edit_mode(psys)){ + //if(psys_in_edit_mode(scene, psys)){ // if((psys->edit_path->flag & PSYS_EP_SHOW_CHILD)==0) // totchild=0; // edit=1; @@ -3432,7 +3481,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle } //} - //psys_get_particle_on_path(bsys,p,t,bkey,ckey[0]); + //psys_get_particle_on_path(scene, bsys,p,t,bkey,ckey[0]); //if(part->rotfrom==PART_ROT_KEYS) // QuatInterpol(state->rot,k2.rot,k3.rot,keytime); @@ -3470,12 +3519,12 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle Mat4Mul3Vecfl(hairmat, state->vel); if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) { - do_guide(state, p, state->time, &psys->effectors); + do_guide(scene, state, p, state->time, &psys->effectors); /* TODO: proper velocity handling */ } if(psys->lattice && edit==0) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } } } @@ -3486,6 +3535,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; } @@ -3496,7 +3549,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle /* get parent states */ while(w<4 && cpa->pa[w]>=0){ keys[w].time = t; - psys_get_particle_on_path(ob, psys, cpa->pa[w], keys+w, 1); + psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1); w++; } @@ -3522,7 +3575,7 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle /* get the parent state */ keys->time = t; - psys_get_particle_on_path(ob,psys,cpa->parent,keys,1); + psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1); /* get the original coordinates (orco) for texture usage */ pa=psys->particles+cpa->parent; @@ -3535,11 +3588,13 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle } /* correct child ipo timing */ +#if 0 // XXX old animation system if((part->flag&PART_ABS_TIME)==0 && part->ipo){ calc_ipo(part->ipo, 100.0f*t); execute_ipo((ID *)part, part->ipo); } - +#endif // XXX old animation system + /* get different child parameters from textures & vgroups */ ptex.clump=1.0; ptex.kink=1.0; @@ -3608,19 +3663,19 @@ void psys_get_particle_on_path(Object *ob, ParticleSystem *psys, int p, Particle //if(vel){ // if(t>=0.001f){ // tstate.time=t-0.001f; - // psys_get_particle_on_path(ob,psys,p,&tstate,0); + // psys_get_particle_on_path(scene,ob,psys,p,&tstate,0); // VECSUB(state->vel,state->co,tstate.co); // } // else{ // tstate.time=t+0.001f; - // psys_get_particle_on_path(ob,psys,p,&tstate,0); + // psys_get_particle_on_path(scene, ob,psys,p,&tstate,0); // VECSUB(state->vel,tstate.co,state->co); // } //} } } /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */ -int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){ +int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){ ParticleSettings *part=psys->part; ParticleData *pa=0; float cfra; @@ -3630,7 +3685,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey if(state->time>0) cfra=state->time; else - cfra=bsystem_time(0,(float)G.scene->r.cfra,0.0); + cfra= bsystem_time(scene, 0, (float)scene->r.cfra,0.0); if(psys->totchild && p>=totpart){ if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){ @@ -3666,7 +3721,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey else state->time= (cfra-pa->time)/(pa->dietime-pa->time); - psys_get_particle_on_path(ob,psys,p,state,1); + psys_get_particle_on_path(scene, ob, psys, p, state,1); return 1; } else{ @@ -3698,7 +3753,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0); if(psys->lattice) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } else{ if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */ @@ -3710,7 +3765,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey /* let's interpolate to try to be as accurate as possible */ if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { ParticleKey keys[4]; - float dfra, keytime, frs_sec = G.scene->r.frs_sec; + float dfra, keytime, frs_sec = scene->r.frs_sec; if(pa->prev_state.time >= pa->state.time) { /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ @@ -3750,7 +3805,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey } if(psys->lattice) - calc_latt_deform(state->co,1.0f); + calc_latt_deform(psys->lattice, state->co,1.0f); } } @@ -3860,3 +3915,76 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys *scale= len; } +void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]) +{ + float onevec[3] = {0.0f,0.0f,0.0f}, tvec[3], tvec2[3]; + + xvec[0] = 1.0f; xvec[1] = 0.0f; xvec[2] = 0.0f; + yvec[0] = 0.0f; yvec[1] = 1.0f; yvec[2] = 0.0f; + + if(bb->align < PART_BB_VIEW) + onevec[bb->align]=1.0f; + + if(bb->lock && (bb->align == PART_BB_VIEW)) { + VECCOPY(xvec, bb->ob->obmat[0]); + Normalize(xvec); + + VECCOPY(yvec, bb->ob->obmat[1]); + Normalize(yvec); + + VECCOPY(zvec, bb->ob->obmat[2]); + Normalize(zvec); + } + else if(bb->align == PART_BB_VEL) { + float temp[3]; + + VECCOPY(temp, bb->vel); + Normalize(temp); + + VECSUB(zvec, bb->ob->obmat[3], bb->vec); + + if(bb->lock) { + float fac = -Inpf(zvec, temp); + + VECADDFAC(zvec, zvec, temp, fac); + } + Normalize(zvec); + + Crossf(xvec,temp,zvec); + Normalize(xvec); + + Crossf(yvec,zvec,xvec); + } + else { + VECSUB(zvec, bb->ob->obmat[3], bb->vec); + if(bb->lock) + zvec[bb->align] = 0.0f; + Normalize(zvec); + + if(bb->align < PART_BB_VIEW) + Crossf(xvec, onevec, zvec); + else + Crossf(xvec, bb->ob->obmat[1], zvec); + Normalize(xvec); + + Crossf(yvec,zvec,xvec); + } + + VECCOPY(tvec, xvec); + VECCOPY(tvec2, yvec); + + VecMulf(xvec, cos(bb->tilt * (float)M_PI)); + VecMulf(tvec2, sin(bb->tilt * (float)M_PI)); + VECADD(xvec, xvec, tvec2); + + VecMulf(yvec, cos(bb->tilt * (float)M_PI)); + VecMulf(tvec, -sin(bb->tilt * (float)M_PI)); + VECADD(yvec, yvec, tvec); + + VecMulf(xvec, bb->size); + VecMulf(yvec, bb->size); + + VECADDFAC(center, bb->vec, xvec, bb->offset[0]); + VECADDFAC(center, center, yvec, bb->offset[1]); +} + |