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.c307
1 files changed, 147 insertions, 160 deletions
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index e18e7f54e49..e63b77a134e 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"
@@ -96,8 +97,7 @@ int count_particles(ParticleSystem *psys){
int tot=0;
LOOP_SHOWN_PARTICLES {
- if(pa->alive == PARS_KILLED);
- else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
+ if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
else tot++;
}
@@ -109,8 +109,7 @@ int count_particles_mod(ParticleSystem *psys, int totgr, int cur){
int tot=0;
LOOP_SHOWN_PARTICLES {
- if(pa->alive == PARS_KILLED);
- else if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
+ if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
else if(p%totgr==cur) tot++;
}
@@ -302,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);
}
@@ -428,21 +423,23 @@ void psys_free_particles(ParticleSystem *psys)
}
void psys_free_pdd(ParticleSystem *psys)
{
- if(psys->pdd->cdata)
- MEM_freeN(psys->pdd->cdata);
- psys->pdd->cdata = NULL;
+ 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->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->ndata)
+ MEM_freeN(psys->pdd->ndata);
+ psys->pdd->ndata = NULL;
- if(psys->pdd->vedata)
- MEM_freeN(psys->pdd->vedata);
- psys->pdd->vedata = NULL;
+ if(psys->pdd->vedata)
+ MEM_freeN(psys->pdd->vedata);
+ psys->pdd->vedata = NULL;
+ }
}
/* free everything */
void psys_free(Object *ob, ParticleSystem * psys)
@@ -465,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){
@@ -493,10 +487,11 @@ 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);
@@ -1896,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;
+
+ 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;
-int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase *lb)
+ 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;
+ 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];
- effect[0]=effect[1]=effect[2]=0.0;
+ if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
+ pd = eff->pd;
- 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;
-
- 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;
}
@@ -2053,14 +2059,18 @@ static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheK
{
float force[3] = {0.0f,0.0f,0.0f}, vel[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= sim->psys->particles+i;
- do_effectors(sim, i, pa, &eff_key, 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 * sim->psys->part->eff_hair) / (float)steps);
@@ -2777,9 +2787,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra)
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(sim->scene, (ParticleKey*)ca, p, (float)k/(float)steps, &psys->effectors);
+ do_guides(sim->psys->effectors, (ParticleKey*)ca, p, (float)k/(float)steps);
/* apply lattice */
if(psys->lattice)
@@ -3187,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;
@@ -3199,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;
@@ -3249,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
@@ -3261,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);
}
@@ -3348,24 +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);
- }
-}
/************************************************/
/* Textures */
@@ -3646,7 +3635,7 @@ static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *pte
if(part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
- guided = do_guide(sim->scene, (ParticleKey*)state, cpa->parent, t, &(sim->psys->effectors));
+ guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t);
if(guided==0){
if(part->kink)
@@ -3716,8 +3705,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
Mat4MulVecfl(hairmat, state->co);
Mat4Mul3Vecfl(hairmat, state->vel);
- if(psys->effectors.first && (part->flag & PART_CHILD_GUIDE)==0) {
- do_guide(sim->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 */
}
@@ -3905,8 +3894,6 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
}
if(pa) {
- if(pa->alive == PARS_KILLED) return 0;
-
if(!always)
if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
|| (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))