Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/particle.c')
-rw-r--r--source/blender/blenkernel/intern/particle.c835
1 files changed, 363 insertions, 472 deletions
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 2d3e3210afc..f4f5a1364a3 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -53,7 +53,7 @@
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BLI_kdtree.h"
-#include "BLI_linklist.h"
+#include "BLI_listbase.h"
#include "BLI_rand.h"
#include "BLI_threads.h"
@@ -61,6 +61,7 @@
#include "BKE_boids.h"
#include "BKE_cloth.h"
+#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_lattice.h"
@@ -69,7 +70,7 @@
#include "BKE_particle.h"
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
-#include "BKE_softbody.h"
+#include "BKE_cloth.h"
#include "BKE_material.h"
#include "BKE_key.h"
#include "BKE_library.h"
@@ -81,12 +82,11 @@
#include "RE_render_ext.h"
-static void key_from_object(Object *ob, ParticleKey *key);
static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index,
float *fuv, float *orco, ParticleTexture *ptex, int event);
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
-static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part,
+static void do_child_modifiers(ParticleSimulationData *sim,
ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa,
float *orco, float mat[4][4], ParticleKey *state, float t);
@@ -96,11 +96,9 @@ int count_particles(ParticleSystem *psys){
PARTICLE_P;
int tot=0;
- LOOP_PARTICLES {
- if(pa->alive == PARS_KILLED);
- else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
+ LOOP_SHOWN_PARTICLES {
+ if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
- else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP));
else tot++;
}
return tot;
@@ -110,55 +108,13 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){
PARTICLE_P;
int tot=0;
- LOOP_PARTICLES {
- if(pa->alive == PARS_KILLED);
- else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
+ LOOP_SHOWN_PARTICLES {
+ if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
- else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP));
else if(p%totgr==cur) tot++;
}
return tot;
}
-int psys_count_keys(ParticleSystem *psys)
-{
- PARTICLE_P;
- int totkey=0;
-
- LOOP_PARTICLES
- totkey += pa->totkey;
-
- return totkey;
-}
-/* remember to free the pointer returned from this! */
-char *psys_menu_string(Object *ob, int for_sb)
-{
- ParticleSystem *psys;
- DynStr *ds;
- char *str, num[6];
- int i;
-
- ds = BLI_dynstr_new();
-
- if(for_sb)
- BLI_dynstr_append(ds, "|Object%x-1");
-
- for(i=0,psys=ob->particlesystem.first; psys; i++,psys=psys->next){
-
- BLI_dynstr_append(ds, "|");
- sprintf(num,"%i. ",i+1);
- BLI_dynstr_append(ds, num);
- BLI_dynstr_append(ds, psys->part->id.name+2);
- sprintf(num,"%%x%i",i+1);
- BLI_dynstr_append(ds, num);
- }
-
- str = BLI_dynstr_get_cstring(ds);
-
- BLI_dynstr_free(ds);
-
- return str;
-}
-
/* we allocate path cache memory in chunks instead of a big continguous
* chunk, windows' memory allocater fails to find big blocks of memory often */
@@ -258,30 +214,13 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys)
return NULL;
}
-/* change object's active particle system */
-void psys_change_act(void *ob_v, void *act_v)
-{
- Object *ob = ob_v;
- ParticleSystem *npsys, *psys;
- short act = *((short*)act_v)-1;
-
- if(act>=0){
- npsys=BLI_findlink(&ob->particlesystem,act);
- psys=psys_get_current(ob);
-
- if(psys)
- psys->flag &= ~PSYS_CURRENT;
- if(npsys)
- npsys->flag |= PSYS_CURRENT;
- }
-}
-Object *psys_get_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
+Object *psys_get_lattice(ParticleSimulationData *sim)
{
Object *lattice=0;
- if(psys_in_edit_mode(scene, psys)==0){
+ if(psys_in_edit_mode(sim->scene, sim->psys)==0){
- ModifierData *md = (ModifierData*)psys_get_modifier(ob,psys);
+ ModifierData *md = (ModifierData*)psys_get_modifier(sim->ob, sim->psys);
for(; md; md=md->next){
if(md->type==eModifierType_Lattice){
@@ -310,20 +249,20 @@ void psys_enable_all(Object *ob)
for(; psys; psys=psys->next)
psys->flag &= ~PSYS_DISABLED;
}
-int psys_ob_has_hair(Object *ob)
-{
- ParticleSystem *psys = ob->particlesystem.first;
-
- for(; psys; psys=psys->next)
- if(psys->part->type == PART_HAIR)
- return 1;
-
- return 0;
-}
int psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
{
return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit));
}
+static void psys_create_frand(ParticleSystem *psys)
+{
+ int i;
+ float *rand = psys->frand = MEM_callocN(PSYS_FRAND_COUNT * sizeof(float), "particle randoms");
+
+ BLI_srandom(psys->seed);
+
+ for(i=0; i<1024; i++, rand++)
+ *rand = BLI_frand();
+}
int psys_check_enabled(Object *ob, ParticleSystem *psys)
{
ParticleSystemModifierData *psmd;
@@ -345,6 +284,14 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
}
else if(!(psmd->modifier.mode & eModifierMode_Realtime))
return 0;
+
+ /* perhaps not the perfect place, but we have to be sure the rands are there before usage */
+ if(!psys->frand)
+ psys_create_frand(psys);
+ else if(psys->recalc & PSYS_RECALC_RESET) {
+ MEM_freeN(psys->frand);
+ psys_create_frand(psys);
+ }
return 1;
}
@@ -354,15 +301,11 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys)
/************************************************/
void psys_free_settings(ParticleSettings *part)
{
- if(part->pd) {
- MEM_freeN(part->pd);
- part->pd = NULL;
- }
-
- if(part->pd2) {
- MEM_freeN(part->pd2);
- part->pd2 = NULL;
- }
+ free_partdeflect(part->pd);
+ free_partdeflect(part->pd2);
+
+ if(part->effector_weights)
+ MEM_freeN(part->effector_weights);
boid_free_settings(part->boids);
}
@@ -424,7 +367,7 @@ void free_keyed_keys(ParticleSystem *psys)
}
}
}
-void free_child_path_cache(ParticleSystem *psys)
+static void free_child_path_cache(ParticleSystem *psys)
{
psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs);
psys->childcache = NULL;
@@ -478,6 +421,26 @@ void psys_free_particles(ParticleSystem *psys)
psys->totpart= 0;
}
}
+void psys_free_pdd(ParticleSystem *psys)
+{
+ if(psys->pdd) {
+ if(psys->pdd->cdata)
+ MEM_freeN(psys->pdd->cdata);
+ psys->pdd->cdata = NULL;
+
+ if(psys->pdd->vdata)
+ MEM_freeN(psys->pdd->vdata);
+ psys->pdd->vdata = NULL;
+
+ if(psys->pdd->ndata)
+ MEM_freeN(psys->pdd->ndata);
+ psys->pdd->ndata = NULL;
+
+ if(psys->pdd->vedata)
+ MEM_freeN(psys->pdd->vedata);
+ psys->pdd->vedata = NULL;
+ }
+}
/* free everything */
void psys_free(Object *ob, ParticleSystem * psys)
{
@@ -499,9 +462,6 @@ void psys_free(Object *ob, ParticleSystem * psys)
psys->child = 0;
psys->totchild = 0;
}
-
- if(psys->effectors.first)
- psys_end_effectors(psys);
// check if we are last non-visible particle system
for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){
@@ -527,10 +487,19 @@ void psys_free(Object *ob, ParticleSystem * psys)
psys->pointcache = NULL;
BLI_freelistN(&psys->targets);
- BLI_freelistN(&psys->reactevents);
BLI_kdtree_free(psys->tree);
+ pdEndEffectors(&psys->effectors);
+
+ if(psys->frand)
+ MEM_freeN(psys->frand);
+
+ if(psys->pdd) {
+ psys_free_pdd(psys);
+ MEM_freeN(psys->pdd);
+ }
+
MEM_freeN(psys);
}
}
@@ -722,12 +691,12 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
{
DerivedMesh *dm= ctx->dm;
- Mesh *me= (Mesh*)(ctx->ob->data);
+ Mesh *me= (Mesh*)(ctx->sim.ob->data);
MFace *mf, *mface;
MVert *mvert;
ParticleRenderData *data;
ParticleRenderElem *elems, *elem;
- ParticleSettings *part= ctx->psys->part;
+ ParticleSettings *part= ctx->sim.psys->part;
float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
double vprate;
@@ -736,10 +705,10 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
return tot;
- if(!ctx->psys->renderdata)
+ if(!ctx->sim.psys->renderdata)
return tot;
- data= ctx->psys->renderdata;
+ data= ctx->sim.psys->renderdata;
if(data->timeoffset)
return 0;
if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
@@ -816,7 +785,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
/* set simplification parameters per original face */
for(a=0, elem=elems; a<totorigface; a++, elem++) {
- area = psys_render_projected_area(ctx->psys, facecenter[a], facearea[a], vprate, &viewport);
+ area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
arearatio= fac*area/facearea[a];
if((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
@@ -1438,7 +1407,7 @@ void psys_interpolate_mcol(MCol *mcol, int quad, float *w, MCol *mc)
}
}
-float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values)
+static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, float *fw, float *values)
{
if(values==0 || index==-1)
return 0.0;
@@ -1922,124 +1891,135 @@ static void do_clump(ParticleKey *state, ParticleKey *par, float time, float clu
VecLerpf(state->co,state->co,par->co,clump);
}
}
+void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
+{
+ EffectedPoint point;
+ ParticleKey state;
+ EffectorData efd;
+ EffectorCache *eff;
+ ParticleSystem *psys = sim->psys;
+ EffectorWeights *weights = sim->psys->part->effector_weights;
+ GuideEffectorData *data;
+ PARTICLE_P;
-int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase *lb)
+ if(!effectors)
+ return;
+
+ LOOP_PARTICLES {
+ psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,state.co,0,0,0,0,0);
+ pd_point_from_particle(sim, pa, &state, &point);
+
+ for(eff = effectors->first; eff; eff=eff->next) {
+ if(eff->pd->forcefield != PFIELD_GUIDE)
+ continue;
+
+ if(!eff->guide_data)
+ eff->guide_data = MEM_callocN(sizeof(GuideEffectorData)*psys->totpart, "GuideEffectorData");
+
+ data = eff->guide_data + p;
+
+ VECSUB(efd.vec_to_point, state.co, eff->guide_loc);
+ VECCOPY(efd.nor, eff->guide_dir);
+ efd.distance = VecLength(efd.vec_to_point);
+
+ VECCOPY(data->vec_to_point, efd.vec_to_point);
+ data->strength = effector_falloff(eff, &efd, &point, weights);
+ }
+ }
+}
+int do_guides(ListBase *effectors, ParticleKey *state, int index, float time)
{
+ EffectorCache *eff;
PartDeflect *pd;
- ParticleEffectorCache *ec;
- Object *eob;
Curve *cu;
ParticleKey key, par;
+ GuideEffectorData *data;
- float effect[3]={0.0,0.0,0.0}, distance, f_force, mindist, totforce=0.0;
- float guidevec[4], guidedir[3], rot2[4], radius, temp[3], angle, pa_loc[3], pa_zero[3]={0.0f,0.0f,0.0f};
- float veffect[3]={0.0,0.0,0.0}, guidetime;
-
- effect[0]=effect[1]=effect[2]=0.0;
+ float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
+ float guidevec[4], guidedir[3], rot2[4], temp[3];
+ float guidetime, radius, angle, totstrength = 0.0f;
+ float vec_to_point[3];
- if(lb->first){
- for(ec = lb->first; ec; ec= ec->next){
- eob= ec->ob;
- if(ec->type & PSYS_EC_EFFECTOR){
- pd=eob->pd;
- if(pd->forcefield==PFIELD_GUIDE){
- cu = (Curve*)eob->data;
+ if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
+ pd = eff->pd;
- distance=ec->distances[pa_num];
- mindist=pd->f_strength;
+ if(pd->forcefield != PFIELD_GUIDE)
+ continue;
- VECCOPY(pa_loc, ec->locations+3*pa_num);
- VECCOPY(pa_zero,pa_loc);
- VECADD(pa_zero,pa_zero,ec->firstloc);
+ data = eff->guide_data + index;
- guidetime=time/(1.0-pd->free_end);
+ if(data->strength <= 0.0f)
+ continue;
- /* WARNING: bails out with continue here */
- if(((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist) || guidetime>1.0f) continue;
+ guidetime = time / (1.0 - pd->free_end);
- if(guidetime>1.0f) continue;
+ if(guidetime>1.0f)
+ continue;
- /* calculate contribution factor for this guide */
- f_force=1.0f;
- if(distance<=mindist);
- else if(pd->flag & PFIELD_USEMAX) {
- if(mindist>=pd->maxdist) f_force= 0.0f;
- else if(pd->f_power!=0.0f){
- f_force= 1.0f - (distance-mindist)/(pd->maxdist - mindist);
- f_force = (float)pow(f_force, pd->f_power);
- }
- }
- else if(pd->f_power!=0.0f){
- f_force= 1.0f/(1.0f + distance-mindist);
- f_force = (float)pow(f_force, pd->f_power);
- }
+ cu = (Curve*)eff->ob->data;
- if(pd->flag & PFIELD_GUIDE_PATH_ADD)
- where_on_path(eob, f_force*guidetime, guidevec, guidedir, NULL, &radius);
- else
- where_on_path(eob, guidetime, guidevec, guidedir, NULL, &radius);
+ if(pd->flag & PFIELD_GUIDE_PATH_ADD) {
+ if(where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius)==0)
+ return 0;
+ }
+ else {
+ if(where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius)==0)
+ return 0;
+ }
- Mat4MulVecfl(ec->ob->obmat,guidevec);
- Mat4Mul3Vecfl(ec->ob->obmat,guidedir);
+ Mat4MulVecfl(eff->ob->obmat, guidevec);
+ Mat4Mul3Vecfl(eff->ob->obmat, guidedir);
- Normalize(guidedir);
+ Normalize(guidedir);
- if(guidetime!=0.0){
- /* curve direction */
- Crossf(temp, ec->firstdir, guidedir);
- angle=Inpf(ec->firstdir,guidedir)/(VecLength(ec->firstdir));
- angle=saacos(angle);
- VecRotToQuat(temp,angle,rot2);
- QuatMulVecf(rot2,pa_loc);
+ VECCOPY(vec_to_point, data->vec_to_point);
- /* curve tilt */
- VecRotToQuat(guidedir,guidevec[3]-ec->firstloc[3],rot2);
- QuatMulVecf(rot2,pa_loc);
+ if(guidetime != 0.0){
+ /* curve direction */
+ Crossf(temp, eff->guide_dir, guidedir);
+ angle = Inpf(eff->guide_dir, guidedir)/(VecLength(eff->guide_dir));
+ angle = saacos(angle);
+ VecRotToQuat(temp, angle, rot2);
+ QuatMulVecf(rot2, vec_to_point);
- //vectoquat(guidedir, pd->kink_axis, (pd->kink_axis+1)%3, q);
- //QuatMul(par.rot,rot2,q);
- }
- //else{
- // par.rot[0]=1.0f;
- // par.rot[1]=par.rot[2]=par.rot[3]=0.0f;
- //}
-
- /* curve taper */
- if(cu->taperobj)
- VecMulf(pa_loc, calc_taper(scene, cu->taperobj, (int)(f_force*guidetime*100.0), 100));
-
- else{ /* curve size*/
- if(cu->flag & CU_PATH_RADIUS) {
- VecMulf(pa_loc, radius);
- }
- }
- par.co[0]=par.co[1]=par.co[2]=0.0f;
- VECCOPY(key.co,pa_loc);
- do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0);
- do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f);
- VECCOPY(pa_loc,key.co);
-
- VECADD(pa_loc,pa_loc,guidevec);
- VECSUB(pa_loc,pa_loc,pa_zero);
- VECADDFAC(effect,effect,pa_loc,f_force);
- VECADDFAC(veffect,veffect,guidedir,f_force);
- totforce+=f_force;
- }
- }
+ /* curve tilt */
+ VecRotToQuat(guidedir, guidevec[3] - eff->guide_loc[3], rot2);
+ QuatMulVecf(rot2, vec_to_point);
}
- if(totforce!=0.0){
- if(totforce>1.0)
- VecMulf(effect,1.0f/totforce);
- CLAMP(totforce,0.0,1.0);
- VECADD(effect,effect,pa_zero);
- VecLerpf(state->co,state->co,effect,totforce);
+ /* curve taper */
+ if(cu->taperobj)
+ VecMulf(vec_to_point, calc_taper(eff->scene, cu->taperobj, (int)(data->strength*guidetime*100.0), 100));
- Normalize(veffect);
- VecMulf(veffect,VecLength(state->vel));
- VECCOPY(state->vel,veffect);
- return 1;
+ else{ /* curve size*/
+ if(cu->flag & CU_PATH_RADIUS) {
+ VecMulf(vec_to_point, radius);
+ }
}
+ par.co[0] = par.co[1] = par.co[2] = 0.0f;
+ VECCOPY(key.co, vec_to_point);
+ do_prekink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, pd->kink, pd->kink_axis, 0);
+ do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f);
+ VECCOPY(vec_to_point, key.co);
+
+ VECADD(vec_to_point, vec_to_point, guidevec);
+ //VECSUB(pa_loc,pa_loc,pa_zero);
+ VECADDFAC(effect, effect, vec_to_point, data->strength);
+ VECADDFAC(veffect, veffect, guidedir, data->strength);
+ totstrength += data->strength;
+ }
+
+ if(totstrength != 0.0){
+ if(totstrength > 1.0)
+ VecMulf(effect, 1.0f / totstrength);
+ CLAMP(totstrength, 0.0, 1.0);
+ //VECADD(effect,effect,pa_zero);
+ VecLerpf(state->co, state->co, effect, totstrength);
+
+ Normalize(veffect);
+ VecMulf(veffect, VecLength(state->vel));
+ VECCOPY(state->vel, veffect);
+ return 1;
}
return 0;
}
@@ -2075,20 +2055,24 @@ static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float
VECADDFAC(state->co,state->co,mat[0],rough[0]);
VECADDFAC(state->co,state->co,mat[1],rough[1]);
}
-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)
+static void do_path_effectors(ParticleSimulationData *sim, 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};
+ float force[3] = {0.0f,0.0f,0.0f};
ParticleKey eff_key;
- ParticleData *pa;
+ EffectedPoint epoint;
+
+ /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */
+ if(sim->psys->flag & PSYS_HAIR_DYNAMICS)
+ return;
VECCOPY(eff_key.co,(ca-1)->co);
VECCOPY(eff_key.vel,(ca-1)->vel);
QUATCOPY(eff_key.rot,(ca-1)->rot);
- pa= psys->particles+i;
- do_effectors(i, pa, &eff_key, scene, ob, psys, rootco, force, vel, dfra, cfra);
+ pd_point_from_particle(sim, sim->psys->particles+i, &eff_key, &epoint);
+ pdDoEffectors(sim->psys->effectors, sim->colliders, sim->psys->part->effector_weights, &epoint, force, NULL);
- VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * psys->part->eff_hair) / (float)steps);
+ VecMulf(force, effector*pow((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps);
VecAddf(force, force, vec);
@@ -2155,12 +2139,12 @@ float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup)
}
return vg;
}
-void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys)
+void psys_find_parents(ParticleSimulationData *sim)
{
- ParticleSettings *part=psys->part;
+ ParticleSettings *part=sim->psys->part;
KDTree *tree;
ChildParticle *cpa;
- int p, totparent,totchild=psys->totchild;
+ int p, totparent,totchild=sim->psys->totchild;
float co[3], orco[3];
int from=PART_FROM_FACE;
totparent=(int)(totchild*part->parents*0.3);
@@ -2170,15 +2154,15 @@ void psys_find_parents(Object *ob, ParticleSystemModifierData *psmd, ParticleSys
tree=BLI_kdtree_new(totparent);
- for(p=0,cpa=psys->child; p<totparent; p++,cpa++){
- psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
+ for(p=0,cpa=sim->psys->child; p<totparent; p++,cpa++){
+ psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
BLI_kdtree_insert(tree, p, orco, NULL);
}
BLI_kdtree_balance(tree);
for(; p<totchild; p++,cpa++){
- psys_particle_on_emitter(psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
+ psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
cpa->parent=BLI_kdtree_find_nearest(tree, orco, NULL, NULL);
}
@@ -2216,11 +2200,11 @@ static void get_strand_normal(Material *ma, float *surfnor, float surfdist, floa
VECCOPY(nor, vnor);
}
-int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate)
+static 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;
+/* Object *ob= ctx->sim.ob; */
+ ParticleSystem *psys= ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleEditSettings *pset = &scene->toolsettings->particle;
int totparent=0, between=0;
@@ -2253,10 +2237,10 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in
if(totchild==0) return 0;
/* init random number generator */
- if(ctx->psys->part->flag & PART_ANIM_BRANCHING)
- seed= 31415926 + ctx->psys->seed + (int)cfra;
+ if(ctx->sim.psys->part->flag & PART_ANIM_BRANCHING)
+ seed= 31415926 + ctx->sim.psys->seed + (int)cfra;
else
- seed= 31415926 + ctx->psys->seed;
+ seed= 31415926 + ctx->sim.psys->seed;
if(part->flag & PART_BRANCHING || ctx->editupdate || totchild < 10000)
totthread= 1;
@@ -2274,7 +2258,7 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in
ctx->parent_pass= 0;
ctx->cfra= cfra;
- psys->lattice = psys_get_lattice(scene, ob, psys);
+ psys->lattice = psys_get_lattice(&ctx->sim);
/* cache all relevant vertex groups if they exist */
if(part->from!=PART_FROM_PARTICLE){
@@ -2300,11 +2284,11 @@ int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, in
}
/* note: this function must be thread safe, except for branching! */
-void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i)
+static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *keys, int i)
{
ParticleThreadContext *ctx= thread->ctx;
- Object *ob= ctx->ob;
- ParticleSystem *psys = ctx->psys;
+ Object *ob= ctx->sim.ob;
+ ParticleSystem *psys = ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleCacheKey **cache= psys->childcache;
ParticleCacheKey **pcache= psys->pathcache;
@@ -2373,7 +2357,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
cpa_fuv = cpa->fuv;
cpa_from = PART_FROM_FACE;
- psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0);
+ psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0);
if(part->path_start==0.0f) {
/* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
@@ -2383,7 +2367,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
pa = psys->particles + cpa->parent;
- psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
pa=0;
}
@@ -2405,9 +2389,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
cpa_num=pa->num;
cpa_fuv=pa->fuv;
- psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0);
+ psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0);
- psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
}
keys->steps = ctx->steps;
@@ -2424,7 +2408,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
/* get different child parameters from textures & vgroups */
get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
- if(ptex.exist < cpa->rand[1]) {
+ if(ptex.exist < PSYS_FRAND(i + 24)) {
keys->steps = -1;
return;
}
@@ -2473,7 +2457,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(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
+ do_path_effectors(&ctx->sim, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
}
else {
VecSubf(eff_vec,(state+1)->co,state->co);
@@ -2499,7 +2483,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
}
/* apply different deformations to the child path */
- do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t);
+ do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t);
/* TODO: better branching */
//if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
@@ -2576,7 +2560,7 @@ static void *exec_child_path_cache(void *data)
{
ParticleThread *thread= (ParticleThread*)data;
ParticleThreadContext *ctx= thread->ctx;
- ParticleSystem *psys= ctx->psys;
+ ParticleSystem *psys= ctx->sim.psys;
ParticleCacheKey **cache= psys->childcache;
ChildParticle *cpa;
int i, totchild= ctx->totchild, first= 0;
@@ -2593,21 +2577,21 @@ static void *exec_child_path_cache(void *data)
return 0;
}
-void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int editupdate)
+void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate)
{
- ParticleSettings *part = psys->part;
+ ParticleSettings *part = sim->psys->part;
ParticleThread *pthreads;
ParticleThreadContext *ctx;
ParticleCacheKey **cache;
ListBase threads;
int i, totchild, totparent, totthread;
- if(psys->flag & PSYS_GLOBAL_HAIR)
+ if(sim->psys->flag & PSYS_GLOBAL_HAIR)
return;
- pthreads= psys_threads_create(scene, ob, psys);
+ pthreads= psys_threads_create(sim);
- if(!psys_threads_init_path(pthreads, scene, cfra, editupdate)) {
+ if(!psys_threads_init_path(pthreads, sim->scene, cfra, editupdate)) {
psys_threads_free(pthreads);
return;
}
@@ -2616,14 +2600,14 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa
totchild= ctx->totchild;
totparent= ctx->totparent;
- if(editupdate && psys->childcache && !(part->flag & PART_BRANCHING) && totchild == psys->totchildcache) {
- cache = psys->childcache;
+ if(editupdate && sim->psys->childcache && !(part->flag & PART_BRANCHING) && totchild == sim->psys->totchildcache) {
+ cache = sim->psys->childcache;
}
else {
/* clear out old and create new empty path cache */
- free_child_path_cache(psys);
- psys->childcache= psys_alloc_path_cache_buffers(&psys->childcachebufs, totchild, ctx->steps+1);
- psys->totchildcache = totchild;
+ free_child_path_cache(sim->psys);
+ sim->psys->childcache= psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps+1);
+ sim->psys->totchildcache = totchild;
}
totthread= pthreads[0].tot;
@@ -2661,27 +2645,29 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa
/* -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(Scene *scene, Object *ob, ParticleSystem *psys, float cfra)
+void psys_cache_paths(ParticleSimulationData *sim, float cfra)
{
- ParticleCacheKey *ca, **cache= psys->pathcache;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
+ PARTICLE_PSMD;
+ ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
+ ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
- ParticleEditSettings *pset = &scene->toolsettings->particle;
+ ParticleCacheKey *ca, **cache= psys->pathcache;
DerivedMesh *hair_dm = psys->hair_out_dm;
- ParticleData *pa = psys->particles;
ParticleKey result;
Material *ma;
ParticleInterpolationData pind;
+
+ PARTICLE_P;
float birthtime = 0.0, dietime = 0.0;
- float t, time = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec;
+ float t, time = 0.0, dfra = 1.0, frs_sec = sim->scene->r.frs_sec;
float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
float prev_tangent[3], hairmat[4][4];
float rotmat[3][3];
- int k,i;
+ int k;
int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step));
int totpart = psys->totpart;
float length, vec[3];
@@ -2693,7 +2679,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0)
return;
- if(psys_in_edit_mode(scene, psys))
+ if(psys_in_edit_mode(sim->scene, psys))
if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0)
return;
@@ -2706,8 +2692,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
psys_free_path_cache(psys, psys->edit);
cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1);
- psys->lattice = psys_get_lattice(scene, ob, psys);
- ma= give_current_material(ob, psys->part->omat);
+ psys->lattice = psys_get_lattice(sim);
+ ma= give_current_material(sim->ob, psys->part->omat);
if(ma && (psys->part->draw & PART_DRAW_MAT_COL))
VECCOPY(col, &ma->r)
@@ -2720,12 +2706,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
}
/*---first main loop: create all actual particles' paths---*/
- for(i=0; i<totpart; i++, pa++){
- if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST)
- continue;
-
+ LOOP_SHOWN_PARTICLES {
if(!psys->totchild) {
- BLI_srandom(psys->seed + i);
+ BLI_srandom(psys->seed + p);
pa_length = 1.0f - part->randlength * BLI_frand();
if(vg_length)
pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length);
@@ -2737,15 +2720,15 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
pind.dm = hair_dm;
- memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
+ memset(cache[p], 0, sizeof(*cache[p])*(steps+1));
- cache[i]->steps = steps;
+ cache[p]->steps = steps;
/*--get the first data points--*/
- init_particle_interpolation(ob, psys, pa, &pind);
+ init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
/* hairmat is needed for for non-hair particle too so we get proper rotations */
- psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(sim->ob, psmd->dm, psys->part->from, pa, hairmat);
VECCOPY(rotmat[0], hairmat[2]);
VECCOPY(rotmat[1], hairmat[1]);
VECCOPY(rotmat[2], hairmat[0]);
@@ -2761,26 +2744,26 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
}
if(birthtime >= dietime) {
- cache[i]->steps = -1;
+ cache[p]->steps = -1;
continue;
}
dietime = birthtime + pa_length * (dietime - birthtime);
/*--interpolate actual path from data points--*/
- for(k=0, ca=cache[i]; k<=steps; k++, ca++){
+ for(k=0, ca=cache[p]; k<=steps; k++, ca++){
time = (float)k / (float)steps;
t = birthtime + time * (dietime - birthtime);
result.time = -t;
- do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
+ do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, &result);
/* dynamic hair is in object space */
/* keyed and baked are allready in global space */
if(hair_dm)
- Mat4MulVecfl(ob->obmat, result.co);
+ Mat4MulVecfl(sim->ob->obmat, result.co);
else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR))
Mat4MulVecfl(hairmat, result.co);
@@ -2790,23 +2773,23 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
/*--modify paths and calculate rotation & velocity--*/
- VecSubf(vec,(cache[i]+1)->co,cache[i]->co);
+ VecSubf(vec,(cache[p]+1)->co,cache[p]->co);
length = VecLength(vec);
effector= 1.0f;
if(vg_effector)
effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector);
- for(k=0, ca=cache[i]; k<=steps; k++, ca++) {
+ for(k=0, ca=cache[p]; k<=steps; k++, ca++) {
if(!(psys->flag & PSYS_GLOBAL_HAIR)) {
/* apply effectors */
if(!(psys->part->flag & PART_CHILD_EFFECT) && k)
- do_path_effectors(scene, ob, psys, i, ca, k, steps, cache[i]->co, effector, dfra, cfra, &length, vec);
+ do_path_effectors(sim, p, ca, k, steps, cache[p]->co, effector, dfra, cfra, &length, vec);
/* apply guide curves to path data */
- if(psys->effectors.first && (psys->part->flag & PART_CHILD_EFFECT)==0)
+ if(sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT)==0)
/* ca is safe to cast, since only co and vel are used */
- do_guide(scene, (ParticleKey*)ca, i, (float)k/(float)steps, &psys->effectors);
+ do_guides(sim->psys->effectors, (ParticleKey*)ca, p, (float)k/(float)steps);
/* apply lattice */
if(psys->lattice)
@@ -3022,23 +3005,7 @@ void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, flo
if(time) *time=key->time;
}
/*-------changing particle keys from space to another-------*/
-void psys_key_to_object(Object *ob, ParticleKey *key, float imat[][4]){
- float q[4], imat2[4][4];
-
- if(imat==0){
- Mat4Invert(imat2,ob->obmat);
- imat=imat2;
- }
-
- VECADD(key->vel,key->vel,key->co);
-
- Mat4MulVecfl(imat,key->co);
- Mat4MulVecfl(imat,key->vel);
- Mat4ToQuat(imat,q);
-
- VECSUB(key->vel,key->vel,key->co);
- QuatMul(key->rot,q,key->rot);
-}
+#if 0
static void key_from_object(Object *ob, ParticleKey *key){
float q[4];
@@ -3051,6 +3018,7 @@ static void key_from_object(Object *ob, ParticleKey *key){
VECSUB(key->vel,key->vel,key->co);
QuatMul(key->rot,q,key->rot);
}
+#endif
static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[][4])
{
@@ -3229,8 +3197,6 @@ void object_remove_particle_system(Scene *scene, Object *ob)
}
static void default_particle_settings(ParticleSettings *part)
{
- int i;
-
part->type= PART_EMITTER;
part->distr= PART_DISTR_JIT;
part->draw_as = PART_DRAW_REND;
@@ -3241,7 +3207,7 @@ static void default_particle_settings(ParticleSettings *part)
part->flag=PART_REACT_MULTIPLE|PART_HAIR_GEOMETRY|PART_EDISTR|PART_TRAND;
part->sta= 1.0;
- part->end= 100.0;
+ part->end= 200.0;
part->lifetime= 50.0;
part->jitfac= 1.0;
part->totpart= 1000;
@@ -3291,10 +3257,6 @@ static void default_particle_settings(ParticleSettings *part)
part->keyed_loops = 1;
- for(i=0; i<10; i++)
- part->effector_weight[i]=1.0f;
-
-
#if 0 // XXX old animation system
part->ipo = NULL;
#endif // XXX old animation system
@@ -3303,6 +3265,9 @@ static void default_particle_settings(ParticleSettings *part)
part->simplify_rate= 1.0f;
part->simplify_transition= 0.1f;
part->simplify_viewport= 0.8;
+
+ if(!part->effector_weights)
+ part->effector_weights = BKE_add_effector_weights(NULL);
}
@@ -3390,59 +3355,6 @@ void make_local_particlesettings(ParticleSettings *part)
}
}
}
-void psys_flush_particle_settings(Scene *scene, ParticleSettings *part, int recalc)
-{
- Base *base = scene->base.first;
- ParticleSystem *psys;
- int flush;
-
- for(base = scene->base.first; base; base = base->next) {
- flush = 0;
- for(psys = base->object->particlesystem.first; psys; psys=psys->next) {
- if(psys->part == part) {
- psys->recalc |= recalc;
- flush++;
- }
- }
- if(flush)
- DAG_id_flush_update(&base->object->id, OB_RECALC_DATA);
- }
-}
-
-LinkNode *psys_using_settings(struct Scene *scene, ParticleSettings *part, int flush_update)
-{
- Object *ob, *tob;
- ParticleSystem *psys, *tpsys;
- LinkNode *node= NULL;
- int found;
-
- /* update all that have same particle settings */
- for(ob=G.main->object.first; ob; ob=ob->id.next) {
- found= 0;
-
- for(psys=ob->particlesystem.first; psys; psys=psys->next) {
- if(psys->part == part) {
- BLI_linklist_append(&node, psys);
- found++;
- }
- else if(psys->part->type == PART_REACTOR){
- tob= (psys->target_ob)? psys->target_ob: ob;
- tpsys= BLI_findlink(&tob->particlesystem, psys->target_psys-1);
-
- if(tpsys && tpsys->part==part) {
- BLI_linklist_append(&node, tpsys);
- found++;
- }
- }
- }
-
- if(flush_update && found)
- DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
- }
-
- return node;
-}
-
/************************************************/
/* Textures */
@@ -3498,9 +3410,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float
mtex=ma->mtex[m];
if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){
float def=mtex->def_var;
- float var=mtex->varfac;
short blend=mtex->blendtype;
- short neg=mtex->pmaptoneg;
if((mtex->texco & TEXCO_UV) && fw) {
if(!get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texco))
@@ -3515,18 +3425,18 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float
ptex->time=0.0;
setvars|=MAP_PA_TIME;
}
- ptex->time= texture_value_blend(mtex->def_var,ptex->time,value,var,blend,neg & MAP_PA_TIME);
+ ptex->time= texture_value_blend(mtex->def_var,ptex->time,value,mtex->timefac,blend);
}
if((event & mtex->pmapto) & MAP_PA_LENGTH)
- ptex->length= texture_value_blend(def,ptex->length,value,var,blend,neg & MAP_PA_LENGTH);
+ ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend);
if((event & mtex->pmapto) & MAP_PA_CLUMP)
- ptex->clump= texture_value_blend(def,ptex->clump,value,var,blend,neg & MAP_PA_CLUMP);
+ ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend);
if((event & mtex->pmapto) & MAP_PA_KINK)
- ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_KINK);
+ ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend);
if((event & mtex->pmapto) & MAP_PA_ROUGH)
- ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,var,blend,neg & MAP_PA_ROUGH);
+ ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,mtex->roughfac,blend);
if((event & mtex->pmapto) & MAP_PA_DENS)
- ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS);
+ ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend);
}
}
if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); }
@@ -3540,7 +3450,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float
}
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)
+void psys_get_texture(ParticleSimulationData *sim, Material *ma, ParticleData *pa, ParticleTexture *ptex, int event)
{
MTex *mtex;
int m;
@@ -3550,19 +3460,17 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd
if(ma) for(m=0; m<MAX_MTEX; m++){
mtex=ma->mtex[m];
if(mtex && (ma->septex & (1<<m))==0 && mtex->pmapto){
- float var=mtex->varfac;
float def=mtex->def_var;
short blend=mtex->blendtype;
- short neg=mtex->pmaptoneg;
- if((mtex->texco & TEXCO_UV) && ELEM(psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
- if(!get_particle_uv(psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) {
+ if((mtex->texco & TEXCO_UV) && ELEM(sim->psys->part->from, PART_FROM_FACE, PART_FROM_VOLUME)) {
+ if(!get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texco)) {
/* failed to get uv's, let's try orco's */
- psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0);
+ psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0);
}
}
else {
- psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0);
+ psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texco, 0);
}
externtex(mtex, texco, &value, rgba, rgba+1, rgba+2, rgba+3);
@@ -3570,29 +3478,31 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd
if((event & mtex->pmapto) & MAP_PA_TIME){
/* the first time has to set the base value for time regardless of blend mode */
if((setvars&MAP_PA_TIME)==0){
- ptex->time *= 1.0f - var;
- ptex->time += var * ((neg & MAP_PA_TIME)? 1.0f - value : value);
+ int flip= (mtex->timefac < 0.0f);
+ float timefac= fabsf(mtex->timefac);
+ ptex->time *= 1.0f - timefac;
+ ptex->time += timefac * ((flip)? 1.0f - value : value);
setvars |= MAP_PA_TIME;
}
else
- ptex->time= texture_value_blend(def,ptex->time,value,var,blend,neg & MAP_PA_TIME);
+ ptex->time= texture_value_blend(def,ptex->time,value,mtex->timefac,blend);
}
if((event & mtex->pmapto) & MAP_PA_LIFE)
- ptex->life= texture_value_blend(def,ptex->life,value,var,blend,neg & MAP_PA_LIFE);
+ ptex->life= texture_value_blend(def,ptex->life,value,mtex->lifefac,blend);
if((event & mtex->pmapto) & MAP_PA_DENS)
- ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS);
+ ptex->exist= texture_value_blend(def,ptex->exist,value,mtex->padensfac,blend);
if((event & mtex->pmapto) & MAP_PA_SIZE)
- ptex->size= texture_value_blend(def,ptex->size,value,var,blend,neg & MAP_PA_SIZE);
+ ptex->size= texture_value_blend(def,ptex->size,value,mtex->sizefac,blend);
if((event & mtex->pmapto) & MAP_PA_IVEL)
- ptex->ivel= texture_value_blend(def,ptex->ivel,value,var,blend,neg & MAP_PA_IVEL);
+ ptex->ivel= texture_value_blend(def,ptex->ivel,value,mtex->ivelfac,blend);
if((event & mtex->pmapto) & MAP_PA_PVEL)
- texture_rgb_blend(ptex->pvel,rgba,ptex->pvel,value,var,blend);
+ texture_rgb_blend(ptex->pvel,rgba,ptex->pvel,value,mtex->pvelfac,blend);
if((event & mtex->pmapto) & MAP_PA_LENGTH)
- ptex->length= texture_value_blend(def,ptex->length,value,var,blend,neg & MAP_PA_LENGTH);
+ ptex->length= texture_value_blend(def,ptex->length,value,mtex->lengthfac,blend);
if((event & mtex->pmapto) & MAP_PA_CLUMP)
- ptex->clump= texture_value_blend(def,ptex->clump,value,var,blend,neg & MAP_PA_CLUMP);
+ ptex->clump= texture_value_blend(def,ptex->clump,value,mtex->clumpfac,blend);
if((event & mtex->pmapto) & MAP_PA_KINK)
- ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_CLUMP);
+ ptex->kink= texture_value_blend(def,ptex->kink,value,mtex->kinkfac,blend);
}
}
if(event & MAP_PA_TIME) { CLAMP(ptex->time,0.0,1.0); }
@@ -3607,38 +3517,9 @@ void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd
/************************************************/
/* Particle State */
/************************************************/
-float psys_get_timestep(ParticleSettings *part)
+float psys_get_timestep(ParticleSimulationData *sim)
{
- return 0.04f*part->timetweak;
-}
-/* part->size should be updated with possible ipo effection before this is called */
-float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd, IpoCurve *icu_size, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, float *vg_size)
-{
- ParticleTexture ptex;
- float size=1.0f;
-
- BLI_srandom(psys->seed + (pa - psys->particles) + 100);
-
- if(ma && part->from!=PART_FROM_PARTICLE){
- ptex.size=size;
- psys_get_texture(ob,ma,psmd,psys,pa,&ptex,MAP_PA_SIZE);
- 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);
-
- if(part->randsize!=0.0)
- size*= 1.0f - part->randsize * BLI_frand();
-
- return size*part->size;
+ return 0.04f * sim->psys->part->timetweak;
}
float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
{
@@ -3653,7 +3534,7 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra,
w++;
}
- life = part->lifetime*(1.0f-part->randlife*cpa->rand[1]);
+ life = part->lifetime * (1.0f - part->randlife * PSYS_FRAND(cpa - psys->child + 25));
}
else{
ParticleData *pa = psys->particles + cpa->parent;
@@ -3702,13 +3583,16 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra,
size*=part->childsize;
if(part->childrandsize!=0.0)
- size *= 1.0f - part->childrandsize*cpa->rand[2];
+ size *= 1.0f - part->childrandsize * PSYS_FRAND(cpa - psys->child + 26);
return size;
}
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
{
- ptex->length= 1.0f - part->randlength*cpa->rand[0];
+ ParticleSystem *psys = ctx->sim.psys;
+ int i = cpa - psys->child;
+
+ ptex->length= 1.0f - part->randlength * PSYS_FRAND(i + 26);
ptex->clump=1.0;
ptex->kink=1.0;
ptex->rough1= 1.0;
@@ -3717,13 +3601,13 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
ptex->exist= 1.0;
ptex->effector= 1.0;
- ptex->length*= part->clength_thres < cpa->rand[1] ? part->clength : 1.0f;
+ ptex->length*= part->clength_thres < PSYS_FRAND(i + 27) ? part->clength : 1.0f;
get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex,
MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH);
- if(ptex->exist < cpa->rand[1])
+ if(ptex->exist < PSYS_FRAND(i + 24))
return;
if(ctx->vg_length)
@@ -3741,18 +3625,20 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
if(ctx->vg_effector)
ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector);
}
-static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t)
+static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t)
{
+ ParticleSettings *part = sim->psys->part;
+ int i = cpa - sim->psys->child;
int guided = 0;
if(part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
- guided = do_guide(scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors));
+ guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t);
if(guided==0){
if(part->kink)
do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape,
- part->kink_amp, part->kink, part->kink_axis, ob->obmat);
+ part->kink_amp, part->kink, part->kink_axis, sim->ob->obmat);
do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump);
}
@@ -3761,17 +3647,18 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P
do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state);
if(part->rough2 != 0.0 && ptex->rough2 != 0.0)
- do_rough(cpa->rand, mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state);
+ do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state);
if(part->rough_end != 0.0 && ptex->roughe != 0.0)
- do_rough_end(cpa->rand, mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state);
+ do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state);
}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */
-void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel)
+void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, int vel)
{
- ParticleSettings *part = psys->part;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- Material *ma = give_current_material(ob, part->omat);
+ PARTICLE_PSMD;
+ ParticleSystem *psys = sim->psys;
+ ParticleSettings *part = sim->psys->part;
+ Material *ma = give_current_material(sim->ob, part->omat);
ParticleData *pa;
ChildParticle *cpa;
ParticleTexture ptex;
@@ -3779,7 +3666,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
ParticleThreadContext ctx; /* fake thread context for child modifiers */
ParticleInterpolationData pind;
- float t, frs_sec = scene->r.frs_sec;
+ float t, frs_sec = sim->scene->r.frs_sec;
float co[3], orco[3];
float hairmat[4][4];
int totparent = 0;
@@ -3807,17 +3694,17 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
pind.cache = cached ? psys->pointcache : NULL;
pind.epoint = NULL;
pind.dm = psys->hair_out_dm;
- init_particle_interpolation(ob, psys, pa, &pind);
+ init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state);
if(!keyed && !cached) {
if((pa->flag & PARS_REKEY)==0) {
- psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat);
+ psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat);
Mat4MulVecfl(hairmat, state->co);
Mat4Mul3Vecfl(hairmat, state->vel);
- if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) {
- do_guide(scene, state, p, state->time, &psys->effectors);
+ if(sim->psys->effectors && (part->flag & PART_CHILD_GUIDE)==0) {
+ do_guides(sim->psys->effectors, state, p, state->time);
/* TODO: proper velocity handling */
}
@@ -3850,7 +3737,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
/* get parent states */
while(w<4 && cpa->pa[w]>=0){
keys[w].time = state->time;
- psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1);
+ psys_get_particle_on_path(sim, cpa->pa[w], keys+w, 1);
w++;
}
@@ -3870,14 +3757,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
pa = psys->particles + cpa->parent;
- psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
pa=0;
}
else{
/* get the parent state */
keys->time = state->time;
- psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1);
+ psys_get_particle_on_path(sim, cpa->parent, keys,1);
/* get the original coordinates (orco) for texture usage */
pa=psys->particles+cpa->parent;
@@ -3888,7 +3775,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0);
- psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
}
/* correct child ipo timing */
@@ -3937,7 +3824,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
copy_particle_key(&tstate, state, 1);
/* apply different deformations to the child path */
- do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, hairmat, state, t);
+ do_child_modifiers(sim, &ptex, par, par->rot, cpa, orco, hairmat, state, t);
/* try to estimate correct velocity */
if(vel){
@@ -3946,13 +3833,13 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
if(t>=0.001f){
tstate.time=t-0.001f;
- psys_get_particle_on_path(scene,ob,psys,p,&tstate,0);
+ psys_get_particle_on_path(sim,p,&tstate,0);
VECSUB(state->vel,state->co,tstate.co);
Normalize(state->vel);
}
else{
tstate.time=t+0.001f;
- psys_get_particle_on_path(scene, ob,psys,p,&tstate,0);
+ psys_get_particle_on_path(sim,p,&tstate,0);
VECSUB(state->vel,tstate.co,state->co);
Normalize(state->vel);
}
@@ -3962,39 +3849,50 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
}
}
/* 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(struct Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int always){
- ParticleSettings *part=psys->part;
- ParticleData *pa=0;
+int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always){
+ ParticleSystem *psys = sim->psys;
+ ParticleSettings *part = psys->part;
+ ParticleData *pa = NULL;
+ ChildParticle *cpa = NULL;
float cfra;
- int totpart=psys->totpart, between=0;
+ int totpart = psys->totpart;
/* negative time means "use current time" */
- if(state->time>0)
- cfra=state->time;
- else
- cfra= bsystem_time(scene, 0, (float)scene->r.cfra,0.0);
+ cfra = state->time > 0 ? state->time : bsystem_time(sim->scene, 0, (float)sim->scene->r.cfra, 0.0);
- if(psys->totchild && p>=totpart){
- if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
- between=1;
- }
- else
- pa=psys->particles+(psys->child+p-totpart)->parent;
- }
- else
- pa=psys->particles+p;
-
- if(between){
- state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL);
+ if(p>=totpart){
+ if(!psys->totchild)
+ return 0;
- if(always==0)
- if((state->time<0.0 && (part->flag & PART_UNBORN)==0)
- || (state->time>1.0 && (part->flag & PART_DIED)==0))
+ if(part->from != PART_FROM_PARTICLE && part->childtype == PART_CHILD_FACES){
+ if(!(psys->flag & PSYS_KEYED))
return 0;
+
+ cpa = psys->child + p - totpart;
+
+ state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL);
+
+ if(!always)
+ if((state->time < 0.0 && !(part->flag & PART_UNBORN))
+ || (state->time > 1.0 && !(part->flag & PART_DIED)))
+ return 0;
+
+ state->time= (cfra - (part->sta + (part->end - part->sta) * PSYS_FRAND(p + 23))) / (part->lifetime * PSYS_FRAND(p + 24));
+
+ psys_get_particle_on_path(sim, p, state,1);
+ return 1;
+ }
+ else {
+ cpa = sim->psys->child + p - totpart;
+ pa = sim->psys->particles + cpa->parent;
+ }
}
- else{
- if(pa->alive==PARS_KILLED) return 0;
- if(always==0)
+ else {
+ pa = sim->psys->particles + p;
+ }
+
+ if(pa) {
+ if(!always)
if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
|| (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
return 0;
@@ -4002,38 +3900,28 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
state->time = MIN2(state->time, pa->dietime);
}
- if(psys->flag & PSYS_KEYED){
- if(between){
- ChildParticle *cpa=psys->child+p-totpart;
- state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]);
- }
- else
- state->time= -cfra;
-
- psys_get_particle_on_path(scene, ob, psys, p, state,1);
+ if(sim->psys->flag & PSYS_KEYED){
+ state->time= -cfra;
+ psys_get_particle_on_path(sim, p, state,1);
return 1;
}
else{
- if(between)
- return 0; /* currently not supported */
- else if(psys->totchild && p>=psys->totpart){
- ChildParticle *cpa=psys->child+p-psys->totpart;
+ if(cpa){
ParticleKey *key1;
float t = (cfra - pa->time + pa->loop * pa->lifetime) / pa->lifetime;
- pa = psys->particles + cpa->parent;
key1=&pa->state;
offset_child(cpa, key1, state, part->childflat, part->childrad);
CLAMP(t,0.0,1.0);
if(part->kink) /* TODO: part->kink_freq*pa_kink */
- do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,ob->obmat);
+ do_prekink(state,key1,key1->rot,t,part->kink_freq,part->kink_shape,part->kink_amp,part->kink,part->kink_axis,sim->ob->obmat);
/* TODO: pa_clump vgroup */
do_clump(state,key1,t,part->clumpfac,part->clumppow,1.0);
if(psys->lattice)
- calc_latt_deform(psys->lattice, state->co,1.0f);
+ calc_latt_deform(sim->psys->lattice, state->co,1.0f);
}
else{
if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED))
@@ -4044,7 +3932,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
/* 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 = scene->r.frs_sec;
+ float dfra, keytime, frs_sec = sim->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 */
@@ -4079,8 +3967,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
}
}
- if(psys->lattice)
- calc_latt_deform(psys->lattice, state->co,1.0f);
+ if(sim->psys->lattice)
+ calc_latt_deform(sim->psys->lattice, state->co,1.0f);
}
return 1;
@@ -4136,8 +4024,11 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo
}
}
-void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
+void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
{
+ Object *ob = sim->ob;
+ ParticleSystem *psys = sim->psys;
+ ParticleSystemModifierData *psmd = sim->psmd;
float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4];
float xvec[3] = {-1.0, 0.0, 0.0}, q[4];
@@ -4145,7 +4036,7 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys
len= Normalize(vec);
if(pa)
- psys_particle_on_emitter(psmd,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
+ 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,