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:
-rw-r--r--source/blender/blenkernel/BKE_effect.h4
-rw-r--r--source/blender/blenkernel/intern/anim.c41
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c6
-rw-r--r--source/blender/blenkernel/intern/effect.c1331
-rw-r--r--source/blender/blenkernel/intern/softbody.c50
-rw-r--r--source/blender/blenloader/intern/readfile.c11
-rw-r--r--source/blender/include/BIF_butspace.h2
-rw-r--r--source/blender/include/butspace.h3
-rw-r--r--source/blender/makesdna/DNA_effect_types.h24
-rw-r--r--source/blender/makesdna/DNA_object_force.h1
-rw-r--r--source/blender/renderconverter/intern/convertBlenderScene.c122
-rw-r--r--source/blender/src/buttons_editing.c15
-rw-r--r--source/blender/src/buttons_object.c385
-rw-r--r--source/blender/src/drawobject.c62
-rw-r--r--source/blender/src/editobject.c3
15 files changed, 1347 insertions, 713 deletions
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index cb58496465f..9ebafdff3e4 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -57,7 +57,9 @@ void build_particle_system(struct Object *ob);
/* particle deflector */
#define PE_WIND_AS_SPEED 0x00000001
-void pdDoEffector(float *opco, float *force, float *speed, float cur_time, unsigned int par_layer,unsigned int flags);
+struct ListBase *pdInitEffectors(unsigned int layer);
+void pdEndEffectors(struct ListBase *lb);
+void pdDoEffectors(struct ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags);
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 4d08f958057..dcd49f9f0b2 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -200,6 +200,7 @@ int interval_test(int min, int max, int p1, int cycl)
}
/* warning, *vec needs FOUR items! */
+/* ctime is normalized range <0-1> */
int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* returns OK */
{
Curve *cu;
@@ -488,29 +489,29 @@ void particle_duplilist(Scene *sce, Object *par, PartEff *paf)
}
else { // non static particles
- if(ctime > pa->time) {
- if(ctime < pa->time+pa->lifetime) {
- newob= new_dupli_object(&duplilist, ob, par);
+ if((paf->flag & PAF_UNBORN)==0 && ctime < pa->time) continue;
+ if((paf->flag & PAF_DIED)==0 && ctime > pa->time+pa->lifetime) continue;
- /* to give ipos in object correct offset */
- where_is_object_time(newob, ctime-pa->time);
-
- where_is_particle(paf, pa, ctime, vec);
- if(paf->stype==PAF_VECT) {
- where_is_particle(paf, pa, ctime+1.0f, vec1);
-
- VecSubf(vec1, vec1, vec);
- q2= vectoquat(vec1, ob->trackflag, ob->upflag);
-
- QuatToMat3(q2, mat);
- Mat4CpyMat4(tmat, newob->obmat);
- Mat4MulMat43(newob->obmat, tmat, mat);
- }
+ //if(ctime < pa->time+pa->lifetime) {
+ newob= new_dupli_object(&duplilist, ob, par);
- VECCOPY(newob->obmat[3], vec);
- }
+ /* to give ipos in object correct offset */
+ where_is_object_time(newob, ctime-pa->time);
+
+ where_is_particle(paf, pa, ctime, vec);
+ if(paf->stype==PAF_VECT) {
+ where_is_particle(paf, pa, ctime+1.0f, vec1);
+
+ VecSubf(vec1, vec1, vec);
+ q2= vectoquat(vec1, ob->trackflag, ob->upflag);
+
+ QuatToMat3(q2, mat);
+ Mat4CpyMat4(tmat, newob->obmat);
+ Mat4MulMat43(newob->obmat, tmat, mat);
}
- }
+
+ VECCOPY(newob->obmat[3], vec);
+ }
}
break;
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 8bb010a7847..d211305f0f3 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -467,9 +467,13 @@ struct DagForest *build_dag(struct Scene *sce, short mask)
}
else if(ob->type==OB_MESH) {
PartEff *paf= give_parteff(ob);
- if(paf && (paf->flag & PAF_STATIC)) {
+ if(paf) {
Base *base1;
+ /* ob location depends on itself */
+ if((paf->flag & PAF_STATIC)==0)
+ dag_add_relation(dag, node, node, DAG_RL_OB_DATA);
+
/* force fields, warning for loop inside loop... */
for(base1 = G.scene->base.first; base1; base1= base1->next) {
if( (base1->lay & base->lay) && base1->object->pd) {
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index eb4eb243000..21eafc39fc0 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -55,6 +55,7 @@
#include "BLI_rand.h"
#include "BKE_action.h"
+#include "BKE_anim.h" /* needed for where_on_path */
#include "BKE_armature.h"
#include "BKE_bad_level_calls.h"
#include "BKE_blender.h"
@@ -74,8 +75,8 @@
#include "BKE_screen.h"
#include "BKE_utildefines.h"
-#include "render.h" // externtex, bad level call (ton)
-
+#include "render.h" // externtex, bad level call (ton)
+#include "PIL_time.h"
Effect *add_effect(int type)
{
@@ -102,7 +103,9 @@ Effect *add_effect(int type)
paf->staticstep= 5;
paf->defvec[2]= 1.0f;
paf->nabla= 0.05f;
-
+ paf->disp = 100;
+ paf->speedtex = 8;
+ paf->omat = 1;
break;
}
@@ -205,7 +208,7 @@ static Particle *new_particle(PartEff *paf)
static int cur;
/* we agree: when paf->keys==0: alloc */
- if(paf->keys==0) {
+ if(paf->keys==NULL) {
pa= paf->keys= MEM_callocN( paf->totkey*paf->totpart*sizeof(Particle), "particlekeys" );
cur= 0;
}
@@ -234,7 +237,7 @@ void where_is_particle(PartEff *paf, Particle *pa, float ctime, float *vec)
float dt, t[4];
int a;
- if(paf->totkey==1) {
+ if(paf->totkey==1 || ctime < pa->time) {
VECCOPY(vec, pa->co);
return;
}
@@ -252,7 +255,7 @@ void where_is_particle(PartEff *paf, Particle *pa, float ctime, float *vec)
if(a+1<paf->totkey) p[2]= pa+1; else p[2]= pa;
if(a+2<paf->totkey) p[3]= pa+2; else p[3]= p[2];
- if(p[1]==p[2]) dt= 0.0;
+ if(p[1]==p[2] || p[2]->time == p[1]->time) dt= 0.0;
else dt= (ctime-p[1]->time)/(p[2]->time - p[1]->time);
if(paf->flag & PAF_BSPLINE) set_four_ipo(dt, t, KEY_BSPLINE);
@@ -301,16 +304,111 @@ static void particle_tex(MTex *mtex, PartEff *paf, float *co, float *no)
}
}
-/* -------- pdDoEffector() --------
+
+/* -------------------------- Effectors ------------------ */
+
+typedef struct pEffectorCache {
+ struct pEffectorCache *next, *prev;
+ struct Object *ob;
+
+ /* precalculated variables */
+ float oldloc[3], oldspeed[3];
+ float scale, time_scale;
+ float guide_dist;
+} pEffectorCache;
+
+
+/* returns ListBase handle with objects taking part in the effecting */
+ListBase *pdInitEffectors(unsigned int layer)
+{
+ static ListBase listb={NULL, NULL};
+ Base *base;
+
+ for(base = G.scene->base.first; base; base= base->next) {
+ if( (base->lay & layer) && base->object->pd) {
+ Object *ob= base->object;
+ PartDeflect *pd= ob->pd;
+
+ if(pd->forcefield == PFIELD_GUIDE) {
+ if(ob->type==OB_CURVE) {
+ Curve *cu= ob->data;
+ if((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+ pEffectorCache *ec= MEM_callocN(sizeof(pEffectorCache), "effector cache");
+ ec->ob= ob;
+ BLI_addtail(&listb, ec);
+ }
+ }
+ }
+ else if(pd->forcefield) {
+ pEffectorCache *ec= MEM_callocN(sizeof(pEffectorCache), "effector cache");
+ ec->ob= ob;
+ BLI_addtail(&listb, ec);
+ }
+ }
+ }
+ if(listb.first)
+ return &listb;
+
+ return NULL;
+}
+
+void pdEndEffectors(ListBase *lb)
+{
+ if(lb)
+ BLI_freelistN(lb);
+}
+
+/* local for this c file, only for guides now */
+static void precalc_effectors(Object *ob, PartEff *paf, Particle *pa, ListBase *lb)
+{
+ pEffectorCache *ec;
+
+ for(ec= lb->first; ec; ec= ec->next) {
+ if(ec->ob->type==OB_CURVE) {
+ float vec[4], dir[3];
+
+ /* scale corrects speed vector to curve size */
+ if(paf->totkey>1) ec->scale= (paf->totkey-1)/pa->lifetime;
+ else ec->scale= 1.0f;
+
+ /* time_scale is for random life */
+ if(pa->lifetime>paf->lifetime)
+ ec->time_scale= paf->lifetime/pa->lifetime;
+ else
+ ec->time_scale= pa->lifetime/paf->lifetime;
+
+ /* distance of first path point to particle origin */
+ where_on_path(ec->ob, 0.0f, vec, dir);
+ VECCOPY(ec->oldloc, vec); /* store local coord for differences */
+ Mat4MulVecfl(ec->ob->obmat, vec);
+
+ /* for static we need to move to global space */
+ if(paf->flag & PAF_STATIC) {
+ VECCOPY(dir, pa->co);
+ Mat4MulVecfl(ob->obmat, dir);
+ ec->guide_dist= VecLenf(vec, dir);
+ }
+ else
+ ec->guide_dist= VecLenf(vec, pa->co);
+ }
+ }
+}
+
+
+/* -------- pdDoEffectors() --------
generic force/speed system, now used for particles and softbodies
+ lb = listbase with objects that take part in effecting
opco = global coord, as input
force = force accumulator
- speed = speed accumulator
- cur_time = in frames
+ speed = actual current speed which can be altered
+ cur_time = "external" time in frames, is constant for static particles
+ loc_time = "local" time in frames, range <0-1> for the lifetime of particle
par_layer = layer the caller is in
+ flags = only used for softbody wind now
+ guide = old speed of particle
*/
-void pdDoEffector(float *opco, float *force, float *speed, float cur_time, unsigned int par_layer,unsigned int flags)
+void pdDoEffectors(ListBase *lb, float *opco, float *force, float *speed, float cur_time, float loc_time, unsigned int flags)
{
/*
Modifies the force on a particle according to its
@@ -321,116 +419,186 @@ void pdDoEffector(float *opco, float *force, float *speed, float cur_time, unsig
Vortex fields: swirling effectors
(particles rotate around Z-axis of the object. otherwise, same relation as)
(Forcefields, but this is not done through a force/acceleration)
-
+ Guide: particles on a path
+ (particles are guided along a curve bezier or old nurbs)
+ (is independent of other effectors)
*/
Object *ob;
- Base *base;
+ pEffectorCache *ec;
PartDeflect *pd;
float vect_to_vert[3];
- float force_vec[3];
- float f_force, distance;
+ float f_force, force_vec[3];
float *obloc;
- float force_val, ffall_val;
+ float distance, force_val, ffall_val;
+ float guidecollect[3], guidedist= 0.0f;
short cur_frame;
+
+ guidecollect[0]= guidecollect[1]= guidecollect[2]=0.0f;
- /* Cycle through objects, get total of (1/(gravity_strength * dist^gravity_power)) */
+ /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
/* Check for min distance here? (yes would be cool to add that, ton) */
- for(base = G.scene->base.first; base; base= base->next) {
- if( (base->lay & par_layer) && base->object->pd) {
- ob= base->object;
- pd= ob->pd;
+ for(ec = lb->first; ec; ec= ec->next) {
+ /* object effectors were fully checked to be OK to evaluate! */
+ ob= ec->ob;
+ pd= ob->pd;
- /* checking if to continue or not */
- if(pd->forcefield==0) continue;
+ /* Get IPO force strength and fall off values here */
+ if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+ force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, cur_time);
+ else
+ force_val = pd->f_strength;
+
+ if (has_ipo_code(ob->ipo, OB_PD_FFALL))
+ ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, cur_time);
+ else
+ ffall_val = pd->f_power;
- /* Get IPO force strength and fall off values here */
- if (has_ipo_code(ob->ipo, OB_PD_FSTR))
- force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, cur_time);
- else
- force_val = pd->f_strength;
+ /* Need to set r.cfra for paths (investigate, ton) (uses ob->ctime now, ton) */
+ if(ob->ctime!=cur_time) {
+ cur_frame = G.scene->r.cfra;
+ G.scene->r.cfra = (short)cur_time;
+ where_is_object_time(ob, cur_time);
+ G.scene->r.cfra = cur_frame;
+ }
- if (has_ipo_code(ob->ipo, OB_PD_FFALL))
- ffall_val = IPO_GetFloatValue(ob->ipo, OB_PD_FFALL, cur_time);
- else
- ffall_val = pd->f_power;
+ /* use center of object for distance calculus */
+ obloc= ob->obmat[3];
+ VECSUB(vect_to_vert, obloc, opco);
+ distance = VecLength(vect_to_vert);
+ if((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist && pd->forcefield != PFIELD_GUIDE)
+ ; /* don't do anything */
+ else if(pd->forcefield == PFIELD_WIND) {
+ VECCOPY(force_vec, ob->obmat[2]);
- /* Need to set r.cfra for paths (investigate, ton) (uses ob->ctime now, ton) */
- if(ob->ctime!=cur_time) {
- cur_frame = G.scene->r.cfra;
- G.scene->r.cfra = (short)cur_time;
- where_is_object_time(ob, cur_time);
- G.scene->r.cfra = cur_frame;
+ /* wind works harder perpendicular to normal, would be nice for softbody later (ton) */
+
+ /* Limit minimum distance to vertex so that */
+ /* the force is not too big */
+ if (distance < 0.001) distance = 0.001f;
+ f_force = (force_val)*(1/(1000 * (float)pow((double)distance, (double)ffall_val)));
+ /* this option for softbody only */
+ if(flags && PE_WIND_AS_SPEED){
+ speed[0] -= (force_vec[0] * f_force );
+ speed[1] -= (force_vec[1] * f_force );
+ speed[2] -= (force_vec[2] * f_force );
+ }
+ else{
+ force[0] += force_vec[0]*f_force;
+ force[1] += force_vec[1]*f_force;
+ force[2] += force_vec[2]*f_force;
}
+ }
+ else if(pd->forcefield == PFIELD_FORCE) {
- /* use center of object for distance calculus */
+ /* only use center of object */
obloc= ob->obmat[3];
+
+ /* Now calculate the gravitational force */
VECSUB(vect_to_vert, obloc, opco);
distance = VecLength(vect_to_vert);
+
+ /* Limit minimum distance to vertex so that */
+ /* the force is not too big */
+ if (distance < 0.001) distance = 0.001f;
+ f_force = (force_val)*(1.0/(1000.0 * (float)pow((double)distance, (double)ffall_val)));
+ force[0] += (vect_to_vert[0] * f_force );
+ force[1] += (vect_to_vert[1] * f_force );
+ force[2] += (vect_to_vert[2] * f_force );
+ }
+ else if(pd->forcefield == PFIELD_VORTEX) {
+ float vortexvec[3];
- if((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist)
- ; /* don't do anything */
- else if(pd->forcefield == PFIELD_WIND) {
- VECCOPY(force_vec, ob->obmat[2]);
-
- /* wind works harder perpendicular to normal, would be nice for softbody later (ton) */
-
- /* Limit minimum distance to vertex so that */
- /* the force is not too big */
- if (distance < 0.001) distance = 0.001f;
- f_force = (force_val)*(1/(1000 * (float)pow((double)distance, (double)ffall_val)));
- if(flags &&PE_WIND_AS_SPEED){
- speed[0] -= (force_vec[0] * f_force );
- speed[1] -= (force_vec[1] * f_force );
- speed[2] -= (force_vec[2] * f_force );
- }
- else{
- force[0] += force_vec[0]*f_force;
- force[1] += force_vec[1]*f_force;
- force[2] += force_vec[2]*f_force;
- }
- }
- else if(pd->forcefield == PFIELD_FORCE) {
-
- /* only use center of object */
- obloc= ob->obmat[3];
+ /* only use center of object */
+ obloc= ob->obmat[3];
- /* Now calculate the gravitational force */
- VECSUB(vect_to_vert, obloc, opco);
- distance = VecLength(vect_to_vert);
+ /* Now calculate the vortex force */
+ VECSUB(vect_to_vert, obloc, opco);
+ distance = VecLength(vect_to_vert);
- /* Limit minimum distance to vertex so that */
- /* the force is not too big */
- if (distance < 0.001) distance = 0.001f;
- f_force = (force_val)*(1/(1000 * (float)pow((double)distance, (double)ffall_val)));
- force[0] += (vect_to_vert[0] * f_force );
- force[1] += (vect_to_vert[1] * f_force );
- force[2] += (vect_to_vert[2] * f_force );
+ Crossf(force_vec, ob->obmat[2], vect_to_vert);
+ Normalise(force_vec);
+ /* Limit minimum distance to vertex so that */
+ /* the force is not too big */
+ if (distance < 0.001) distance = 0.001f;
+ f_force = (force_val)*(1.0/(100.0 * (float)pow((double)distance, (double)ffall_val)));
+ vortexvec[0]= -(force_vec[0] * f_force );
+ vortexvec[1]= -(force_vec[1] * f_force );
+ vortexvec[2]= -(force_vec[2] * f_force );
+
+ /* this option for softbody only */
+ if(flags &&PE_WIND_AS_SPEED) {
+ speed[0]+= vortexvec[0];
+ speed[1]+= vortexvec[1];
+ speed[2]+= vortexvec[2];
}
- else if(pd->forcefield == PFIELD_VORTEX) {
-
- /* only use center of object */
- obloc= ob->obmat[3];
-
- /* Now calculate the vortex force */
- VECSUB(vect_to_vert, obloc, opco);
- distance = VecLength(vect_to_vert);
-
- Crossf(force_vec, ob->obmat[2], vect_to_vert);
- Normalise(force_vec);
-
- /* Limit minimum distance to vertex so that */
- /* the force is not too big */
- if (distance < 0.001) distance = 0.001f;
- f_force = (force_val)*(1/(100 * (float)pow((double)distance, (double)ffall_val)));
- speed[0] -= (force_vec[0] * f_force );
- speed[1] -= (force_vec[1] * f_force );
- speed[2] -= (force_vec[2] * f_force );
-
+ else {
+ /* since vortex alters the speed, we have to correct for the previous vortex result */
+ speed[0]+= vortexvec[0] - ec->oldspeed[0];
+ speed[1]+= vortexvec[1] - ec->oldspeed[1];
+ speed[2]+= vortexvec[2] - ec->oldspeed[2];
+
+ VECCOPY(ec->oldspeed, vortexvec);
}
}
+ else if(pd->forcefield == PFIELD_GUIDE) {
+ float guidevec[4], guidedir[3];
+ float mindist= force_val; /* force_val is actually mindist in the UI */
+
+ distance= ec->guide_dist;
+
+ /* WARNING: bails out with continue here */
+ if((pd->flag & PFIELD_USEMAX) && distance>pd->maxdist) continue;
+
+ /* derive path point from loc_time */
+ where_on_path(ob, loc_time*ec->time_scale, guidevec, guidedir);
+ VECSUB(guidedir, guidevec, ec->oldloc);
+ VECCOPY(ec->oldloc, guidevec);
+
+ Mat4Mul3Vecfl(ob->obmat, guidedir);
+ VecMulf(guidedir, ec->scale); /* correction for lifetime and speed */
+
+ /* we subtract the speed we gave it previous step */
+ VECCOPY(guidevec, guidedir);
+ VECSUB(guidedir, guidedir, ec->oldspeed);
+ VECCOPY(ec->oldspeed, guidevec);
+
+ /* calculate contribution factor for this guide */
+ if(distance<=mindist) f_force= 1.0f;
+ else if(pd->flag & PFIELD_USEMAX) {
+ if(distance>pd->maxdist || mindist>=pd->maxdist) f_force= 0.0f;
+ else {
+ f_force= 1.0f - (distance-mindist)/(pd->maxdist - mindist);
+ if(ffall_val!=0.0f)
+ f_force = (float)pow(f_force, ffall_val+1.0);
+ }
+ }
+ else {
+ f_force= 1.0f/(1.0f + distance-mindist);
+ if(ffall_val!=0.0f)
+ f_force = (float)pow(f_force, ffall_val+1.0);
+ }
+
+ /* if it fully contributes, we stop */
+ if(f_force==1.0) {
+ VECCOPY(guidecollect, guidedir);
+ guidedist= 1.0f;
+ break;
+ }
+ else if(guidedist<1.0f) {
+ VecMulf(guidedir, f_force);
+ VECADD(guidecollect, guidecollect, guidedir);
+ guidedist += f_force;
+ }
+ }
+ }
+
+ /* all guides are accumulated here */
+ if(guidedist!=0.0f) {
+ if(guidedist!=1.0f) VecMulf(guidecollect, 1.0f/guidedist);
+ VECADD(speed, speed, guidecollect);
}
}
@@ -788,11 +956,11 @@ static int pdDoDeflection(RNG *rng, float opco[3], float npco[3], float opno[3],
part = current particle
force = force vector
deform = flag to indicate lattice deform
- cfraont = current frame
*/
-static void make_particle_keys(RNG *rng, Object *ob, int depth, int nr, PartEff *paf, Particle *part, float *force, int deform, MTex *mtex, unsigned int par_layer, int cfraont)
+static void make_particle_keys(RNG *rng, Object *ob, int depth, int nr, PartEff *paf, Particle *part, float *force, int deform, MTex *mtex, unsigned int par_layer)
{
Particle *pa, *opa = NULL;
+ ListBase *effectorbase;
float damp, deltalife, life;
float cur_time;
float opco[3], opno[3], npco[3], npno[3], new_force[3], new_speed[3];
@@ -814,120 +982,122 @@ static void make_particle_keys(RNG *rng, Object *ob, int depth, int nr, PartEff
particle_tex(mtex, paf, pa->co, pa->no);
}
+ /* effectors here? */
+ effectorbase= pdInitEffectors(par_layer);
+ if(effectorbase)
+ precalc_effectors(ob, paf, pa, effectorbase);
+
if(paf->totkey>1) deltalife= pa->lifetime/(paf->totkey-1);
else deltalife= pa->lifetime;
+ /* longer lifetime results in longer distance covered */
+ VecMulf(pa->no, deltalife);
+
opa= pa;
pa++;
- b= paf->totkey-1;
- while(b--) {
+ for(b=1; b<paf->totkey; b++) {
+
/* new time */
pa->time= opa->time+deltalife;
+ cur_time = pa->time;
/* set initial variables */
- opco[0] = opa->co[0];
- opco[1] = opa->co[1];
- opco[2] = opa->co[2];
-
- new_force[0] = force[0];
- new_force[1] = force[1];
- new_force[2] = force[2];
- new_speed[0] = 0.0;
- new_speed[1] = 0.0;
- new_speed[2] = 0.0;
-
- /* handle differences between static (local coords, fixed frae) and dynamic */
- if(paf->flag & PAF_STATIC) {
- float opco1[3], new_force1[3], new_speed1[3];
-
- /* move to global coords */
- VECCOPY(opco1, opco);
- Mat4MulVecfl(ob->obmat, opco1);
-
- VECCOPY(new_force1, new_force);
- Mat4Mul3Vecfl(ob->obmat, new_force1);
- VECCOPY(new_speed1, new_speed);
- Mat4Mul3Vecfl(ob->obmat, new_speed1);
-
- cur_time = cfraont;
-
- /* force fields */
- pdDoEffector(opco1, new_force1, new_speed1, cur_time, par_layer, 0);
+ VECCOPY(opco, opa->co);
+ VECCOPY(new_force, force);
+ VECCOPY(new_speed, opa->no);
+ VecMulf(new_speed, 1.0f/deltalife);
+ //new_speed[0] = new_speed[1] = new_speed[2] = 0.0f;
+
+ /* handle differences between static (local coords, fixed frame) and dynamic */
+ if(effectorbase) {
+ float loc_time= ((float)b)/(float)(paf->totkey-1);
- /* move back to local */
- VECCOPY(opco, opco1);
- Mat4MulVecfl(ob->imat, opco);
-
- VECCOPY(new_force, new_force1);
- Mat4Mul3Vecfl(ob->imat, new_force);
- VECCOPY(new_speed, new_speed1);
- Mat4Mul3Vecfl(ob->imat, new_speed);
- }
- else {
- cur_time = pa->time;
-
- /* force fields */
- pdDoEffector(opco, new_force, new_speed, cur_time, par_layer,0);
- }
-
- /* new location */
- pa->co[0]= opa->co[0] + deltalife * (opa->no[0] + new_speed[0] + 0.5f*new_force[0]);
- pa->co[1]= opa->co[1] + deltalife * (opa->no[1] + new_speed[1] + 0.5f*new_force[1]);
- pa->co[2]= opa->co[2] + deltalife * (opa->no[2] + new_speed[2] + 0.5f*new_force[2]);
-
- /* new speed */
- pa->no[0]= opa->no[0] + deltalife*new_force[0];
- pa->no[1]= opa->no[1] + deltalife*new_force[1];
- pa->no[2]= opa->no[2] + deltalife*new_force[2];
-
- /* Particle deflection code */
- deflection = 0;
- finish_defs = 1;
- def_count = 0;
-
- VECCOPY(opno, opa->no);
- VECCOPY(npco, pa->co);
- VECCOPY(npno, pa->no);
-
- life = deltalife;
- cur_time -= deltalife;
-
- last_ob = -1;
- last_fc = -1;
- same_fc = 0;
-
- /* First call the particle deflection check for the particle moving */
- /* between the old co-ordinates and the new co-ordinates */
- /* If a deflection occurs, call the code again, this time between the */
- /* intersection point and the updated new co-ordinates */
- /* Bail out if we've done the calculation 10 times - this seems ok */
- /* for most scenes I've tested */
- while (finish_defs) {
- deflected = pdDoDeflection(rng, opco, npco, opno, npno, life, new_force,
- def_count, cur_time, par_layer,
- &last_ob, &last_fc, &same_fc);
- if (deflected) {
- def_count = def_count + 1;
- deflection = 1;
- if (def_count==10) finish_defs = 0;
+ if(paf->flag & PAF_STATIC) {
+ float opco1[3], new_force1[3];
+
+ /* move co and force to global coords */
+ VECCOPY(opco1, opco);
+ Mat4MulVecfl(ob->obmat, opco1);
+ VECCOPY(new_force1, new_force);
+ Mat4Mul3Vecfl(ob->obmat, new_force1);
+
+ cur_time = G.scene->r.cfra;
+
+ /* force fields */
+ pdDoEffectors(effectorbase, opco1, new_force1, new_speed, cur_time, loc_time, 0);
+
+ /* move co, force and newspeed back to local */
+ VECCOPY(opco, opco1);
+ Mat4MulVecfl(ob->imat, opco);
+ VECCOPY(new_force, new_force1);
+ Mat4Mul3Vecfl(ob->imat, new_force);
+ Mat4Mul3Vecfl(ob->imat, new_speed);
}
else {
- finish_defs = 0;
+ /* force fields */
+ pdDoEffectors(effectorbase, opco, new_force, new_speed, cur_time, loc_time, 0);
}
}
+
+ /* new speed */
+ pa->no[0]= deltalife * (new_speed[0] + new_force[0]);
+ pa->no[1]= deltalife * (new_speed[1] + new_force[1]);
+ pa->no[2]= deltalife * (new_speed[2] + new_force[2]);
+
+ /* new location */
+ pa->co[0]= opa->co[0] + pa->no[0];
+ pa->co[1]= opa->co[1] + pa->no[1];
+ pa->co[2]= opa->co[2] + pa->no[2];
- /* Only update the particle positions and speed if we had a deflection */
- if (deflection) {
- pa->co[0] = npco[0];
- pa->co[1] = npco[1];
- pa->co[2] = npco[2];
- pa->no[0] = npno[0];
- pa->no[1] = npno[1];
- pa->no[2] = npno[2];
- }
-
+ /* Particle deflection code */
+ if((paf->flag & PAF_STATIC)==0) {
+ deflection = 0;
+ finish_defs = 1;
+ def_count = 0;
+
+ VECCOPY(opno, opa->no);
+ VECCOPY(npco, pa->co);
+ VECCOPY(npno, pa->no);
+
+ life = deltalife;
+ cur_time -= deltalife;
+
+ last_ob = -1;
+ last_fc = -1;
+ same_fc = 0;
+
+ /* First call the particle deflection check for the particle moving */
+ /* between the old co-ordinates and the new co-ordinates */
+ /* If a deflection occurs, call the code again, this time between the */
+ /* intersection point and the updated new co-ordinates */
+ /* Bail out if we've done the calculation 10 times - this seems ok */
+ /* for most scenes I've tested */
+ while (finish_defs) {
+ deflected = pdDoDeflection(rng, opco, npco, opno, npno, life, new_force,
+ def_count, cur_time, par_layer,
+ &last_ob, &last_fc, &same_fc);
+ if (deflected) {
+ def_count = def_count + 1;
+ deflection = 1;
+ if (def_count==10) finish_defs = 0;
+ }
+ else {
+ finish_defs = 0;
+ }
+ }
+ /* Only update the particle positions and speed if we had a deflection */
+ if (deflection) {
+ pa->co[0] = npco[0];
+ pa->co[1] = npco[1];
+ pa->co[2] = npco[2];
+ pa->no[0] = npno[0];
+ pa->no[1] = npno[1];
+ pa->no[2] = npno[2];
+ }
+ }
+
/* speed: texture */
if(mtex && paf->texfac!=0.0) {
particle_tex(mtex, paf, pa->co, pa->no);
@@ -937,9 +1107,7 @@ static void make_particle_keys(RNG *rng, Object *ob, int depth, int nr, PartEff
pa->no[1]*= damp;
pa->no[2]*= damp;
}
-
-
-
+
opa= pa;
pa++;
/* opa is used later on too! */
@@ -974,13 +1142,18 @@ static void make_particle_keys(RNG *rng, Object *ob, int depth, int nr, PartEff
}
pa->mat_nr= paf->mat[depth];
- make_particle_keys(rng, ob, depth+1, b, paf, pa, force, deform, mtex, par_layer, cfraont);
+ make_particle_keys(rng, ob, depth+1, b, paf, pa, force, deform, mtex, par_layer);
}
}
}
+
+ /* cleanup */
+ if(effectorbase)
+ pdEndEffectors(effectorbase);
+
}
-static void init_mv_jit(float *jit, int num,int seed2)
+static void init_mv_jit(float *jit, int num, int seed2)
{
RNG *rng;
float *jit2, x, rad1, rad2, rad3;
@@ -1018,211 +1191,414 @@ static void init_mv_jit(float *jit, int num,int seed2)
rng_free(rng);
}
+#define JIT_RAND 32
-static void give_mesh_mvert(Mesh *me, DispListMesh *dlm, int nr, float *co, short *no, int seed2)
+/* for a position within a face, tot is total amount of faces */
+static void give_mesh_particle_coord(PartEff *paf, MVert *mvert, MFace *mface, int partnr, int subnr, float *co, short *no)
{
- static float *jit=0;
- static int jitlevel=1;
- MVert *mvert, *mvertbase=NULL;
- MFace *mface, *mfacebase=NULL;
- float u, v, *v1, *v2, *v3, *v4;
- int totface=0, totvert=0, curface, curjit;
+ static float *jit= NULL;
+ static float *trands= NULL;
+ static int jitlevel= 1;
+ float *v1, *v2, *v3, *v4;
+ float u, v;
short *n1, *n2, *n3, *n4;
- /* signal */
- if(me==0) {
+ /* free signal */
+ if(paf==NULL) {
if(jit) MEM_freeN(jit);
- jit= 0;
+ jit= NULL;
+ if(trands) MEM_freeN(trands);
+ trands= NULL;
return;
}
- if(dlm) {
- mvertbase= dlm->mvert;
- mfacebase= dlm->mface;
- totface= dlm->totface;
- totvert= dlm->totvert;
+ /* first time initialize jitter or trand, partnr then is total amount of particles, subnr total amount of faces */
+ if(trands==NULL && jit==NULL) {
+ RNG *rng = rng_new(31415926 + paf->seed);
+ int i, tot;
+
+ if(paf->flag & PAF_TRAND)
+ tot= partnr;
+ else
+ tot= JIT_RAND; /* arbitrary... allows JIT_RAND times more particles in a face for jittered distro */
+
+ trands= MEM_callocN(2+2*tot*sizeof(float), "trands");
+ for(i=0; i<tot; i++) {
+ trands[2*i]= rng_getFloat(rng);
+ trands[2*i+1]= rng_getFloat(rng);
+ }
+ rng_free(rng);
+
+ if((paf->flag & PAF_TRAND)==0) {
+ jitlevel= paf->userjit;
+
+ if(jitlevel == 0) {
+ jitlevel= partnr/subnr;
+ if(paf->flag & PAF_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */
+ if(jitlevel<3) jitlevel= 3;
+ if(jitlevel>100) jitlevel= 100;
+ }
+
+ jit= MEM_callocN(2+ jitlevel*2*sizeof(float), "jit");
+ init_mv_jit(jit, jitlevel, paf->seed);
+ BLI_array_randomize(jit, 2*sizeof(float), jitlevel, paf->seed); /* for custom jit or even distribution */
+ }
+ return;
}
- if(totvert==0) {
- mvertbase= me->mvert;
- mfacebase= me->mface;
- totface= me->totface;
- totvert= me->totvert;
+ if(paf->flag & PAF_TRAND) {
+ u= trands[2*partnr];
+ v= trands[2*partnr+1];
}
+ else {
+ /* jittered distribution gets fixed random offset */
+ if(subnr>=jitlevel) {
+ int jitrand= (subnr/jitlevel) % JIT_RAND;
+
+ subnr %= jitlevel;
+ u= jit[2*subnr] + trands[2*jitrand];
+ v= jit[2*subnr+1] + trands[2*jitrand+1];
+ if(u > 1.0f) u-= 1.0f;
+ if(v > 1.0f) v-= 1.0f;
+ }
+ else {
+ u= jit[2*subnr];
+ v= jit[2*subnr+1];
+ }
+ }
+
+ v1= (mvert+(mface->v1))->co;
+ v2= (mvert+(mface->v2))->co;
+ v3= (mvert+(mface->v3))->co;
+ n1= (mvert+(mface->v1))->no;
+ n2= (mvert+(mface->v2))->no;
+ n3= (mvert+(mface->v3))->no;
- if(totface==0 || nr<totvert) {
- mvert= mvertbase + (nr % totvert);
- VECCOPY(co, mvert->co);
- VECCOPY(no, mvert->no);
+ if(mface->v4) {
+ float uv= u*v;
+ float muv= (1.0f-u)*(v);
+ float umv= (u)*(1.0f-v);
+ float mumv= (1.0f-u)*(1.0f-v);
+
+ v4= (mvert+(mface->v4))->co;
+ n4= (mvert+(mface->v4))->no;
+
+ co[0]= mumv*v1[0] + muv*v2[0] + uv*v3[0] + umv*v4[0];
+ co[1]= mumv*v1[1] + muv*v2[1] + uv*v3[1] + umv*v4[1];
+ co[2]= mumv*v1[2] + muv*v2[2] + uv*v3[2] + umv*v4[2];
+
+ no[0]= (short)(mumv*n1[0] + muv*n2[0] + uv*n3[0] + umv*n4[0]);
+ no[1]= (short)(mumv*n1[1] + muv*n2[1] + uv*n3[1] + umv*n4[1]);
+ no[2]= (short)(mumv*n1[2] + muv*n2[2] + uv*n3[2] + umv*n4[2]);
}
else {
-
- nr-= totvert;
+ /* mirror triangle uv coordinates when on other side */
+ if(u + v > 1.0f) {
+ u= 1.0f-u;
+ v= 1.0f-v;
+ }
+ co[0]= v1[0] + u*(v3[0]-v1[0]) + v*(v2[0]-v1[0]);
+ co[1]= v1[1] + u*(v3[1]-v1[1]) + v*(v2[1]-v1[1]);
+ co[2]= v1[2] + u*(v3[2]-v1[2]) + v*(v2[2]-v1[2]);
- if(jit==0) {
- jitlevel= nr/totface;
- if(jitlevel==0) jitlevel= 1;
- if(jitlevel>100) jitlevel= 100;
+ no[0]= (short)(n1[0] + u*(n3[0]-n1[0]) + v*(n2[0]-n1[0]));
+ no[1]= (short)(n1[1] + u*(n3[1]-n1[1]) + v*(n2[1]-n1[1]));
+ no[2]= (short)(n1[2] + u*(n3[2]-n1[2]) + v*(n2[2]-n1[2]));
+ }
+}
- jit= MEM_callocN(2+ jitlevel*2*sizeof(float), "jit");
- init_mv_jit(jit, jitlevel,seed2);
-
+
+/* Gets a MDeformVert's weight in group (0 if not in group) */
+/* note; this call could be in mesh.c or deform.c, but OK... it's in armature.c too! (ton) */
+static float vert_weight(MDeformVert *dvert, int group)
+{
+ MDeformWeight *dw;
+ int i;
+
+ if(dvert) {
+ dw= dvert->dw;
+ for(i= dvert->totweight; i>0; i--, dw++) {
+ if(dw->def_nr == group) return dw->weight;
+ if(i==1) break; /*otherwise dw will point to somewhere it shouldn't*/
}
+ }
+ return 0.0;
+}
- curjit= nr/totface;
- curjit= curjit % jitlevel;
+/* Gets a faces average weight in a group, helper for below, face and weights are always set */
+static float face_weight(MFace *face, float *weights)
+{
+ float tweight;
+
+ tweight = weights[face->v1] + weights[face->v2] + weights[face->v3];
+
+ if(face->v4) {
+ tweight += weights[face->v4];
+ tweight /= 4.0;
+ }
+ else {
+ tweight /= 3.0;
+ }
- curface= nr % totface;
+ return tweight;
+}
+
+/* helper function for build_particle_system() */
+static void make_weight_tables(PartEff *paf, Mesh *me, int totpart, MVert *vertlist, int totvert, MFace *facelist, int totface, float **vweights, float **fweights)
+{
+ MFace *mface;
+ float *foweights=NULL, *voweights=NULL;
+ float totvweight=0.0f, totfweight=0.0f;
+ int a;
+
+ if((paf->flag & PAF_FACE)==0) totface= 0;
+
+ /* collect emitting vertices & faces if vert groups used */
+ if(paf->vertgroup && me->dvert) {
+
+ /* allocate weights array for all vertices, also for lookup of faces later on. note it's a malloc */
+ *vweights= voweights= MEM_mallocN( totvert*sizeof(float), "pafvoweights" );
+ totvweight= 0.0f;
+ for(a=0; a<totvert; a++) {
+ voweights[a]= vert_weight(me->dvert+a, paf->vertgroup-1);
+ totvweight+= voweights[a];
+ }
+
+ if(totface) {
+ /* allocate weights array for faces, note it's a malloc */
+ *fweights= foweights= MEM_mallocN(totface*sizeof(float), "paffoweights" );
+ for(a=0, mface=facelist; a<totface; a++, mface++) {
+ foweights[a] = face_weight(mface, voweights);
+ }
+ }
+ }
+
+ /* make weights for faces or for even area distribution */
+ if(totface && (paf->flag & PAF_EDISTR)) {
+ float maxfarea= 0.0f, curfarea;
- mface= mfacebase;
- mface+= curface;
-
- v1= (mvertbase+(mface->v1))->co;
- v2= (mvertbase+(mface->v2))->co;
- n1= (mvertbase+(mface->v1))->no;
- n2= (mvertbase+(mface->v2))->no;
- v3= (mvertbase+(mface->v3))->co;
- n3= (mvertbase+(mface->v3))->no;
- if(mface->v4==0) {
- v4= (mvertbase+(mface->v1))->co;
- n4= (mvertbase+(mface->v1))->no;
+ /* two cases for area distro, second case we already have group weights */
+ if(foweights==NULL) {
+ /* allocate weights array for faces, note it's a malloc */
+ *fweights= foweights= MEM_mallocN(totface*sizeof(float), "paffoweights" );
+
+ for(a=0, mface=facelist; a<totface; a++, mface++) {
+ if (mface->v4)
+ curfarea= AreaQ3Dfl(vertlist[mface->v1].co, vertlist[mface->v2].co, vertlist[mface->v3].co, vertlist[mface->v4].co);
+ else
+ curfarea= AreaT3Dfl(vertlist[mface->v1].co, vertlist[mface->v2].co, vertlist[mface->v3].co);
+ if(curfarea>maxfarea)
+ maxfarea = curfarea;
+ foweights[a]= curfarea;
+ }
}
else {
- v4= (mvertbase+(mface->v4))->co;
- n4= (mvertbase+(mface->v4))->no;
+ for(a=0, mface=facelist; a<totface; a++, mface++) {
+ if(foweights[a]!=0.0f) {
+ if (mface->v4)
+ curfarea= AreaQ3Dfl(vertlist[mface->v1].co, vertlist[mface->v2].co, vertlist[mface->v3].co, vertlist[mface->v4].co);
+ else
+ curfarea= AreaT3Dfl(vertlist[mface->v1].co, vertlist[mface->v2].co, vertlist[mface->v3].co);
+ if(curfarea>maxfarea)
+ maxfarea = curfarea;
+ foweights[a]*= curfarea;
+ }
+ }
+ }
+
+ /* normalize weights for max face area, calculate tot */
+ if(maxfarea!=0.0f) {
+ maxfarea= 1.0f/maxfarea;
+ for(a=0; a< totface; a++) {
+ if(foweights[a]!=0.0) {
+ foweights[a] *= maxfarea;
+ totfweight+= foweights[a];
+ }
+ }
+ }
+ }
+ else if(foweights) {
+ /* only add totfweight value */
+ for(a=0; a< totface; a++) {
+ if(foweights[a]!=0.0) {
+ totfweight+= foweights[a];
+ }
+ }
+ }
+
+ /* if weight arrays, we turn these arrays into the amount of particles */
+ if(totvert && voweights) {
+ float mult= (float)totpart/totvweight;
+
+ for(a=0; a< totvert; a++) {
+ if(voweights[a]!=0.0)
+ voweights[a] *= mult;
+ }
+ }
+
+ if(totface && foweights) {
+ float mult= (float)totpart/totfweight;
+
+ for(a=0; a< totface; a++) {
+ if(foweights[a]!=0.0)
+ foweights[a] *= mult;
}
+ }
+}
- u= jit[2*curjit];
- v= jit[2*curjit+1];
+/* for paf start to end, store all matrices for objects */
+typedef struct pMatrixCache {
+ float obmat[4][4];
+ float imat[3][3];
+} pMatrixCache;
- co[0]= (float)((1.0-u)*(1.0-v)*v1[0] + (1.0-u)*(v)*v2[0] + (u)*(v)*v3[0] + (u)*(1.0-v)*v4[0]);
- co[1]= (float)((1.0-u)*(1.0-v)*v1[1] + (1.0-u)*(v)*v2[1] + (u)*(v)*v3[1] + (u)*(1.0-v)*v4[1]);
- co[2]= (float)((1.0-u)*(1.0-v)*v1[2] + (1.0-u)*(v)*v2[2] + (u)*(v)*v3[2] + (u)*(1.0-v)*v4[2]);
+static pMatrixCache *cache_object_matrices(Object *ob, int start, int end)
+{
+ pMatrixCache *mcache, *mc;
+ Object *par;
+ float framelenold, sfrao;
+ int cfrao;
+
+ mcache= mc= MEM_mallocN( (end-start+1)*sizeof(pMatrixCache), "ob matrix cache");
+
+ framelenold= G.scene->r.framelen;
+ G.scene->r.framelen= 1.0f;
+ cfrao= G.scene->r.cfra;
+ sfrao= ob->sf;
+ ob->sf= 0.0f;
+
+ for(G.scene->r.cfra= start; G.scene->r.cfra<=end; G.scene->r.cfra++, mc++) {
- no[0]= (short)((1.0-u)*(1.0-v)*n1[0] + (1.0-u)*(v)*n2[0] + (u)*(v)*n3[0] + (u)*(1.0-v)*n4[0]);
- no[1]= (short)((1.0-u)*(1.0-v)*n1[1] + (1.0-u)*(v)*n2[1] + (u)*(v)*n3[1] + (u)*(1.0-v)*n4[1]);
- no[2]= (short)((1.0-u)*(1.0-v)*n1[2] + (1.0-u)*(v)*n2[2] + (u)*(v)*n3[2] + (u)*(1.0-v)*n4[2]);
+ par= ob;
+ while(par) {
+ par->ctime= -1234567.0; /* hrms? */
+ do_ob_key(par);
+ if(par->type==OB_ARMATURE) {
+ do_all_pose_actions(par); // only does this object actions
+ where_is_pose(par);
+ }
+ par= par->parent;
+ }
+
+ where_is_object(ob);
+ Mat4CpyMat4(mc->obmat, ob->obmat);
+ Mat4Invert(ob->imat, ob->obmat);
+ Mat3CpyMat4(mc->imat, ob->imat);
+ Mat3Transp(mc->imat);
+ }
+
+
+ /* restore */
+ G.scene->r.cfra= cfrao;
+ G.scene->r.framelen= framelenold;
+ ob->sf= sfrao;
+
+ /* restore hierarchy */
+ par= ob;
+ while(par) {
+ /* do not do ob->ipo: keep insertkey */
+ par->ctime= -1234567.0; /* hrms? */
+ do_ob_key(par);
+ if(par->type==OB_ARMATURE) {
+ do_all_pose_actions(par); // only does this object actions
+ where_is_pose(par);
+ }
+ par= par->parent;
}
+
+ where_is_object(ob);
+
+ return mcache;
}
-
+/* main particle building function
+ one day particles should become dynamic (realtime) with the current method as a 'bake' (ton) */
void build_particle_system(Object *ob)
{
RNG *rng;
- Base *base;
- Object *par;
PartEff *paf;
Particle *pa;
Mesh *me;
- MTex *mtexmove=0;
+ Base *base;
+ MTex *mtexmove=0, *mtextime=0;
Material *ma;
DispListMesh *dlm;
- int dmNeedsFree;
+ MFace *facelist= NULL;
+ MVert *vertlist= NULL;
DerivedMesh *dm;
- float framelenont, ftime, dtime, force[3], imat[3][3], vec[3];
- float fac, prevobmat[4][4], sfraont, co[3];
- int deform=0, a, cur, cfraont, cfralast, totpart, totvert;
+ pMatrixCache *mcache=NULL, *mcnow, *mcprev;
+ double startseconds= PIL_check_seconds_timer();
+ float ftime, dtime, force[3], vec[3];
+ float fac, co[3];
+ float *voweights= NULL, *foweights= NULL, maxw=1.0f;
+ int deform=0, a, totpart, paf_sta, paf_end;
+ int dmNeedsFree, waitcursor_set= 0, totvert, totface, curface, curvert;
short no[3];
-
+
+ /* return conditions */
if(ob->type!=OB_MESH) return;
me= ob->data;
- if(me->totvert==0) return;
-
- ma= give_current_material(ob, 1);
- if(ma) {
- mtexmove= ma->mtex[7];
- }
paf= give_parteff(ob);
if(paf==NULL) return;
+ if(paf->keys) MEM_freeN(paf->keys); /* free as early as possible, for returns */
+ paf->keys= NULL;
+
+ if(paf->end < paf->sta) return;
+
+ if( (paf->flag & PAF_OFACE) && (paf->flag & PAF_FACE)==0) return;
+
+ if(me->totvert==0) return;
+
+ /* this call returns NULL during editmode, just ignore it and
+ * particles should be recalc'd on exit. */
+ dm = mesh_get_derived_deform(ob, &dmNeedsFree);
+ if (dm==NULL)
+ return;
+
+ /* No returns after this line! */
+
+ /* material */
+ ma= give_current_material(ob, paf->omat);
+ if(ma) {
+ if(paf->speedtex)
+ mtexmove= ma->mtex[paf->speedtex-1];
+ mtextime= ma->mtex[paf->timetex-1];
+ }
- waitcursor(1);
-
- disable_speed_curve(1);
+ disable_speed_curve(1); /* check this... */
- /* generate all particles */
- if(paf->keys) MEM_freeN(paf->keys);
- paf->keys= NULL;
+ /* initialize particles */
new_particle(paf);
/* reset deflector cache, sumohandle is free, but its still sorta abuse... (ton) */
- for(base= G.scene->base.first; base; base= base->next) {
+ for(base= G.scene->base.first; base; base= base->next)
base->object->sumohandle= NULL;
- }
-
- cfraont= G.scene->r.cfra;
- cfralast= -1000;
- framelenont= G.scene->r.framelen;
- G.scene->r.framelen= 1.0;
- sfraont= ob->sf;
- ob->sf= 0.0;
+ /* all object positions from start to end */
+ paf_sta= (int)floor(paf->sta);
+ paf_end= (int)ceil(paf->end);
+ if((paf->flag & PAF_STATIC)==0)
+ mcache= cache_object_matrices(ob, paf_sta, paf_end);
+
/* mult generations? */
- totpart= paf->totpart;
+ totpart= (R.flag & R_RENDERING)?paf->totpart:(paf->disp*paf->totpart)/100;
for(a=0; a<PAF_MAXMULT; a++) {
if(paf->mult[a]!=0.0) {
- /* interessant formula! this way after 'x' generations the total is paf->totpart */
+ /* interesting formula! this way after 'x' generations the total is paf->totpart */
totpart= (int)(totpart / (1.0+paf->mult[a]*paf->child[a]));
}
else break;
}
- if (paf->flag & PAF_STATIC) {
- ftime = cfraont;
- dtime = 0;
- } else {
- ftime= paf->sta;
- dtime= (paf->end - paf->sta)/totpart;
- }
-
- /* this call returns NULL during editmode, just ignore it and
- * particles should be recalc'd on exit.
- */
- dm = mesh_get_derived_final(ob, &dmNeedsFree);
- if (!dm) {
- waitcursor(0);
- return;
- }
-
- /* WARNING!!!! pushdata and popdata actually copy object memory!!!!
- * Changes between these calls will be lost!!!
- */
-
- /* remember full hierarchy */
- par= ob;
- while(par) {
- pushdata(par, sizeof(Object));
- par= par->parent;
- }
-
- /* for static particles, calculate system on current frame */
+ /* for static particles, calculate system on current frame (? ton) */
if(ma) do_mat_ipo(ma);
-
- /* set it all at first frame */
- G.scene->r.cfra= cfralast= (int)floor(ftime);
- par= ob;
- while(par) {
- /* do_ob_ipo(par); */
- do_ob_key(par);
- par= par->parent;
- }
- /* matrix stuff for static too */
+ /* matrix invert for static too */
Mat4Invert(ob->imat, ob->obmat);
- if((paf->flag & PAF_STATIC)==0) {
- if(ma) do_mat_ipo(ma); // nor for static
-
- where_is_object(ob);
- Mat4CpyMat4(prevobmat, ob->obmat);
- Mat3CpyMat4(imat, ob->imat);
- }
- else {
- Mat4One(prevobmat);
- Mat3One(imat);
- }
-
+ /* new random generator */
rng = rng_new(paf->seed);
/* otherwise it goes way too fast */
@@ -1236,142 +1612,223 @@ void build_particle_system(Object *ob)
if(deform) init_latt_deform(ob->parent, 0);
}
- /* init */
-
+ /* init geometry */
dlm = dm->convertToDispListMesh(dm, 1);
- totvert = dlm->totvert;
-
- give_mesh_mvert(me, dlm, totpart, co, no, paf->seed);
- if(G.f & G_DEBUG) {
- printf("\n");
- printf("Calculating particles......... \n");
+ /* subsurfs don't have vertexgroups, so we need to use me->mvert in that case */
+ if(paf->vertgroup && me->dvert && (dlm->totvert != me->totvert)) {
+ vertlist= me->mvert;
+ facelist= me->mface;
+ totvert= me->totvert;
+ totface= me->totface;
+ }
+ else {
+ vertlist= dlm->mvert;
+ facelist= dlm->mface;
+ totvert= dlm->totvert;
+ totface= dlm->totface;
+ }
+ /* if vertexweights or even distribution, it makes weight tables, also checks where it emits from */
+ make_weight_tables(paf, me, totpart, vertlist, totvert, facelist, totface, &voweights, &foweights);
+
+ /* now define where to emit from, if there are face weights we skip vertices */
+ if(paf->flag & PAF_OFACE) totvert= 0;
+ if((paf->flag & PAF_FACE)==0) totface= 0;
+ if(foweights) totvert= 0;
+
+ /* initialize give_mesh_particle_coord */
+ if(totface)
+ give_mesh_particle_coord(paf, vertlist, facelist, totpart, totface, NULL, NULL);
+
+ /* correction for face timing when using weighted average */
+ if(totface && foweights) {
+ maxw= (paf->end-paf->sta)/foweights[0];
+ }
+ else if(totvert && voweights) {
+ maxw= (paf->end-paf->sta)/voweights[0];
+ }
+
+ /* for loop below */
+ if (paf->flag & PAF_STATIC) {
+ ftime = G.scene->r.cfra;
+ dtime= 0.0f;
+ } else {
+ ftime= paf->sta;
+ dtime= (paf->end - paf->sta)/(float)totpart;
}
+
+ curface= curvert= 0;
for(a=0; a<totpart; a++, ftime+=dtime) {
+ /* we set waitcursor only when a half second expired, particles now are realtime updated */
+ if(waitcursor_set==0 && (a % 256)==255) {
+ double seconds= PIL_check_seconds_timer();
+ if(seconds - startseconds > 0.5) {
+ waitcursor(1);
+ waitcursor_set= 1;
+ }
+ }
+
pa= new_particle(paf);
pa->time= ftime;
-
- if(G.f & G_DEBUG) {
- int b, c;
+
+ /* get coordinates from faces, only when vertices set to zero */
+ if(totvert==0 && totface) {
+ int curjit;
- c = totpart/100;
- if (c==0){
- c = 1;
+ /* use weight table, we have to do faces in order to be able to use jitter table... */
+ if(foweights) {
+
+ if(foweights[curface] < 1.0f) {
+ float remainder= 0.0f;
+
+ while(remainder + foweights[curface] < 1.0f && curface<totface-1) {
+ remainder += foweights[curface];
+ curface++;
+ }
+ foweights[curface] += remainder;
+ maxw= (paf->end-paf->sta)/foweights[curface];
+ }
+
+ if(foweights[curface]==0.0f)
+ break; /* WARN skips here out of particle generating */
+ else {
+ if(foweights[curface] > 1.0f)
+ foweights[curface] -= 1.0f;
+
+ curjit= (int) foweights[curface];
+ give_mesh_particle_coord(paf, vertlist, facelist+curface, a, curjit, co, no);
+
+ /* time correction to make particles appear evenly, maxw does interframe (0-1) */
+ pa->time= paf->sta + maxw*foweights[curface];
+ }
}
-
- b=(a%c);
- if (b==0) {
- printf("\r Particle: %d / %d ", a, totpart);
- fflush(stdout);
+ else {
+ curface= a % totface;
+ curjit= a/totface;
+ give_mesh_particle_coord(paf, vertlist, facelist+curface, a, curjit, co, no);
}
}
- /* set ob at correct time */
-
- if((paf->flag & PAF_STATIC)==0) {
-
- cur= (int)floor(ftime) + 1 ; /* + 1 has a reason: (obmat/prevobmat) otherwise comet-tails start too late */
- if(cfralast != cur) {
- G.scene->r.cfra= cfralast= cur;
-
- /* added later: blur? */
- bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0);
-
- par= ob;
- while(par) {
- /* do_ob_ipo(par); */
- par->ctime= -1234567.0;
- do_ob_key(par);
- if(par->type==OB_ARMATURE) {
- do_all_pose_actions(par); // only does this object actions
- where_is_pose(par);
+ /* get coordinates from vertices */
+ if(totvert) {
+ /* use weight table */
+ if(voweights) {
+
+ if(voweights[curvert] < 1.0f) {
+ float remainder= 0.0f;
+
+ while(remainder + voweights[curvert] < 1.0f && curvert<totvert-1) {
+ remainder += voweights[curvert];
+ curvert++;
}
- par= par->parent;
+ voweights[curvert] += remainder;
+ maxw= (paf->end-paf->sta)/voweights[curvert];
+ }
+
+ if(voweights[curvert]==0.0f)
+ break; /* WARN skips here out of particle generating */
+ else {
+ if(voweights[curvert] > 1.0f)
+ voweights[curvert] -= 1.0f;
+
+ /* time correction to make particles appear evenly */
+ pa->time= paf->sta + maxw*voweights[curvert];
}
- if(ma) do_mat_ipo(ma);
- Mat4CpyMat4(prevobmat, ob->obmat);
- where_is_object(ob);
- Mat4Invert(ob->imat, ob->obmat);
- Mat3CpyMat4(imat, ob->imat);
}
- }
- /* get coordinates */
- if(paf->flag & PAF_FACE) give_mesh_mvert(me, dlm, a, co, no, paf->seed);
- else {
- if (totvert) {
- VECCOPY(co, dlm->mvert[a%totvert].co);
- VECCOPY(no, dlm->mvert[a%totvert].no);
- } else {
- co[0] = co[1] = co[2] = 0.0f;
- no[0] = no[1] = no[2] = 0;
+ else {
+ curvert= a % totvert;
+ if(a >= totvert && totface)
+ totvert= 0;
}
+
+ VECCOPY(co, vertlist[curvert].co);
+ VECCOPY(no, vertlist[curvert].no);
}
VECCOPY(pa->co, co);
- if(paf->flag & PAF_STATIC);
- else {
- Mat4MulVecfl(ob->obmat, pa->co);
+ /* dynamic options */
+ if((paf->flag & PAF_STATIC)==0) {
+ int cur;
+
+ /* particle retiming with texture */
+ if(mtextime && (paf->flag2 & PAF_TEXTIME)) {
+ float tin, tr, tg, tb, ta, orco[3];
+
+ /* calculate normalized orco */
+ orco[0] = (co[0]-me->loc[0])/me->size[0];
+ orco[1] = (co[1]-me->loc[1])/me->size[1];
+ orco[2] = (co[2]-me->loc[2])/me->size[2];
+ externtex(mtextime, orco, &tin, &tr, &tg, &tb, &ta);
+
+ if(paf->flag2neg & PAF_TEXTIME)
+ pa->time = paf->sta + (paf->end - paf->sta)*tin;
+ else
+ pa->time = paf->sta + (paf->end - paf->sta)*(1.0f-tin);
+ }
+
+ /* set ob at correct time, we use cached matrices */
+ cur= (int)floor(pa->time) + 1 ; /* + 1 has a reason: (obmat/prevobmat) otherwise comet-tails start too late */
+
+ if(cur <= paf_end) mcnow= mcache + cur - paf_sta;
+ else mcnow= mcache + paf_end - paf_sta + 1;
+
+ if(cur > paf_sta) mcprev= mcnow-1;
+ else mcprev= mcache;
+
+ /* move to global space */
+ Mat4MulVecfl(mcnow->obmat, pa->co);
VECCOPY(vec, co);
- Mat4MulVecfl(prevobmat, vec);
+ Mat4MulVecfl(mcprev->obmat, vec);
/* first start speed: object */
VECSUB(pa->no, pa->co, vec);
+
VecMulf(pa->no, paf->obfac);
/* calculate the correct inter-frame */
- fac= (ftime- (float)floor(ftime));
+ fac= (pa->time- (float)floor(pa->time));
pa->co[0]= fac*pa->co[0] + (1.0f-fac)*vec[0];
pa->co[1]= fac*pa->co[1] + (1.0f-fac)*vec[1];
pa->co[2]= fac*pa->co[2] + (1.0f-fac)*vec[2];
- }
- /* start speed: normal */
- if(paf->normfac!=0.0) {
- /* transpose ! */
- vec[0]= imat[0][0]*no[0] + imat[0][1]*no[1] + imat[0][2]*no[2];
- vec[1]= imat[1][0]*no[0] + imat[1][1]*no[1] + imat[1][2]*no[2];
- vec[2]= imat[2][0]*no[0] + imat[2][1]*no[1] + imat[2][2]*no[2];
-
- Normalise(vec);
- VecMulf(vec, paf->normfac);
- VECADD(pa->no, pa->no, vec);
+ /* start speed: normal */
+ if(paf->normfac!=0.0) {
+ /* imat is transpose ! */
+ VECCOPY(vec, no);
+ Mat3MulVecfl(mcnow->imat, vec);
+
+ Normalise(vec);
+ VecMulf(vec, paf->normfac);
+ VECADD(pa->no, pa->no, vec);
+ }
+ }
+ else {
+ if(paf->normfac!=0.0) {
+ VECCOPY(pa->no, no);
+ Normalise(pa->no);
+ VecMulf(pa->no, paf->normfac);
+ }
}
+
pa->lifetime= paf->lifetime;
if(paf->randlife!=0.0) {
pa->lifetime*= 1.0f + paf->randlife*(rng_getFloat(rng) - 0.5f);
}
- pa->mat_nr= 1;
+ pa->mat_nr= paf->omat;
- make_particle_keys(rng, ob, 0, a, paf, pa, force, deform, mtexmove, ob->lay, cfraont);
+ make_particle_keys(rng, ob, 0, a, paf, pa, force, deform, mtexmove, ob->lay);
}
- if(G.f & G_DEBUG) {
- printf("\r Particle: %d / %d \n", totpart, totpart);
- fflush(stdout);
- }
- if(deform) end_latt_deform();
-
- /* restore */
- G.scene->r.cfra= cfraont;
- G.scene->r.framelen= framelenont;
- give_mesh_mvert(0, 0, 0, 0, 0,paf->seed);
-
- /* put hierarchy back */
- par= ob;
- while(par) {
- popfirst(par);
- /* do not do ob->ipo: keep insertkey */
- do_ob_key(par);
-
- if(par->type==OB_ARMATURE) {
- do_all_pose_actions(par); // only does this object actions
- where_is_pose(par);
- }
- par= par->parent;
- }
+ /* free stuff */
+ give_mesh_particle_coord(NULL, NULL, NULL, 0, 0, NULL, NULL);
+ if(voweights) MEM_freeN(voweights);
+ if(foweights) MEM_freeN(foweights);
+ if(mcache) MEM_freeN(mcache);
+ if(deform) end_latt_deform();
+
/* reset deflector cache */
for(base= G.scene->base.first; base; base= base->next) {
if(base->object->sumohandle) {
@@ -1380,10 +1837,6 @@ void build_particle_system(Object *ob)
}
}
- /* restore: AFTER popfirst */
- ob->sf= sfraont;
-
- if(ma) do_mat_ipo(ma); // set back on current time
disable_speed_curve(0);
waitcursor(0);
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 10395326357..38732377e29 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -346,11 +346,11 @@ int sb_detect_collision(float opco[3], float facenormal[3], float *damp,
{
Base *base;
Object *ob;
- int a, deflected=0;
float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3], dv2[3],
facedist,n_mag,t,force_mag_norm,
innerfacethickness = -0.5f, outerfacethickness = 0.2f,
ee = 5.0f, ff = 0.1f, fa;
+ int a, deflected=0;
base= G.scene->base.first;
while (base) {
@@ -495,29 +495,27 @@ static int sb_deflect_face(Object *ob,float *actpos, float *futurepos,float *col
{
int deflected;
float s_actpos[3], s_futurepos[3];
+
VECCOPY(s_actpos,actpos);
if(futurepos)
- VECCOPY(s_futurepos,futurepos);
+ VECCOPY(s_futurepos,futurepos);
+
deflected= sb_detect_collision(s_actpos, facenormal, cf, force , ob->lay, ob);
return(deflected);
-
}
-#define USES_FIELD 1
-#define USES_DEFLECT 2
static int is_there_deflection(unsigned int layer)
{
Base *base;
- int retval= 0;
for(base = G.scene->base.first; base; base= base->next) {
if( (base->lay & layer) && base->object->pd) {
- if(base->object->pd->forcefield) retval |= USES_FIELD;
- if(base->object->pd->deflect) retval |= USES_DEFLECT;
+ if(base->object->pd->deflect)
+ return 1;
}
}
- return retval;
+ return 0;
}
static void softbody_calc_forces(Object *ob, float forcetime)
@@ -529,10 +527,10 @@ static void softbody_calc_forces(Object *ob, float forcetime)
BodyPoint *bp;
BodyPoint *bproot;
BodySpring *bs;
- float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3],
- fieldfactor = 1000.0f,
- windfactor = 250.0f;
- int a, b, do_effector;
+ ListBase *do_effector;
+ float iks, ks, kd, gravity, actspringlen, forcefactor, sd[3];
+ float fieldfactor = 1000.0f, windfactor = 250.0f;
+ int a, b, do_deflector;
/* clear forces */
for(a=sb->totpoint, bp= sb->bpoint; a>0; a--, bp++) {
@@ -540,8 +538,11 @@ static void softbody_calc_forces(Object *ob, float forcetime)
}
gravity = sb->grav * sb_grav_force_scale(ob);
+
/* check! */
- do_effector= is_there_deflection(ob->lay);
+ do_deflector= is_there_deflection(ob->lay);
+ do_effector= pdInitEffectors(ob->lay);
+
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
bproot= sb->bpoint; /* need this for proper spring addressing */
@@ -581,14 +582,15 @@ static void softbody_calc_forces(Object *ob, float forcetime)
bp->force[2]-= gravity*sb->nodemass; /* individual mass of node here */
/* particle field & vortex */
- if(do_effector & USES_FIELD) {
+ if(do_effector) {
float force[3]= {0.0f, 0.0f, 0.0f};
float speed[3]= {0.0f, 0.0f, 0.0f};
float eval_sb_fric_force_scale = sb_fric_force_scale(ob); // just for calling functio once
- pdDoEffector(bp->pos, force, speed, (float)G.scene->r.cfra, ob->lay,PE_WIND_AS_SPEED);
- // note: now we have wind as motion of media, so we can do anisotropic stuff here,
- // if we had vertex normals here(BM)
+ pdDoEffectors(do_effector, bp->pos, force, speed, (float)G.scene->r.cfra, 0.0f, PE_WIND_AS_SPEED);
+
+ /* note: now we have wind as motion of media, so we can do anisotropic stuff here, */
+ /* if we had vertex normals here(BM) */
/* apply forcefield*/
VecMulf(force,fieldfactor* eval_sb_fric_force_scale);
VECADD(bp->force, bp->force, force);
@@ -616,7 +618,7 @@ static void softbody_calc_forces(Object *ob, float forcetime)
yes, constraints and collision stuff should go here too (read baraff papers on that!)
*/
/* moving collision targets */
- if(do_effector & USES_DEFLECT) {
+ if(do_deflector) {
float defforce[3] = {0.0f,0.0f,0.0f}, collisionpos[3],facenormal[3], cf = 1.0f;
kd = 1.0f;
@@ -689,6 +691,11 @@ static void softbody_calc_forces(Object *ob, float forcetime)
}/*any edges*/
}/*omit on snap */
}/*loop all bp's*/
+
+ /* cleanup */
+ if(do_effector)
+ pdEndEffectors(do_effector);
+
}
static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *err)
@@ -701,11 +708,9 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
float dx[3],dv[3];
float timeovermass;
float maxerr = 0.0;
- int a, do_effector;
+ int a;
forcetime *= sb_time_scale(ob);
- /* check! */
- do_effector= is_there_deflection(ob->lay);
// claim a minimum mass for vertex
if (sb->nodemass > 0.09999f) timeovermass = forcetime/sb->nodemass;
@@ -771,6 +776,7 @@ static void softbody_apply_forces(Object *ob, float forcetime, int mode, float *
else { VECADD(bp->pos, bp->pos, dx);}
}//snap
} //for
+
if (err){ /* so step size will be controlled by biggest difference in slope */
*err = maxerr;
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index ab7352e4a5f..f84f72da494 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4909,6 +4909,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
for(ob=main->object.first; ob; ob= ob->id.next) {
ModifierData *md;
+ PartEff *paf;
for (md=ob->modifiers.first; md; md=md->next) {
if (md->type==eModifierType_Subsurf) {
@@ -4959,6 +4960,16 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
+
+ paf = give_parteff(ob);
+ if (paf) {
+ if(paf->disp == 0)
+ paf->disp = 100;
+ if(paf->speedtex == 0)
+ paf->speedtex = 8;
+ if(paf->omat == 0)
+ paf->omat = 1;
+ }
}
for(arm=main->armature.first; arm; arm= arm->id.next) {
diff --git a/source/blender/include/BIF_butspace.h b/source/blender/include/BIF_butspace.h
index 4dda9f6fb43..f5ae79fcd80 100644
--- a/source/blender/include/BIF_butspace.h
+++ b/source/blender/include/BIF_butspace.h
@@ -44,8 +44,6 @@ extern void redraw_test_buttons(struct Object *new);
/* buttons_editing.c */
extern void validate_editbonebutton_cb(void *bonev, void *namev);
-extern void autocomplete_bone(char *str, void *arg_v);
-
/* buts->mainb old */
#define BUTS_VIEW 0
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index e497fe48c77..e6e291fb285 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -65,6 +65,8 @@ extern void physics_panels(void);
extern void do_object_panels(unsigned short event);
extern void do_constraintbuts(unsigned short event);
extern void object_panel_constraint(char *context);
+extern void autocomplete_bone(char *str, void *arg_v);
+extern void autocomplete_vgroup(char *str, void *arg_v);
/* effects */
extern void effects_panels(void);
@@ -625,6 +627,7 @@ enum {
#define B_EFFECT_DEP 3413
#define B_FIELD_DEP 3414
#define B_FIELD_CHANGE 3415
+#define B_PAF_SET_VG 3416
#define B_MODIFIER_BUTS 3600
diff --git a/source/blender/makesdna/DNA_effect_types.h b/source/blender/makesdna/DNA_effect_types.h
index 299756edfe1..084ad9ac82f 100644
--- a/source/blender/makesdna/DNA_effect_types.h
+++ b/source/blender/makesdna/DNA_effect_types.h
@@ -38,11 +38,27 @@
#define PAF_MAXMULT 4
- /* paf->flag (keep bit 0 free for compatibility) */
+/* paf->flag (keep bit 0 free for compatibility) */
#define PAF_BSPLINE 2
#define PAF_STATIC 4
#define PAF_FACE 8
#define PAF_ANIMATED 16
+ /* show particles before they're emitted*/
+#define PAF_UNBORN 32
+ /* emit only from faces*/
+#define PAF_OFACE 64
+ /* show emitter (don't hide actual mesh)*/
+#define PAF_SHOWE 128
+ /* true random emit from faces (not just ordered jitter)*/
+#define PAF_TRAND 256
+ /* even distribution in face emission based on face areas*/
+#define PAF_EDISTR 512
+ /*show particles after they've died*/
+#define PAF_DIED 2048
+
+
+/*paf->flag2 for pos/neg paf->flag2neg*/
+#define PAF_TEXTIME 1 /*texture timing*/
/* eff->type */
#define EFF_BUILD 0
@@ -91,7 +107,7 @@ typedef struct Particle {
typedef struct PartEff {
struct PartEff *next, *prev;
- short type, flag, buttype, stype;
+ short type, flag, buttype, stype, vertgroup, userjit;
float sta, end, lifetime;
int totpart, totkey, seed;
@@ -105,8 +121,10 @@ typedef struct PartEff {
float mult[4], life[4];
short child[4], mat[4];
short texmap, curmult;
- short staticstep, pad;
+ short staticstep, omat, timetex, speedtex, flag2, flag2neg;
+ short disp, pad;
+ char vgroupname[32];
Particle *keys;
} PartEff;
diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h
index 3396c59a53a..60a60cf22f3 100644
--- a/source/blender/makesdna/DNA_object_force.h
+++ b/source/blender/makesdna/DNA_object_force.h
@@ -104,6 +104,7 @@ typedef struct SoftBody {
#define PFIELD_VORTEX 2
#define PFIELD_MAGNET 3
#define PFIELD_WIND 4
+#define PFIELD_GUIDE 5
/* pd->flag: various settings */
#define PFIELD_USEMAX 1
diff --git a/source/blender/renderconverter/intern/convertBlenderScene.c b/source/blender/renderconverter/intern/convertBlenderScene.c
index ddc97c1c0cb..37d256e261a 100644
--- a/source/blender/renderconverter/intern/convertBlenderScene.c
+++ b/source/blender/renderconverter/intern/convertBlenderScene.c
@@ -816,7 +816,7 @@ static void render_particle_system(Object *ob, PartEff *paf)
int a, mat_nr=1, seed;
pa= paf->keys;
- if(pa==NULL) {
+ if(pa==NULL || paf->disp!=100) {
build_particle_system(ob);
pa= paf->keys;
if(pa==NULL) return;
@@ -839,65 +839,74 @@ static void render_particle_system(Object *ob, PartEff *paf)
for(a=0; a<paf->totpart; a++, pa+=paf->totkey) {
- if(ctime > pa->time) {
- if(ctime < pa->time+pa->lifetime) {
-
- /* watch it: also calculate the normal of a particle */
- if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
- where_is_particle(paf, pa, ctime, vec);
- MTC_Mat4MulVecfl(R.viewmat, vec);
- where_is_particle(paf, pa, ctime+1.0, vec1);
- MTC_Mat4MulVecfl(R.viewmat, vec1);
- }
- else {
- where_is_particle(paf, pa, ctime, vec);
- MTC_Mat4MulVecfl(R.viewmat, vec);
- }
+ if((paf->flag & PAF_UNBORN)==0) {
+ if(ctime < pa->time)
+ {
+ seed++;
+ continue;
+ }
+ }
+ if((paf->flag & PAF_DIED)==0) {
+ if(ctime > pa->time+pa->lifetime)
+ {
+ seed++;
+ continue;
+ }
+ }
+ /* watch it: also calculate the normal of a particle */
+ if(paf->stype==PAF_VECT || ma->mode & MA_HALO_SHADE) {
+ where_is_particle(paf, pa, ctime, vec);
+ MTC_Mat4MulVecfl(R.viewmat, vec);
+ where_is_particle(paf, pa, ctime+1.0, vec1);
+ MTC_Mat4MulVecfl(R.viewmat, vec1);
+ }
+ else {
+ where_is_particle(paf, pa, ctime, vec);
+ MTC_Mat4MulVecfl(R.viewmat, vec);
+ }
- if(pa->mat_nr != mat_nr) {
- mat_nr= pa->mat_nr;
- ma= give_render_material(ob, mat_nr);
- }
+ if(pa->mat_nr != mat_nr) {
+ mat_nr= pa->mat_nr;
+ ma= give_render_material(ob, mat_nr);
+ }
- if(ma->ipo) {
- /* correction for lifetime */
- ptime= 100.0*(ctime-pa->time)/pa->lifetime;
- calc_ipo(ma->ipo, ptime);
- execute_ipo((ID *)ma, ma->ipo);
- }
+ if(ma->ipo) {
+ /* correction for lifetime */
+ ptime= 100.0*(ctime-pa->time)/pa->lifetime;
+ calc_ipo(ma->ipo, ptime);
+ execute_ipo((ID *)ma, ma->ipo);
+ }
- hasize= ma->hasize;
+ hasize= ma->hasize;
- if(ma->mode & MA_HALOPUNO) {
- xn= pa->no[0];
- yn= pa->no[1];
- zn= pa->no[2];
+ if(ma->mode & MA_HALOPUNO) {
+ xn= pa->no[0];
+ yn= pa->no[1];
+ zn= pa->no[2];
- /* transpose ! */
- nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
- nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
- nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
- Normalise(nor);
+ /* transpose ! */
+ nor[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn;
+ nor[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn;
+ nor[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn;
+ Normalise(nor);
- VECCOPY(view, vec);
- Normalise(view);
+ VECCOPY(view, vec);
+ Normalise(view);
- zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
- if(zn>=0.0) hasize= 0.0;
- else hasize*= zn*zn*zn*zn;
- }
+ zn= nor[0]*view[0]+nor[1]*view[1]+nor[2]*view[2];
+ if(zn>=0.0) hasize= 0.0;
+ else hasize*= zn*zn*zn*zn;
+ }
- if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
- else {
- har= RE_inithalo(ma, vec, NULL, pa->co, hasize, 0.0, seed);
- if(har && ma->mode & MA_HALO_SHADE) {
- VecSubf(har->no, vec, vec1);
- Normalise(har->no);
- }
- }
- if(har) har->lay= ob->lay;
+ if(paf->stype==PAF_VECT) har= RE_inithalo(ma, vec, vec1, pa->co, hasize, paf->vectsize, seed);
+ else {
+ har= RE_inithalo(ma, vec, NULL, pa->co, hasize, 0.0, seed);
+ if(har && ma->mode & MA_HALO_SHADE) {
+ VecSubf(har->no, vec, vec1);
+ Normalise(har->no);
}
}
+ if(har) har->lay= ob->lay;
seed++;
}
@@ -907,6 +916,10 @@ static void render_particle_system(Object *ob, PartEff *paf)
if(ma) do_mat_ipo(ma);
}
+ if(paf->disp!=100) {
+ MEM_freeN(paf->keys);
+ paf->keys= NULL;
+ }
}
@@ -1005,7 +1018,7 @@ static void render_static_particle_system(Object *ob, PartEff *paf)
int a, mat_nr=1, seed;
pa= paf->keys;
- if(pa==NULL || (paf->flag & PAF_ANIMATED)) {
+ if(pa==NULL || (paf->flag & PAF_ANIMATED) || paf->disp!=100) {
build_particle_system(ob);
pa= paf->keys;
if(pa==NULL) return;
@@ -1139,6 +1152,11 @@ static void render_static_particle_system(Object *ob, PartEff *paf)
seed++;
if(orco) orco+=3;
}
+
+ if(paf->disp!=100) {
+ MEM_freeN(paf->keys);
+ paf->keys= NULL;
+ }
}
@@ -1349,7 +1367,7 @@ static void init_render_mesh(Object *ob)
/* warning; build_particle_system does modifier calls itself */
if(paf->flag & PAF_STATIC) render_static_particle_system(ob, paf);
else render_particle_system(ob, paf);
- return;
+ if((paf->flag & PAF_SHOWE)==0) return;
}
MTC_Mat4MulMat4(mat, ob->obmat, R.viewmat);
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index 46c6b1b7959..77570ed688f 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -1271,11 +1271,13 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
} else if (md->type==eModifierType_Lattice) {
LatticeModifierData *lmd = (LatticeModifierData*) md;
uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
- uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+ but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)lmd->object);
} else if (md->type==eModifierType_Curve) {
CurveModifierData *cmd = (CurveModifierData*) md;
uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
- uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+ but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)cmd->object);
} else if (md->type==eModifierType_Build) {
BuildModifierData *bmd = (BuildModifierData*) md;
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Start:", lx, (cy-=19), buttonWidth,19, &bmd->start, 1.0, MAXFRAMEF, 100, 0, "Specify the start frame of the effect");
@@ -1291,7 +1293,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefButBitS(block, TOG, MOD_MIR_CLIPPING, B_MODIFIER_RECALC, "Do Clipping", lx+60, cy, buttonWidth-60,19, &mmd->flag, 1, 2, 0, 0, "Prevents during Transform vertices to go through Mirror");
} else if (md->type==eModifierType_Decimate) {
DecimateModifierData *dmd = (DecimateModifierData*) md;
- uiDefButF(block, NUM, B_MODIFIER_RECALC, "Percent:", lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 0, 0, "Defines the percentage of triangles to reduce to");
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Percent:", lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to");
sprintf(str, "Face Count: %d", dmd->faceCount);
uiDefBut(block, LABEL, 1, str, lx, (cy-=19), 160,19, NULL, 0.0, 0.0, 0, 0, "Displays the current number of faces in the decimated mesh");
} else if (md->type==eModifierType_Wave) {
@@ -1323,8 +1325,10 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Falloff: ", lx, (cy-=19), buttonWidth,19, &hmd->falloff, 0.0, 100.0, 100, 0, "If not zero, the distance from hook where influence ends");
uiDefButF(block, NUMSLI, B_MODIFIER_RECALC, "Force: ", lx, (cy-=19), buttonWidth,19, &hmd->force, 0.0, 1.0, 100, 0, "Set relative force of hook");
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &hmd->object, "Parent Object for hook, also recalculates and clears offset");
- if(hmd->indexar==NULL)
- uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+ if(hmd->indexar==NULL) {
+ but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)hmd->object);
+ }
uiBlockBeginAlign(block);
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reset", lx, (cy-=19), 80,19, NULL, 0.0, 0.0, 0, 0, "Recalculate and clear offset (transform) of hook");
uiButSetFunc(but, modifiers_clearHookOffset, ob, md);
@@ -3410,6 +3414,7 @@ static void editing_panel_links(Object *ob)
defGroup = BLI_findlink(&ob->defbase, ob->actdef-1);
but= uiDefBut(block, TEX, REDRAWBUTSEDIT,"", 161,132,140-18,21, defGroup->name, 0, 31, 0, 0, "Displays current vertex group name. Click to change. (Match bone name for deformation.)");
uiButSetFunc(but, verify_vertexgroup_name_func, defGroup, NULL);
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
uiDefButF(block, NUM, REDRAWVIEW3D, "Weight:", 143, 111, 140, 21, &editbutvweight, 0, 1, 10, 0, "Sets the current vertex group's bone deformation strength");
}
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 43897b2f0bd..c12fd3165df 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -114,6 +114,7 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
+#include "BKE_deform.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
@@ -130,9 +131,11 @@
#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BKE_DerivedMesh.h"
+
#include "LBM_fluidsim.h"
#include "BIF_editconstraint.h"
+#include "BIF_editdeform.h"
#include "BSE_editipo.h"
#include "BSE_edit.h"
@@ -447,7 +450,43 @@ void autocomplete_bone(char *str, void *arg_v)
}
}
-
+/* autocomplete callback for ID buttons */
+void autocomplete_vgroup(char *str, void *arg_v)
+{
+ Object *ob= (Object *)arg_v;
+ char truncate[40]= {0};
+
+ if(ob==NULL) return;
+
+ /* search if str matches the beginning of an ID struct */
+ if(str[0]) {
+ bDeformGroup *dg;
+
+ for(dg= ob->defbase.first; dg; dg= dg->next) {
+ int a;
+
+ for(a=0; a<31; a++) {
+ if(str[a]==0 || str[a]!=dg->name[a])
+ break;
+ }
+ /* found a match */
+ if(str[a]==0) {
+ /* first match */
+ if(truncate[0]==0)
+ BLI_strncpy(truncate, dg->name, 32);
+ else {
+ /* remove from truncate what is not in bone->name */
+ for(a=0; a<31; a++) {
+ if(truncate[a]!=dg->name[a])
+ truncate[a]= 0;
+ }
+ }
+ }
+ }
+ if(truncate[0])
+ BLI_strncpy(str, truncate, 32);
+ }
+}
static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, short *xco, short *yco)
{
@@ -1485,7 +1524,7 @@ void do_effects_panels(unsigned short event)
Object *ob;
Base *base;
Effect *eff, *effn;
- int type;
+ PartEff *paf;
ob= OBACT;
@@ -1506,11 +1545,12 @@ void do_effects_panels(unsigned short event)
else
copy_act_effect(ob);
}
+ DAG_scene_sort(G.scene);
BIF_undo_push("New effect");
allqueue(REDRAWBUTSOBJECT, 0);
break;
case B_DELEFFECT:
- if(ob==0 || ob->type!=OB_MESH) break;
+ if(ob==NULL || ob->type!=OB_MESH) break;
eff= ob->effect.first;
while(eff) {
effn= eff->next;
@@ -1555,25 +1595,6 @@ void do_effects_panels(unsigned short event)
}
allqueue(REDRAWBUTSOBJECT, 0);
break;
- case B_CHANGEEFFECT:
- if(ob==0 || ob->type!=OB_MESH) break;
- eff= ob->effect.first;
- while(eff) {
- if(eff->flag & SELECT) {
- if(eff->type!=eff->buttype) {
- BLI_remlink(&ob->effect, eff);
- type= eff->buttype;
- free_effect(eff);
- eff= add_effect(type);
- BLI_addtail(&ob->effect, eff);
- }
- break;
- }
- eff= eff->next;
- }
- allqueue(REDRAWVIEW3D, 0);
- allqueue(REDRAWBUTSOBJECT, 0);
- break;
case B_EFFECT_DEP:
DAG_scene_sort(G.scene);
/* no break, pass on */
@@ -1589,9 +1610,30 @@ void do_effects_panels(unsigned short event)
allqueue(REDRAWVIEW3D, 0);
allqueue(REDRAWBUTSOBJECT, 0);
break;
+ case B_PAF_SET_VG:
+
+ paf= give_parteff(ob);
+ if(paf) {
+ bDeformGroup *dg= get_named_vertexgroup(ob, paf->vgroupname);
+ if(dg)
+ paf->vertgroup= get_defgroup_num(ob, dg)+1;
+ else
+ paf->vertgroup= 0;
+
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ allqueue(REDRAWVIEW3D, 0);
+ }
+ break;
case B_FIELD_DEP:
DAG_scene_sort(G.scene);
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
+ if(ob->type==OB_CURVE && ob->pd->forcefield==PFIELD_GUIDE) {
+ Curve *cu= ob->data;
+ cu->flag |= (CU_PATH|CU_3D);
+ DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
+ }
allqueue(REDRAWVIEW3D, 0);
+ allqueue(REDRAWBUTSOBJECT, 0);
break;
case B_FIELD_CHANGE:
DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
@@ -1614,7 +1656,6 @@ void do_effects_panels(unsigned short event)
}
allqueue(REDRAWVIEW3D, 0);
break;
-
default:
if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
ob= OBACT;
@@ -1642,49 +1683,59 @@ static void object_panel_fields(Object *ob)
uiBlock *block;
block= uiNewBlock(&curarea->uiblocks, "object_panel_fields", UI_EMBOSS, UI_HELV, curarea->win);
- if(uiNewPanel(curarea, block, "Fields and Defection", "Physics", 420, 0, 318, 204)==0) return;
+ if(uiNewPanel(curarea, block, "Fields and Defection", "Physics", 0, 0, 318, 204)==0) return;
/* should become button, option? */
if(ob->pd==NULL) {
ob->pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect");
/* and if needed, init here */
- ob->pd->pdef_sbdamp = 0.1;
- ob->pd->pdef_sbift = 0.2;
- ob->pd->pdef_sboft = 0.02;
+ ob->pd->pdef_sbdamp = 0.1f;
+ ob->pd->pdef_sbift = 0.2f;
+ ob->pd->pdef_sboft = 0.02f;
}
if(ob->pd) {
PartDeflect *pd= ob->pd;
+ char *menustr= MEM_mallocN(256, "temp string");
+ char *tipstr="Choose field type";
uiDefBut(block, LABEL, 0, "Fields", 10,180,140,20, NULL, 0.0, 0, 0, 0, "");
- uiBlockBeginAlign(block);
- uiDefButS(block, ROW, B_FIELD_DEP, "None", 10,160,50,20, &pd->forcefield, 1.0, 0, 0, 0, "No force");
- uiDefButS(block, ROW, B_FIELD_DEP, "Force field", 60,160,90,20, &pd->forcefield, 1.0, PFIELD_FORCE, 0, 0, "Object center attracts or repels particles");
- uiDefButS(block, ROW, B_FIELD_DEP, "Wind", 10,140,50,20, &pd->forcefield, 1.0, PFIELD_WIND, 0, 0, "Constant force applied in direction of Object Z axis");
- uiDefButS(block, ROW, B_FIELD_DEP, "Vortex field", 60,140,90,20, &pd->forcefield, 1.0, PFIELD_VORTEX, 0, 0, "Particles swirl around Z-axis of the object");
-
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Strength: ", 10,110,140,20, &pd->f_strength, -1000, 1000, 10, 0, "Strength of force field");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 10,90,140,20, &pd->f_power, 0, 10, 100, 0, "Falloff power (real gravitational fallof = 2)");
+ /* setup menu button */
+ sprintf(menustr, "Field Type%%t|None %%x0|Spherical %%x%d|Wind %%x%d|Vortex %%x%d|Curve Guide %%x%d",
+ PFIELD_FORCE, PFIELD_WIND, PFIELD_VORTEX, PFIELD_GUIDE);
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use MaxDist", 10,60,140,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
- uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ", 10,40,140,20, &pd->maxdist, 0, 1000.0, 100, 0, "Maximum distance for the field to work");
- uiBlockEndAlign(block);
-
-// if(modifiers_isSoftbodyEnabled(ob)) {
- if(0) {
- uiDefBut(block, LABEL, 0, "Object is Soft Body,", 160,160,150,20, NULL, 0.0, 0, 0, 0, "");
- uiDefBut(block, LABEL, 0, "No Deflection possible", 160,140,150,20, NULL, 0.0, 0, 0, 0, "");
- pd->deflect= 0;
+ if(pd->forcefield==PFIELD_FORCE) tipstr= "Object center attracts or repels particles";
+ else if(pd->forcefield==PFIELD_WIND) tipstr= "Constant force applied in direction of Object Z axis";
+ else if(pd->forcefield==PFIELD_VORTEX) tipstr= "Particles swirl around Z-axis of the Object";
+ else if(pd->forcefield==PFIELD_GUIDE) tipstr= "Use a Curve Path to guide particles";
+
+ uiDefButS(block, MENU, B_FIELD_DEP, menustr, 10,160,140,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr);
+ MEM_freeN(menustr);
+
+ if(pd->forcefield) {
+ uiBlockBeginAlign(block);
+ if(pd->forcefield == PFIELD_GUIDE) {
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MinDist: ", 10,120,140,20, &pd->f_strength, 0.0, 1000.0, 10, 0, "The distance from which particles are affected fully.");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 10,100,140,20, &pd->f_power, 0.0, 10.0, 10, 0, "Falloff factor, between mindist and maxdist");
+ }
+ else {
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Strength: ", 10,110,140,20, &pd->f_strength, -1000, 1000, 10, 0, "Strength of force field");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "Fall-off: ", 10,90,140,20, &pd->f_power, 0, 10, 10, 0, "Falloff power (real gravitational fallof = 2)");
+ }
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, PFIELD_USEMAX, B_FIELD_CHANGE, "Use MaxDist", 10,60,140,20, &pd->flag, 0.0, 0, 0, 0, "Use a maximum distance for the field to work");
+ uiDefButF(block, NUM, B_FIELD_CHANGE, "MaxDist: ", 10,40,140,20, &pd->maxdist, 0, 1000.0, 10, 0, "Maximum distance for the field to work");
+ uiBlockEndAlign(block);
}
- else {
- uiDefBut(block, LABEL, 0, "Deflection", 160,180,140,20, NULL, 0.0, 0, 0, 0, "");
+
+ uiDefBut(block, LABEL, 0, "Deflection", 160,180,140,20, NULL, 0.0, 0, 0, 0, "");
- /* only meshes collide now */
- if(ob->type==OB_MESH) {
- uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
+ /* only meshes collide now */
+ if(ob->type==OB_MESH) {
+ uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision");
+ if(pd->deflect) {
uiDefBut(block, LABEL, 0, "Particles", 160,140,150,20, NULL, 0.0, 0, 0, 0, "");
uiBlockBeginAlign(block);
@@ -1699,12 +1750,8 @@ static void object_panel_fields(Object *ob)
uiDefButF(block, NUM, B_DIFF, "Damping:", 160,40,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during soft body collision");
uiDefButF(block, NUM, B_DIFF, "Inner:", 160,20,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness");
uiDefButF(block, NUM, B_DIFF, "Outer:", 160, 0,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness");
- uiBlockBeginAlign(block);
-/* seems to be working fine .. so we do use modifier stack by default .. code here rests for debugging
- uiDefButBitS(block, TOG, PDEFLE_DEFORM , 0,"UMS or CRASH", 0,0,150,20, &pd->flag, 0, 0, 0, 0, "Let collision object move with armatures/lattices WARNING logical circles will CRASH");
-*/
- }
- }
+ }
+ }
}
}
@@ -1741,7 +1788,7 @@ static void object_softbodies(Object *ob)
uiBlock *block;
block= uiNewBlock(&curarea->uiblocks, "object_softbodies", UI_EMBOSS, UI_HELV, curarea->win);
- if(uiNewPanel(curarea, block, "Soft Body", "Physics", 740, 0, 318, 204)==0) return;
+ if(uiNewPanel(curarea, block, "Soft Body", "Physics", 640, 0, 318, 204)==0) return;
/* do not allow to combine with force fields */
/* if(ob->pd && ob->pd->deflect) { */
@@ -1842,115 +1889,145 @@ static void object_softbodies(Object *ob)
}
+static void object_panel_particles_motion(Object *ob)
+{
+ uiBlock *block;
+ PartEff *paf= give_parteff(ob);
+
+ if (paf==NULL) return;
+
+ block= uiNewBlock(&curarea->uiblocks, "object_panel_particles_motion", UI_EMBOSS, UI_HELV, curarea->win);
+ uiNewPanelTabbed("Particles ", "Physics");
+ if(uiNewPanel(curarea, block, "Particle Motion", "Physics", 320, 0, 318, 204)==0) return;
+
+ /* top row */
+ uiBlockBeginAlign(block);
+ uiDefButI(block, NUM, B_CALCEFFECT, "Keys:", 0,180,75,20, &paf->totkey, 1.0, 100.0, 0, 0, "Specify the number of key positions");
+ uiDefButBitS(block, TOG, PAF_BSPLINE, B_CALCEFFECT, "Bspline", 75,180,75,20, &paf->flag, 0, 0, 0, 0, "Use B spline formula for particle interpolation");
+ uiDefButI(block, NUM, B_CALCEFFECT, "Seed:", 150,180,75,20, &paf->seed, 0.0, 255.0, 0, 0, "Set an offset in the random table");
+ uiDefButF(block, NUM, B_CALCEFFECT, "RLife:", 225,180,85,20, &paf->randlife, 0.0, 2.0, 10, 1, "Give the particlelife a random variation");
+ uiBlockEndAlign(block);
+
+ /* left collumn */
+ uiDefBut(block, LABEL, 0, "Velocity:", 0,150,150,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiBlockSetCol(block, TH_BUT_SETTING2);
+ uiDefButF(block, NUM, B_CALCEFFECT, "Normal:", 0,130,150,20, &paf->normfac, -2.0, 2.0, 1, 3, "Let the mesh give the particle a starting speed");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Object:", 0,110,150,20, &paf->obfac, -1.0, 1.0, 1, 3, "Let the object give the particle a starting speed");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Random:", 0,90,150,20, &paf->randfac, 0.0, 2.0, 1, 3, "Give the startingspeed a random variation");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Texture:", 0,70,150,20, &paf->texfac, 0.0, 2.0, 1, 3, "Let the texture give the particle a starting speed");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Damping:", 0,50,150,20, &paf->damp, 0.0, 1.0, 1, 3, "Specify the damping factor");
+ uiBlockEndAlign(block);
+ uiBlockSetCol(block, TH_AUTO);
+
+ uiDefBut(block, LABEL, 0, "Texture Emission", 0,30,150,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG3, PAF_TEXTIME, B_CALCEFFECT, "TexEmit", 0,10,75,20, &(paf->flag2), 0, 0, 0, 0, "Use a texture to define emission of particles");
+ uiDefButS(block, NUM, B_CALCEFFECT, "Tex:", 75,10,75,20, &paf->timetex, 1.0, 8.0, 0, 0, "Specify texture used for the texture emission");
+
+ /* right collumn */
+ uiBlockBeginAlign(block);
+ uiDefBut(block, LABEL, 0, "Force:", 160,130,75,20, NULL, 0.0, 0, 0, 0, "");
+ uiDefButF(block, NUM, B_CALCEFFECT, "X:", 235,130,75,20, paf->force, -1.0, 1.0, 1, 2, "Specify the X axis of a continues force");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Y:", 160,110,75,20, paf->force+1,-1.0, 1.0, 1, 2, "Specify the Y axis of a continues force");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Z:", 235,110,75,20, paf->force+2, -1.0, 1.0, 1, 2, "Specify the Z axis of a continues force");
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, B_CALCEFFECT, "Tex:", 160,80,75,20, &paf->speedtex, 1.0, 10.0, 0, 2, "Specify the texture used for force");
+ uiDefButF(block, NUM, B_CALCEFFECT, "X:", 235,80,75,20, paf->defvec, -1.0, 1.0, 1, 2, "Specify the X axis of a force, determined by the texture");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Y:", 160,60,75,20, paf->defvec+1,-1.0, 1.0, 1, 2, "Specify the Y axis of a force, determined by the texture");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Z:", 235,60,75,20, paf->defvec+2, -1.0, 1.0, 1, 2, "Specify the Z axis of a force, determined by the texture");
+
+ uiBlockBeginAlign(block);
+ uiDefButS(block, ROW, B_CALCEFFECT, "Int", 160,30,50,20, &paf->texmap, 14.0, 0.0, 0, 0, "Use texture intensity as a factor for texture force");
+ uiDefButS(block, ROW, B_CALCEFFECT, "RGB", 210,30,50,20, &paf->texmap, 14.0, 1.0, 0, 0, "Use RGB values as a factor for particle speed vector");
+ uiDefButS(block, ROW, B_CALCEFFECT, "Grad", 260,30,50,20, &paf->texmap, 14.0, 2.0, 0, 0, "Use texture gradient as a factor for particle speed vector");
+
+ uiDefButF(block, NUM, B_CALCEFFECT, "Nabla:", 160,10,150,20, &paf->nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient calculation");
+
+}
+
+
static void object_panel_particles(Object *ob)
{
- Effect *eff;
uiBlock *block;
- int a;
- short x, y;
+ uiBut *but;
+ PartEff *paf= give_parteff(ob);
block= uiNewBlock(&curarea->uiblocks, "object_panel_particles", UI_EMBOSS, UI_HELV, curarea->win);
- if(uiNewPanel(curarea, block, "Particles", "Physics", 0, 0, 418, 204)==0) return;
+ if(uiNewPanel(curarea, block, "Particles ", "Physics", 320, 0, 318, 204)==0) return;
- /* EFFECTS */
-
if (ob->type == OB_MESH) {
uiBlockBeginAlign(block);
- uiDefBut(block, BUT, B_NEWEFFECT, "NEW", 550,187,124,27, 0, 0, 0, 0, 0, "Create a new Particle effect");
- uiDefBut(block, BUT, B_DELEFFECT, "Delete", 676,187,62,27, 0, 0, 0, 0, 0, "Delete the effect");
- uiBlockEndAlign(block);
+ if(paf==NULL)
+ uiDefBut(block, BUT, B_NEWEFFECT, "NEW", 0,180,75,20, 0, 0, 0, 0, 0, "Create a new Particle effect");
+ else
+ uiDefBut(block, BUT, B_DELEFFECT, "Delete", 0,180,75,20, 0, 0, 0, 0, 0, "Delete the effect");
}
-
- /* select effs */
- eff= ob->effect.first;
- a= 0;
- while(eff) {
-
- x= 15 * a + 550;
- y= 172; // - 12*( abs(a/10) ) ;
- uiDefButBitS(block, TOG, SELECT, B_SELEFFECT+a, "", x, y, 15, 12, &eff->flag, 0, 0, 0, 0, "");
-
- a++;
- if(a==MAX_EFFECT) break;
- eff= eff->next;
+ else uiDefBut(block, LABEL, 0, "Only Mesh Objects can generate particles", 10,180,300,20, NULL, 0.0, 0, 0, 0, "");
+
+
+ if(paf==NULL) return;
+
+ uiDefBut(block, BUT, B_RECALCAL, "RecalcAll", 75,180,75,20, 0, 0, 0, 0, 0, "Update all particle systems");
+ uiBlockEndAlign(block);
+
+ uiDefBut(block, LABEL, 0, "Emit:", 0,150,75,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButI(block, NUM, B_CALCEFFECT, "Num:", 0,130,150,20, &paf->totpart, 1.0, 100000.0, 0, 0, "The total number of particles");
+ if(paf->flag & PAF_STATIC) {
+ uiDefButS(block, NUM, REDRAWVIEW3D, "Step:", 0,110,150,20, &paf->staticstep, 1.0, 100.0, 10, 0, "For static duplicators, the Step value skips particles");
}
+ else {
+ uiDefButF(block, NUM, B_CALCEFFECT, "Sta:", 0,110,75,20, &paf->sta, -250.0, MAXFRAMEF, 100, 1, "Frame # to start emitting particles");
+ uiDefButF(block, NUM, B_CALCEFFECT, "End:", 75,110,75,20, &paf->end, 1.0, MAXFRAMEF, 100, 1, "Frame # to stop emitting particles");
+ }
+ uiDefButF(block, NUM, B_CALCEFFECT, "Life:", 0,90,75,20, &paf->lifetime, 1.0, MAXFRAMEF, 100, 1, "Specify the life span of the particles");
+ uiDefButS(block, NUM, B_CALCEFFECT, "Disp:", 75,90,75,20, &paf->disp, 1.0, 100.0, 10, 0, "Percentage of particles to calculate for 3d view");
+ uiBlockEndAlign(block);
- eff= ob->effect.first;
- while(eff) {
- if(eff->flag & SELECT) break;
- eff= eff->next;
+ uiDefBut(block, LABEL, 0, "From:", 0,70,75,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOGN, PAF_OFACE, B_CALCEFFECT, "Verts", 0,50,75,20, &paf->flag, 0, 0, 0, 0, "Emit particles from vertices");
+ uiDefButBitS(block, TOG, PAF_FACE, B_CALCEFFECT, "Faces", 75,50,75,20, &paf->flag, 0, 0, 0, 0, "Emit particles from faces");
+ if(paf->flag & PAF_FACE) {
+ uiDefButBitS(block, TOG, PAF_TRAND, B_CALCEFFECT, "Rand", 0,30,50,20, &paf->flag, 0, 0, 0, 0, "Use true random distribution from faces");
+ uiDefButBitS(block, TOG, PAF_EDISTR, B_CALCEFFECT, "Even", 50,30,50,20, &paf->flag, 0, 0, 0, 0, "Use even distribution from faces based on face areas");
+ uiDefButS(block, NUM, B_CALCEFFECT, "P/F:", 100,30,50,20, &paf->userjit, 0.0, 200.0, 1, 0, "Jitter table distribution: maximum particles per face (0=uses default)");
}
+ else uiBlockEndAlign(block); /* vgroup button no align */
- if(eff) {
- if(eff->type==EFF_PARTICLE) {
- PartEff *paf;
-
- paf= (PartEff *)eff;
-
- uiDefBut(block, BUT, B_RECALCAL, "RecalcAll", 741,187,67,27, 0, 0, 0, 0, 0, "Update the particle system");
- uiBlockBeginAlign(block);
- uiDefButBitS(block, TOG, PAF_STATIC, B_EFFECT_DEP, "Static", 825,187,67,27, &paf->flag, 0, 0, 0, 0, "Make static particles (deform only works with SubSurf)");
- if(paf->flag & PAF_STATIC) {
- uiDefButBitS(block, TOG, PAF_ANIMATED, B_DIFF, "Animated",895,187,107,27, &paf->flag, 0, 0, 0, 0, "Static particles are recalculated each rendered frame");
- }
- uiBlockBeginAlign(block);
- uiDefButI(block, NUM, B_CALCEFFECT, "Tot:", 550,146,91,20, &paf->totpart, 1.0, 100000.0, 0, 0, "Set the total number of particles");
- if(paf->flag & PAF_STATIC) {
- uiDefButS(block, NUM, REDRAWVIEW3D, "Step:", 644,146,84+97,20, &paf->staticstep, 1.0, 100.0, 10, 0, "For static duplicators, the Step value skips particles");
- }
- else {
- uiDefButF(block, NUM, B_CALCEFFECT, "Sta:", 644,146,84,20, &paf->sta, -250.0, MAXFRAMEF, 100, 0, "Specify the startframe");
- uiDefButF(block, NUM, B_CALCEFFECT, "End:", 731,146,97,20, &paf->end, 1.0, MAXFRAMEF, 100, 0, "Specify the endframe");
- }
- uiDefButF(block, NUM, B_CALCEFFECT, "Life:", 831,146,88,20, &paf->lifetime, 1.0, MAXFRAMEF, 100, 0, "Specify the life span of the particles");
- uiDefButI(block, NUM, B_CALCEFFECT, "Keys:", 922,146,80,20, &paf->totkey, 1.0, 100.0, 0, 0, "Specify the number of key positions");
-
- uiDefButS(block, NUM, B_REDR, "CurMul:", 550,124,91,20, &paf->curmult, 0.0, 3.0, 0, 0, "Multiply the particles");
- uiDefButS(block, NUM, B_CALCEFFECT, "Mat:", 644,124,84,20, paf->mat+paf->curmult, 1.0, 8.0, 0, 0, "Specify the material used for the particles");
- uiDefButF(block, NUM, B_CALCEFFECT, "Mult:", 730,124,98,20, paf->mult+paf->curmult, 0.0, 1.0, 10, 0, "Probability \"dying\" particle spawns a new one.");
- uiDefButF(block, NUM, B_CALCEFFECT, "Life:", 831,124,89,20, paf->life+paf->curmult, 1.0, 600.0, 100, 0, "Specify the lifespan of the next generation particles");
- uiDefButS(block, NUM, B_CALCEFFECT, "Child:", 922,124,80,20, paf->child+paf->curmult, 1.0, 600.0, 100, 0, "Specify the number of children of a particle that multiply itself");
-
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_CALCEFFECT, "Randlife:", 550,96,96,20, &paf->randlife, 0.0, 2.0, 10, 0, "Give the particlelife a random variation");
- uiDefButI(block, NUM, B_CALCEFFECT, "Seed:", 652,96,80,20, &paf->seed, 0.0, 255.0, 0, 0, "Set an offset in the random table");
-
- uiDefButBitS(block, TOG, PAF_FACE, B_CALCEFFECT, "Face", 735,96,46,20, &paf->flag, 0, 0, 0, 0, "Emit particles also from faces");
- uiDefButBitS(block, TOG, PAF_BSPLINE, B_CALCEFFECT, "Bspline", 782,96,54,20, &paf->flag, 0, 0, 0, 0, "Use B spline formula for particle interpolation");
- uiDefButS(block, TOG, REDRAWVIEW3D, "Vect", 837,96,45,20, &paf->stype, 0, 0, 0, 0, "Give the particles a rotation direction");
- uiDefButF(block, NUM, B_DIFF, "VectSize", 885,96,116,20, &paf->vectsize, 0.0, 1.0, 10, 0, "Set the speed for Vect");
-
- uiBlockBeginAlign(block);
- uiBlockSetCol(block, TH_BUT_SETTING2);
- uiDefButF(block, NUM, B_CALCEFFECT, "Norm:", 550,67,96,20, &paf->normfac, -2.0, 2.0, 10, 0, "Let the mesh give the particle a starting speed");
- uiDefButF(block, NUM, B_CALCEFFECT, "Ob:", 649,67,86,20, &paf->obfac, -1.0, 1.0, 10, 0, "Let the object give the particle a starting speed");
- uiDefButF(block, NUM, B_CALCEFFECT, "Rand:", 738,67,86,20, &paf->randfac, 0.0, 2.0, 10, 0, "Give the startingspeed a random variation");
- uiDefButF(block, NUM, B_CALCEFFECT, "Tex:", 826,67,85,20, &paf->texfac, 0.0, 2.0, 10, 0, "Let the texture give the particle a starting speed");
- uiDefButF(block, NUM, B_CALCEFFECT, "Damp:", 913,67,89,20, &paf->damp, 0.0, 1.0, 10, 0, "Specify the damping factor");
- uiBlockSetCol(block, TH_AUTO);
-
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_CALCEFFECT, "X:", 550,31,72,20, paf->force, -1.0, 1.0, 1, 0, "Specify the X axis of a continues force");
- uiDefButF(block, NUM, B_CALCEFFECT, "Y:", 624,31,78,20, paf->force+1,-1.0, 1.0, 1, 0, "Specify the Y axis of a continues force");
- uiDefBut(block, LABEL, 0, "Force:", 550,9,72,20, NULL, 1.0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_CALCEFFECT, "Z:", 623,9,79,20, paf->force+2, -1.0, 1.0, 1, 0, "Specify the Z axis of a continues force");
-
- uiBlockBeginAlign(block);
- uiDefButF(block, NUM, B_CALCEFFECT, "X:", 722,31,74,20, paf->defvec, -1.0, 1.0, 1, 0, "Specify the X axis of a force, determined by the texture");
- uiDefButF(block, NUM, B_CALCEFFECT, "Y:", 798,31,74,20, paf->defvec+1,-1.0, 1.0, 1, 0, "Specify the Y axis of a force, determined by the texture");
- uiDefBut(block, LABEL, 0, "Texture:", 722,9,74,20, NULL, 1.0, 0, 0, 0, "");
- uiDefButF(block, NUM, B_CALCEFFECT, "Z:", 797,9,75,20, paf->defvec+2, -1.0, 1.0, 1, 0, "Specify the Z axis of a force, determined by the texture");
- uiBlockEndAlign(block);
-
- uiDefButS(block, ROW, B_CALCEFFECT, "Int", 875,9,32,43, &paf->texmap, 14.0, 0.0, 0, 0, "Use texture intensity as a factor for texture force");
+ but=uiDefBut(block, TEX, B_PAF_SET_VG, "VGroup:", 0,10,150,20, paf->vgroupname, 0, 31, 0, 0, "Name of vertex group to use");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)OBACT);
+ uiBlockEndAlign(block);
+
+ /* right collumn */
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, PAF_STATIC, B_EFFECT_DEP, "Static", 160,180,75,20, &paf->flag, 0, 0, 0, 0, "Make static particles (deform only works with SubSurf)");
+ if(paf->flag & PAF_STATIC) {
+ uiDefButBitS(block, TOG, PAF_ANIMATED, B_DIFF, "Animated", 235,180,75,20, &paf->flag, 0, 0, 0, 0, "Static particles are recalculated each rendered frame");
+ }
+ uiBlockEndAlign(block);
- uiBlockBeginAlign(block);
- uiDefButS(block, ROW, B_CALCEFFECT, "RGB", 911,31,45,20, &paf->texmap, 14.0, 1.0, 0, 0, "Use RGB values as a factor for particle speed vector");
- uiDefButS(block, ROW, B_CALCEFFECT, "Grad", 958,31,44,20, &paf->texmap, 14.0, 2.0, 0, 0, "Use texture gradient as a factor for particle speed vector");
- uiDefButF(block, NUM, B_CALCEFFECT, "Nabla:", 911,9,91,20, &paf->nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient calculation");
+ uiDefBut(block, LABEL, 0, "Display:", 160,150,75,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, B_CALCEFFECT, "Material:", 160,130,150,20, &paf->omat, 1.0, 16.0, 0, 0, "Specify material used for the particles");
+ uiDefButS(block, TOG|BIT|7, B_REDR, "Mesh", 160,110,50,20, &paf->flag, 0, 0, 0, 0, "Render emitter Mesh also");
+ uiDefButBitS(block, TOG, PAF_UNBORN, B_DIFF, "Unborn",210,110,50,20, &paf->flag, 0, 0, 0, 0, "Make particles appear before they are emitted");
+ uiDefButBitS(block, TOG, PAF_DIED, B_DIFF, "Died", 260,110,50,20, &paf->flag, 0, 0, 0, 0, "Make particles appear after they have died");
+ uiDefButS(block, TOG, REDRAWVIEW3D, "Vect", 160,90,75,20, &paf->stype, 0, 0, 0, 0, "Give the particles a direction and rotation");
+ uiDefButF(block, NUM, B_DIFF, "Size:", 235,90,75,20, &paf->vectsize, 0.0, 1.0, 10, 1, "The amount the Vect option influences halo size");
+ uiBlockEndAlign(block);
- }
- }
+ uiDefBut(block, LABEL, 0, "Children:", 160,70,75,20, NULL, 0.0, 0, 0, 0, "");
+ uiBlockBeginAlign(block);
+ uiDefButS(block, NUM, B_REDR, "Generation:", 160,50,150,20, &paf->curmult, 0.0, 3.0, 0, 0, "Current generation of particles");
+ uiDefButS(block, NUM, B_CALCEFFECT, "Num:", 160,30,75,20, paf->child+paf->curmult, 1.0, 600.0, 100, 0, "Specify the number of generations of particles that can multiply itself");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Prob:", 235,30,75,20, paf->mult+paf->curmult, 0.0, 1.0, 10, 1, "Probability \"dying\" particle spawns a new one.");
+ uiDefButF(block, NUM, B_CALCEFFECT, "Life:", 160,10,75,20, paf->life+paf->curmult, 1.0, 600.0, 100, 1, "Specify the lifespan of the next generation particles");
+ uiDefButS(block, NUM, B_CALCEFFECT, "Mat:", 235,10,75,20, paf->mat+paf->curmult, 1.0, 8.0, 0, 0, "Specify the material used for the particles");
+ uiBlockEndAlign(block);
+
}
/* NT - Panel for fluidsim settings */
@@ -1963,6 +2040,7 @@ static void object_panel_fluidsim(Object *ob)
const int objHeight = 20;
block= uiNewBlock(&curarea->uiblocks, "object_fluidsim", UI_EMBOSS, UI_HELV, curarea->win);
+ uiNewPanelTabbed("Soft Body", "Physics");
if(uiNewPanel(curarea, block, "Fluid Simulation", "Physics", 1060, 0, 318, 204)==0) return;
uiDefButBitS(block, TOG, OB_FLUIDSIM_ENABLE, REDRAWBUTSOBJECT, "Enable", 0,yline, 75,objHeight,
@@ -2130,8 +2208,9 @@ void physics_panels()
ob= OBACT;
if(ob) {
if(ob->id.lib) uiSetButLock(1, "Can't edit library data");
- object_panel_particles(ob);
object_panel_fields(ob);
+ object_panel_particles(ob);
+ object_panel_particles_motion(ob);
object_softbodies(ob);
object_panel_fluidsim(ob);
}
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index 9323ac6ea2e..60383de8b14 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -87,6 +87,7 @@
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_object.h"
+#include "BKE_anim.h" //for the where_on_path function
#include "BIF_gl.h"
#include "BIF_glutil.h"
@@ -2390,10 +2391,10 @@ static void draw_static_particle_system(Object *ob, PartEff *paf)
int a;
pa= paf->keys;
- if(pa==0) {
+ if(pa==NULL) {
build_particle_system(ob);
pa= paf->keys;
- if(pa==0) return;
+ if(pa==NULL) return;
}
glPointSize(1.0);
@@ -2978,6 +2979,13 @@ static void draw_forcefield(Object *ob)
PartDeflect *pd= ob->pd;
float imat[4][4], tmat[4][4];
float vec[3]= {0.0, 0.0, 0.0};
+ int curcol;
+
+ if(ob!=G.obedit && (ob->flag & SELECT)) {
+ if(ob==OBACT) curcol= TH_ACTIVE;
+ else curcol= TH_SELECT;
+ }
+ else curcol= TH_WIRE;
/* calculus here, is reused in PFIELD_FORCE */
mygetmatrix(tmat);
@@ -2985,17 +2993,11 @@ static void draw_forcefield(Object *ob)
// Normalise(imat[0]); // we don't do this because field doesnt scale either... apart from wind!
// Normalise(imat[1]);
- if(pd->flag & PFIELD_USEMAX) {
- setlinestyle(3);
- BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
- drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
- setlinestyle(0);
- }
if (pd->forcefield == PFIELD_WIND) {
float force_val;
Mat4One(tmat);
- BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.5);
if (has_ipo_code(ob->ipo, OB_PD_FSTR))
force_val = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
@@ -3019,11 +3021,11 @@ static void draw_forcefield(Object *ob)
else
ffall_val = pd->f_power;
- BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.5);
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.5);
drawcircball(GL_LINE_LOOP, vec, 1.0, imat);
- BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(1.5, (double)ffall_val));
drawcircball(GL_LINE_LOOP, vec, 1.5, imat);
- BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.9 - 0.4 / pow(2.0, (double)ffall_val));
drawcircball(GL_LINE_LOOP, vec, 2.0, imat);
}
else if (pd->forcefield == PFIELD_VORTEX) {
@@ -3040,7 +3042,7 @@ static void draw_forcefield(Object *ob)
else
force_val = pd->f_strength;
- BIF_ThemeColorBlend(TH_WIRE, TH_BACK, 0.7);
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.7);
if (force_val < 0) {
drawspiral(vec, 1.0, imat, 1);
drawspiral(vec, 1.0, imat, 16);
@@ -3050,7 +3052,39 @@ static void draw_forcefield(Object *ob)
drawspiral(vec, 1.0, imat, -16);
}
}
+ else if (pd->forcefield == PFIELD_GUIDE && ob->type==OB_CURVE) {
+ Curve *cu= ob->data;
+ if((cu->flag & CU_PATH) && cu->path && cu->path->data) {
+ float mindist, guidevec1[4], guidevec2[3];
+
+ if (has_ipo_code(ob->ipo, OB_PD_FSTR))
+ mindist = IPO_GetFloatValue(ob->ipo, OB_PD_FSTR, G.scene->r.cfra);
+ else
+ mindist = pd->f_strength;
+
+ /*path end*/
+ setlinestyle(3);
+ where_on_path(ob, 1.0f, guidevec1, guidevec2);
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.5);
+ drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+
+ /*path beginning*/
+ setlinestyle(0);
+ where_on_path(ob, 0.0f, guidevec1, guidevec2);
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.5);
+ drawcircball(GL_LINE_LOOP, guidevec1, mindist, imat);
+
+ VECCOPY(vec, guidevec1); /* max center */
+ }
+ }
+ /* as last, guide curve alters it */
+ if(pd->flag & PFIELD_USEMAX) {
+ setlinestyle(3);
+ BIF_ThemeColorBlend(curcol, TH_BACK, 0.5);
+ drawcircball(GL_LINE_LOOP, vec, pd->maxdist, imat);
+ setlinestyle(0);
+ }
}
static void draw_box(float vec[8][3])
@@ -3480,7 +3514,7 @@ void draw_object(Base *base)
PartEff *paf = give_parteff(ob);
if(paf) {
- if(col) cpack(0xFFFFFF); /* for visibility */
+ if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
if(paf->flag & PAF_STATIC) draw_static_particle_system(ob, paf);
else if((G.f & G_PICKSEL) == 0) draw_particle_system(ob, paf); // selection errors happen to easy
if(col) cpack(col);
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 7a8375ba0cc..5fdd2aa3980 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1539,7 +1539,8 @@ void exit_editmode(int freedata) /* freedata==0 at render, 1= freedata, 2= do un
sbObjectToSoftbody(ob);
}
- DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
+ /* also flush ob recalc, doesn't take much overhead, but used for particles */
+ DAG_object_flush_update(G.scene, ob, OB_RECALC_OB|OB_RECALC_DATA);
if(freedata) {
setcursor_space(SPACE_VIEW3D, CURSOR_STD);