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--release/ui/buttons_data_modifier.py9
-rw-r--r--release/ui/buttons_particle.py35
-rw-r--r--source/blender/blenkernel/BKE_particle.h5
-rw-r--r--source/blender/blenkernel/intern/anim.c13
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c4
-rw-r--r--source/blender/blenkernel/intern/modifier.c62
-rw-r--r--source/blender/blenkernel/intern/particle.c541
-rw-r--r--source/blender/blenkernel/intern/particle_system.c36
-rw-r--r--source/blender/blenkernel/intern/pointcache.c15
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/editors/interface/interface_templates.c2
-rw-r--r--source/blender/editors/object/object_modifier.c4
-rw-r--r--source/blender/editors/space_view3d/drawobject.c549
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h4
-rw-r--r--source/blender/makesdna/DNA_particle_types.h8
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c30
-rw-r--r--source/blender/makesrna/intern/rna_particle.c73
-rw-r--r--source/blender/render/intern/source/convertblender.c163
18 files changed, 982 insertions, 572 deletions
diff --git a/release/ui/buttons_data_modifier.py b/release/ui/buttons_data_modifier.py
index 2400461b623..477be27e820 100644
--- a/release/ui/buttons_data_modifier.py
+++ b/release/ui/buttons_data_modifier.py
@@ -300,9 +300,18 @@ class DATA_PT_modifiers(DataButtonsPanel):
col.itemR(md, "normal")
col.itemR(md, "children")
col.itemR(md, "path")
+ if md.path:
+ col.itemR(md, "keep_shape")
col.itemR(md, "unborn")
col.itemR(md, "alive")
col.itemR(md, "dead")
+ if md.path:
+ col.itemR(md, "axis", text="")
+
+ if md.path:
+ row = layout.row()
+ row.itemR(md, "position", slider=True)
+ row.itemR(md, "random_position", text = "Random", slider=True)
def particlesystem(self, layout, ob, md):
layout.itemL(text="See Particle panel.")
diff --git a/release/ui/buttons_particle.py b/release/ui/buttons_particle.py
index 49ceaf6aae1..93ce9c5c745 100644
--- a/release/ui/buttons_particle.py
+++ b/release/ui/buttons_particle.py
@@ -353,19 +353,14 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
colsub.itemR(part, "adaptive_pix")
sub.itemR(part, "hair_bspline")
sub.itemR(part, "render_step", text="Steps")
- sub = split.column()
- sub.itemL(text="Length:")
- sub.itemR(part, "abs_length", text="Absolute")
- sub.itemR(part, "absolute_length", text="Maximum")
+ sub = split.column()
+
+ sub.itemL(text="Timing:")
+ sub.itemR(part, "abs_path_time")
+ sub.itemR(part, "path_start", text="Start", slider= not part.abs_path_time)
+ sub.itemR(part, "path_end", text="End", slider= not part.abs_path_time)
sub.itemR(part, "random_length", text="Random", slider=True)
- #row = layout.row()
- #row.itemR(part, "timed_path")
- #col = row.column(align=True)
- #col.active = part.timed_path == True
- #col.itemR(part, "line_length_tail", text="Start")
- #col.itemR(part, "line_length_head", text="End")
-
row = layout.row()
col = row.column()
@@ -384,7 +379,6 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
elif part.ren_as == 'OBJECT':
- #sub = split.column()
sub.itemR(part, "dupli_object")
elif part.ren_as == 'GROUP':
sub.itemR(part, "dupli_group")
@@ -428,7 +422,19 @@ class PARTICLE_PT_render(ParticleButtonsPanel):
row.itemR(part, "billboard_animation", expand=True)
row.itemL(text="Offset:")
row.itemR(part, "billboard_split_offset", expand=True)
-
+ if part.ren_as == 'HALO' or part.ren_as == 'LINE' or part.ren_as=='BILLBOARD':
+ row = layout.row()
+ col = row.column()
+ col.itemR(part, "trail_count")
+ if part.trail_count > 1:
+ col.itemR(part, "abs_path_time", text="Length in frames")
+ col = row.column()
+ col.itemR(part, "path_end", text="Length", slider=not part.abs_path_time)
+ col.itemR(part, "random_length", text="Random", slider=True)
+ else:
+ col = row.column()
+ col.itemL(text="")
+
class PARTICLE_PT_draw(ParticleButtonsPanel):
__idname__= "PARTICLE_PT_draw"
__label__ = "Display"
@@ -475,11 +481,12 @@ class PARTICLE_PT_draw(ParticleButtonsPanel):
col.itemR(part, "draw_health")
col = row.column()
+ col.itemR(part, "material_color", text="Use material color")
+
if (path):
box = col.box()
box.itemR(part, "draw_step")
else:
- col.itemR(part, "material_color", text="Use material color")
subcol = col.column()
subcol.active = part.material_color==False
#subcol.itemL(text="color")
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 73f0195d1d8..aa24706077d 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -91,7 +91,8 @@ typedef struct ParticleTexture{
float ivel; /* used in reset */
float time, life, exist, size; /* used in init */
float pvel[3]; /* used in physics */
- float length, clump, kink, rough; /* used in path caching */
+ float length, clump, kink, effector;/* used in path caching */
+ float rough1, rough2, roughe; /* used in path caching */
} ParticleTexture;
typedef struct BoidVecFunc{
@@ -270,7 +271,7 @@ void psys_update_world_cos(struct Object *ob, struct ParticleSystem *psys);
int do_guide(struct Scene *scene, struct ParticleKey *state, int pa_num, float time, struct ListBase *lb);
float psys_get_size(struct Object *ob, struct Material *ma, struct ParticleSystemModifierData *psmd, struct IpoCurve *icu_size, struct ParticleSystem *psys, struct ParticleSettings *part, struct ParticleData *pa, float *vg_size);
float psys_get_timestep(struct ParticleSettings *part);
-float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra);
+float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
float psys_get_child_size(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *pa_time);
void psys_get_particle_on_path(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int pa_num, struct ParticleKey *state, int vel);
int psys_get_particle_state(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, int p, struct ParticleKey *state, int always);
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 1aceca454d2..6c1b8eb9000 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -786,8 +786,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
BLI_srandom(31415926 + psys->seed);
lay= scene->lay;
- if((part->draw_as == PART_DRAW_OB && part->dup_ob) ||
- (part->draw_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first)) {
+ if((psys->renderdata || part->draw_as==PART_DRAW_REND) &&
+ ((part->ren_as == PART_DRAW_OB && part->dup_ob) ||
+ (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first))) {
/* if we have a hair particle system, use the path cache */
if(part->type == PART_HAIR) {
@@ -804,7 +805,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
psys->lattice = psys_get_lattice(scene, par, psys);
/* gather list of objects or single object */
- if(part->draw_as==PART_DRAW_GR) {
+ if(part->ren_as==PART_DRAW_GR) {
group_handle_recalc_and_update(scene, par, part->dup_group);
for(go=part->dup_group->gobject.first; go; go=go->next)
@@ -850,7 +851,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
size = psys_get_child_size(psys, cpa, ctime, 0);
}
- if(part->draw_as==PART_DRAW_GR) {
+ if(part->ren_as==PART_DRAW_GR) {
/* for groups, pick the object based on settings */
if(part->draw&PART_DRAW_RAND_GR)
b= BLI_rand() % totgroup;
@@ -894,7 +895,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
pamat[3][3]= 1.0f;
}
- if(part->draw_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
+ if(part->ren_as==PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
for(go= part->dup_group->gobject.first, b=0; go; go= go->next, b++) {
Mat4MulMat4(tmat, oblist[b]->obmat, pamat);
Mat4MulFloat3((float *)tmat, size*scale);
@@ -930,7 +931,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p
}
/* restore objects since they were changed in where_is_object_time */
- if(part->draw_as==PART_DRAW_GR) {
+ if(part->ren_as==PART_DRAW_GR) {
for(a=0; a<totgroup; a++)
*(oblist[a])= obcopylist[a];
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index a36b825293e..de036e25d82 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -568,14 +568,14 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Keyed Physics");
}
- if(part->draw_as == PART_DRAW_OB && part->dup_ob) {
+ if(part->ren_as == PART_DRAW_OB && part->dup_ob) {
node2 = dag_get_node(dag, part->dup_ob);
dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualisation");
if(part->dup_ob->type == OB_MBALL)
dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualisation");
}
- if(part->draw_as == PART_DRAW_GR && part->dup_group) {
+ if(part->ren_as == PART_DRAW_GR && part->dup_group) {
for(go=part->dup_group->gobject.first; go; go=go->next) {
node2 = dag_get_node(dag, go->ob);
dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Group Visualisation");
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 9ecf3a32c2b..71428a9e947 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -6390,6 +6390,7 @@ static void particleSystemModifier_deformVerts(
}
if(psys){
+ psmd->flag &= ~eParticleSystemFlag_psys_updated;
particle_system_update(md->scene, ob, psys);
psmd->flag |= eParticleSystemFlag_psys_updated;
psmd->flag &= ~eParticleSystemFlag_DM_changed;
@@ -6421,6 +6422,8 @@ static void particleInstanceModifier_initData(ModifierData *md)
pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
pimd->psys = 1;
+ pimd->position = 1.0f;
+ pimd->axis = 2;
}
static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *target)
@@ -6431,6 +6434,8 @@ static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *ta
tpimd->ob = pimd->ob;
tpimd->psys = pimd->psys;
tpimd->flag = pimd->flag;
+ tpimd->position = pimd->position;
+ tpimd->random_position = pimd->random_position;
}
static int particleInstanceModifier_dependsOnTime(ModifierData *md)
@@ -6470,7 +6475,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
MFace *mface, *orig_mface;
MVert *mvert, *orig_mvert;
int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
- short track=ob->trackflag%3, trackneg;
+ short track=ob->trackflag%3, trackneg, axis = pimd->axis;
float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
trackneg=((ob->trackflag>2)?1:0);
@@ -6508,7 +6513,7 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
psys->lattice=psys_get_lattice(md->scene, ob, psys);
- if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){
+ if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
float min_r[3], max_r[3];
INIT_MINMAX(min_r, max_r);
@@ -6533,33 +6538,50 @@ static DerivedMesh * particleInstanceModifier_applyModifier(
/*change orientation based on object trackflag*/
VECCOPY(temp_co,mv->co);
- mv->co[0]=temp_co[track];
- mv->co[1]=temp_co[(track+1)%3];
- mv->co[2]=temp_co[(track+2)%3];
-
- if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) && pimd->flag & eParticleInstanceFlag_Path){
- state.time=(mv->co[0]-min_co)/(max_co-min_co);
- if(trackneg)
- state.time=1.0f-state.time;
- psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1);
+ mv->co[axis]=temp_co[track];
+ mv->co[(axis+1)%3]=temp_co[(track+1)%3];
+ mv->co[(axis+2)%3]=temp_co[(track+2)%3];
+
+ if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
+ float ran = 0.0f;
+ if(pimd->random_position != 0.0f) {
+ /* just use some static collection of random numbers */
+ /* TODO: use something else that's unique to each instanced object */
+ pa = psys->particles + (i/totvert)%totpart;
+ ran = pimd->random_position * 0.5 * (1.0f + pa->r_ave[0]);
+ }
- mv->co[0] = 0.0;
+ if(pimd->flag & eParticleInstanceFlag_KeepShape) {
+ state.time = pimd->position * (1.0f - ran);
+ }
+ else {
+ state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
+
+ if(trackneg)
+ state.time=1.0f-state.time;
+
+ mv->co[axis] = 0.0;
+ }
+
+ psys_get_particle_on_path(md->scene, pimd->ob, psys,first_particle + i/totvert, &state,1);
Normalize(state.vel);
- if(state.vel[0] < -0.9999 || state.vel[0] > 0.9999) {
- state.rot[0] = 1.0;
+ /* TODO: incremental rotations somehow */
+ if(state.vel[axis] < -0.9999 || state.vel[axis] > 0.9999) {
+ state.rot[0] = 1;
state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
}
else {
- /* a cross product of state.vel and a unit vector in x-direction */
- cross[0] = 0.0f;
- cross[1] = -state.vel[2];
- cross[2] = state.vel[1];
+ float temp[3] = {0.0f,0.0f,0.0f};
+ temp[axis] = 1.0f;
- /* state.vel[0] is the only component surviving from a dot product with a vector in x-direction*/
- VecRotToQuat(cross,saacos(state.vel[0]),state.rot);
+ Crossf(cross, temp, state.vel);
+
+ /* state.vel[axis] is the only component surviving from a dot product with the axis */
+ VecRotToQuat(cross,saacos(state.vel[axis]),state.rot);
}
+
}
else{
state.time=-1.0;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 5bf9335d211..6ab8d72aa6d 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -81,6 +81,10 @@
static void key_from_object(Object *ob, ParticleKey *key);
static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index,
float *fuv, float *orco, ParticleTexture *ptex, int event);
+static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
+ ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
+static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part,
+ ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t);
/* few helpers for countall etc. */
int count_particles(ParticleSystem *psys){
@@ -452,7 +456,7 @@ void psys_free(Object *ob, ParticleSystem * psys)
for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){
if(tpsys->part)
{
- if(ELEM(tpsys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
+ if(ELEM(tpsys->part->ren_as,PART_DRAW_OB,PART_DRAW_GR))
{
nr++;
break;
@@ -491,6 +495,7 @@ typedef struct ParticleRenderData {
ChildParticle *child;
ParticleCacheKey **pathcache;
ParticleCacheKey **childcache;
+ ListBase pathcachebufs, childcachebufs;
int totchild, totcached, totchildcache;
DerivedMesh *dm;
int totdmvert, totdmedge, totdmface;
@@ -577,8 +582,12 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
data->child= psys->child;
data->totchild= psys->totchild;
data->pathcache= psys->pathcache;
+ data->pathcachebufs.first = psys->pathcachebufs.first;
+ data->pathcachebufs.last = psys->pathcachebufs.last;
data->totcached= psys->totcached;
data->childcache= psys->childcache;
+ data->childcachebufs.first = psys->childcachebufs.first;
+ data->childcachebufs.last = psys->childcachebufs.last;
data->totchildcache= psys->totchildcache;
if(psmd->dm)
@@ -591,6 +600,8 @@ void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float
psys->pathcache= NULL;
psys->childcache= NULL;
psys->totchild= psys->totcached= psys->totchildcache= 0;
+ psys->pathcachebufs.first = psys->pathcachebufs.last = NULL;
+ psys->childcachebufs.first = psys->childcachebufs.last = NULL;
Mat4CpyMat4(data->winmat, winmat);
Mat4MulMat4(data->viewmat, ob->obmat, viewmat);
@@ -631,8 +642,12 @@ void psys_render_restore(Object *ob, ParticleSystem *psys)
psys->child= data->child;
psys->totchild= data->totchild;
psys->pathcache= data->pathcache;
+ psys->pathcachebufs.first = data->pathcachebufs.first;
+ psys->pathcachebufs.last = data->pathcachebufs.last;
psys->totcached= data->totcached;
psys->childcache= data->childcache;
+ psys->childcachebufs.first = data->childcachebufs.first;
+ psys->childcachebufs.last = data->childcachebufs.last;
psys->totchildcache= data->totchildcache;
psmd->dm= data->dm;
@@ -663,7 +678,7 @@ int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
int *origindex, *facetotvert;
int a, b, totorigface, totface, newtot, skipped;
- if(part->draw_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
+ if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
return tot;
if(!ctx->psys->renderdata)
return tot;
@@ -1992,11 +2007,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
ParticleData *pa=NULL;
ParticleTexture ptex;
float *cpa_fuv=0, *par_rot=0;
- float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3];
+ float co[3], orco[3], ornor[3], t, cpa_1st[3], dvec[3];
float branch_begin, branch_end, branch_prob, branchfac, rough_rand;
- float pa_rough1, pa_rough2, pa_roughe;
- float length, pa_length, pa_clump, pa_kink, pa_effector;
- float max_length = 1.0f, cur_length = 0.0f;
+ float length, max_length = 1.0f, cur_length = 0.0f;
float eff_length, eff_vec[3];
int k, cpa_num, guided = 0;
short cpa_from;
@@ -2059,9 +2072,11 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0);
- /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
- VECCOPY(cpa_1st,co);
- Mat4MulVecfl(ob->obmat,cpa_1st);
+ if(part->path_start==0.0f) {
+ /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
+ VECCOPY(cpa_1st,co);
+ Mat4MulVecfl(ob->obmat,cpa_1st);
+ }
pa=0;
}
@@ -2098,43 +2113,13 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
#endif // XXX old animation system
/* get different child parameters from textures & vgroups */
- ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]);
- ptex.clump=1.0;
- ptex.kink=1.0;
- ptex.rough= 1.0;
- ptex.exist= 1.0;
-
- get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,&ptex,
- MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH);
-
- pa_length=ptex.length;
- pa_clump=ptex.clump;
- pa_kink=ptex.kink;
- pa_rough1=ptex.rough;
- pa_rough2=ptex.rough;
- pa_roughe=ptex.rough;
- pa_effector= 1.0f;
+ get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
if(ptex.exist < cpa->rand[1]) {
keys->steps = -1;
return;
}
- if(ctx->vg_length)
- pa_length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length);
- if(ctx->vg_clump)
- pa_clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump);
- if(ctx->vg_kink)
- pa_kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink);
- if(ctx->vg_rough1)
- pa_rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1);
- if(ctx->vg_rough2)
- pa_rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2);
- if(ctx->vg_roughe)
- pa_roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe);
- if(ctx->vg_effector)
- pa_effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector);
-
/* create the child path */
for(k=0,state=keys; k<=ctx->steps; k++,state++){
if(ctx->between){
@@ -2158,12 +2143,14 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
key[w]++;
w++;
}
- if(k==0){
- /* calculate the offset between actual child root position and first position interpolated from parents */
- VECSUB(cpa_1st,cpa_1st,state->co);
+ if(part->path_start==0.0f) {
+ if(k==0){
+ /* calculate the offset between actual child root position and first position interpolated from parents */
+ VECSUB(cpa_1st,cpa_1st,state->co);
+ }
+ /* apply offset for correct positioning */
+ VECADD(state->co,state->co,cpa_1st);
}
- /* apply offset for correct positioning */
- VECADD(state->co,state->co,cpa_1st);
}
else{
/* offset the child from the parent position */
@@ -2177,7 +2164,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
if(part->flag & PART_CHILD_EFFECT) {
for(k=0,state=keys; k<=ctx->steps; k++,state++) {
if(k) {
- do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, pa_effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
+ do_path_effectors(ctx->scene, ob, psys, cpa->pa[0], state, k, ctx->steps, keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
}
else {
VecSubf(eff_vec,(state+1)->co,state->co);
@@ -2203,67 +2190,50 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
}
/* apply different deformations to the child path */
- if(part->flag & PART_CHILD_EFFECT)
- /* state is safe to cast, since only co and vel are used */
- guided = do_guide(ctx->scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors));
-
- if(guided==0){
- if(part->kink)
- do_prekink((ParticleKey*)state, (ParticleKey*)par, par_rot, t,
- part->kink_freq * pa_kink, part->kink_shape, part->kink_amp, part->kink, part->kink_axis, ob->obmat);
-
- do_clump((ParticleKey*)state, (ParticleKey*)par, t, part->clumpfac, part->clumppow, pa_clump);
- }
-
- if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
- rough_t = t * rough_rand;
- else
- rough_t = t;
+ do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, (ParticleKey *)state, t);
- if(part->rough1 != 0.0 && pa_rough1 != 0.0)
- do_rough(orco, rough_t, pa_rough1*part->rough1, part->rough1_size, 0.0, (ParticleKey*)state);
-
- if(part->rough2 != 0.0 && pa_rough2 != 0.0)
- do_rough(cpa->rand, rough_t, pa_rough2*part->rough2, part->rough2_size, part->rough2_thres, (ParticleKey*)state);
-
- if(part->rough_end != 0.0 && pa_roughe != 0.0)
- do_rough_end(cpa->rand, rough_t, pa_roughe*part->rough_end, part->rough_end_shape, (ParticleKey*)state, (ParticleKey*)par);
-
- if(part->flag & PART_BRANCHING && ctx->between==0){
- if(branch_prob > part->branch_thres){
- branchfac=0.0f;
- }
- else{
- if(part->flag & PART_SYMM_BRANCHING){
- if(t < branch_begin || t > branch_end)
- branchfac=0.0f;
- else{
- if((t-branch_begin)/(branch_end-branch_begin)<0.5)
- branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin);
- else
- branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin);
+ /* TODO: better branching */
+ //if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
+ // rough_t = t * rough_rand;
+ //else
+ // rough_t = t;
- CLAMP(branchfac,0.0f,1.0f);
- }
- }
- else{
- if(t < branch_begin){
- branchfac=0.0f;
- }
- else{
- branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f);
- CLAMP(branchfac,0.0f,1.0f);
- }
- }
- }
+ /* TODO: better branching */
+ //if(part->flag & PART_BRANCHING && ctx->between==0){
+ // if(branch_prob > part->branch_thres){
+ // branchfac=0.0f;
+ // }
+ // else{
+ // if(part->flag & PART_SYMM_BRANCHING){
+ // if(t < branch_begin || t > branch_end)
+ // branchfac=0.0f;
+ // else{
+ // if((t-branch_begin)/(branch_end-branch_begin)<0.5)
+ // branchfac=2.0f*(t-branch_begin)/(branch_end-branch_begin);
+ // else
+ // branchfac=2.0f*(branch_end-t)/(branch_end-branch_begin);
+
+ // CLAMP(branchfac,0.0f,1.0f);
+ // }
+ // }
+ // else{
+ // if(t < branch_begin){
+ // branchfac=0.0f;
+ // }
+ // else{
+ // branchfac=(t-branch_begin)/((1.0f-branch_begin)*0.5f);
+ // CLAMP(branchfac,0.0f,1.0f);
+ // }
+ // }
+ // }
- if(i<psys->totpart)
- VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac);
- else
- /* this is not threadsafe, but should only happen for
- * branching particles particles, which are not threaded */
- VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac);
- }
+ // if(i<psys->totpart)
+ // VecLerpf(state->co, (pcache[i] + k)->co, state->co, branchfac);
+ // else
+ // /* this is not threadsafe, but should only happen for
+ // * branching particles particles, which are not threaded */
+ // VecLerpf(state->co, (cache[i - psys->totpart] + k)->co, state->co, branchfac);
+ //}
/* we have to correct velocity because of kink & clump */
if(k>1){
@@ -2287,9 +2257,9 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
else{
/* initialize length calculation */
if(part->flag&PART_ABS_LENGTH)
- max_length= part->abslength*pa_length;
+ max_length= part->abslength*ptex.length;
else
- max_length= pa_length;
+ max_length= ptex.length;
cur_length= 0.0f;
}
@@ -2383,7 +2353,36 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa
psys_threads_free(pthreads);
}
+static void get_pointcache_keys_for_time(ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2)
+{
+ PointCache *cache = psys->pointcache;
+ static PTCacheMem *pm = NULL;
+
+ if(cache->flag & PTCACHE_DISK_CACHE) {
+ /* TODO */
+ }
+ else {
+ if(index < 0) { /* initialize */
+ pm = cache->mem_cache.first;
+ if(pm)
+ pm = pm->next;
+ }
+ else {
+ if(pm) {
+ while(pm && pm->next && (float)pm->frame < t)
+ pm = pm->next;
+ copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
+ copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1);
+ }
+ else if(cache->mem_cache.first) {
+ pm = cache->mem_cache.first;
+ copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
+ copy_particle_key(key1, ((ParticleKey *)pm->data) + index, 1);
+ }
+ }
+ }
+}
/* Calculates paths ready for drawing/rendering. */
/* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */
/* -Makes child strands possible and creates them too into the cache. */
@@ -2409,7 +2408,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
float birthtime = 0.0, dietime = 0.0;
float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec;
- float col[3] = {0.5f, 0.5f, 0.5f};
+ float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
float prev_tangent[3], hairmat[4][4];
int k,i;
int steps = (int)pow(2.0, (double)psys->part->draw_step);
@@ -2419,12 +2418,17 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
float length, vec[3];
float *vg_effector= NULL, effector=0.0f;
float *vg_length= NULL, pa_length=1.0f, max_length=1.0f, cur_length=0.0f;
- float len, dvec[3];
+ int keyed, baked;
/* we don't have anything valid to create paths from so let's quit here */
- if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0)
+ if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0 && (psys->pointcache->flag & PTCACHE_BAKED)==0)
return;
+ BLI_srandom(psys->seed);
+
+ keyed = psys->flag & PSYS_KEYED;
+ baked = psys->pointcache->flag & PTCACHE_BAKED;
+
if(psys->renderdata) {
steps = (int)pow(2.0, (double)psys->part->ren_step);
}
@@ -2488,7 +2492,8 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
else memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
if(!edit && !psys->totchild) {
- pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]);
+ //pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]);
+ pa_length = 1.0f - part->randlength * 0.5 * (1.0f + pa->r_ave[0]);
if(vg_length)
pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length);
}
@@ -2499,13 +2504,19 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
ekey = edit->keys[i];
/*--get the first data points--*/
- if(psys->flag & PSYS_KEYED) {
+ if(keyed) {
kkey[0] = pa->keys;
kkey[1] = kkey[0] + 1;
birthtime = kkey[0]->time;
dietime = kkey[0][pa->totkey-1].time;
}
+ else if(baked) {
+ get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL);
+
+ birthtime = pa->time;
+ dietime = pa->dietime;
+ }
else {
hkey[0] = pa->hair;
hkey[1] = hkey[0] + 1;
@@ -2516,6 +2527,25 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
}
+ if(!edit) {
+ if(part->draw & PART_ABS_PATH_TIME) {
+ birthtime = MAX2(birthtime, part->path_start);
+ dietime = MIN2(dietime, part->path_end);
+ }
+ else {
+ float tb = birthtime;
+ birthtime = tb + part->path_start * (dietime - tb);
+ dietime = tb + part->path_end * (dietime - tb);
+ }
+
+ if(birthtime >= dietime) {
+ cache[i]->steps = -1;
+ continue;
+ }
+
+ dietime = birthtime + pa_length * (dietime - birthtime);
+ }
+
if(soft){
bp[0] = soft->bpoint + pa->bpi;
bp[1] = bp[0] + 1;
@@ -2527,13 +2557,16 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
t = birthtime + time * (dietime - birthtime);
- if(psys->flag & PSYS_KEYED) {
+ if(keyed) {
while(kkey[1]->time < t) {
kkey[1]++;
}
kkey[0] = kkey[1] - 1;
}
+ else if(baked) {
+ get_pointcache_keys_for_time(psys, i, t, keys+1, keys+2);
+ }
else {
while(hkey[1]->time < t) {
hkey[1]++;
@@ -2548,17 +2581,19 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
bp_to_particle(keys + 1, bp[0], hkey[0]);
bp_to_particle(keys + 2, bp[1], hkey[1]);
}
- else if(psys->flag & PSYS_KEYED) {
+ else if(keyed) {
memcpy(keys + 1, kkey[0], sizeof(ParticleKey));
memcpy(keys + 2, kkey[1], sizeof(ParticleKey));
}
+ else if(baked)
+ ; /* keys already set */
else {
hair_to_particle(keys + 1, hkey[0]);
hair_to_particle(keys + 2, hkey[1]);
}
- if((psys->flag & PSYS_KEYED)==0) {
+ if(!keyed && !baked) {
if(soft) {
if(hkey[0] != pa->hair)
bp_to_particle(keys, bp[0] - 1, hkey[0] - 1);
@@ -2591,18 +2626,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
keytime = (t - keys[1].time) / dfra;
/* convert velocity to timestep size */
- if(psys->flag & PSYS_KEYED){
+ if(keyed || baked){
VecMulf(keys[1].vel, dfra / frs_sec);
VecMulf(keys[2].vel, dfra / frs_sec);
}
/* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/
- psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
+ psys_interpolate_particle((keyed || baked) ? -1 /* signal for cubic interpolation */
: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
,keys, keytime, &result, 0);
/* the velocity needs to be converted back from cubic interpolation */
- if(psys->flag & PSYS_KEYED){
+ if(keyed || baked){
VecMulf(result.vel, frs_sec / dfra);
}
else if(soft==NULL) { /* softbody and keyed are allready in global space */
@@ -2717,28 +2752,6 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
}
}
-
- if(!edit && !psys->totchild) {
- /* check if path needs to be cut before actual end of data points */
- if(k){
- VECSUB(dvec,ca->co,(ca-1)->co);
- if(part->flag&PART_ABS_LENGTH)
- len=VecLength(dvec);
- else
- len=1.0f/(float)steps;
-
- k=check_path_length(k,cache[i],ca,max_length,&cur_length,len,dvec);
- }
- else{
- /* initialize length calculation */
- if(part->flag&PART_ABS_LENGTH)
- max_length= part->abslength*pa_length;
- else
- max_length= pa_length;
-
- cur_length= 0.0f;
- }
- }
}
}
@@ -2990,7 +3003,8 @@ static void default_particle_settings(ParticleSettings *part)
part->type= PART_EMITTER;
part->distr= PART_DISTR_JIT;
- part->draw_as=PART_DRAW_DOT;
+ part->draw_as = PART_DRAW_REND;
+ part->ren_as = PART_DRAW_HALO;
part->bb_uv_split=1;
part->bb_align=PART_BB_VIEW;
part->bb_split_offset=PART_BB_OFF_LINEAR;
@@ -3046,6 +3060,8 @@ static void default_particle_settings(ParticleSettings *part)
part->rough_end_shape=1.0;
part->draw_line[0]=0.5;
+ part->path_start = 0.0f;
+ part->path_end = 1.0f;
part->banking=1.0;
part->max_bank=1.0;
@@ -3282,7 +3298,7 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float
if((event & mtex->pmapto) & MAP_PA_KINK)
ptex->kink= texture_value_blend(def,ptex->kink,value,var,blend,neg & MAP_PA_KINK);
if((event & mtex->pmapto) & MAP_PA_ROUGH)
- ptex->rough= texture_value_blend(def,ptex->rough,value,var,blend,neg & MAP_PA_ROUGH);
+ ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,var,blend,neg & MAP_PA_ROUGH);
if((event & mtex->pmapto) & MAP_PA_DENS)
ptex->exist= texture_value_blend(def,ptex->exist,value,var,blend,neg & MAP_PA_DENS);
}
@@ -3291,7 +3307,11 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index, float
if(event & MAP_PA_LENGTH) { CLAMP(ptex->length,0.0,1.0); }
if(event & MAP_PA_CLUMP) { CLAMP(ptex->clump,0.0,1.0); }
if(event & MAP_PA_KINK) { CLAMP(ptex->kink,0.0,1.0); }
- if(event & MAP_PA_ROUGH) { CLAMP(ptex->rough,0.0,1.0); }
+ if(event & MAP_PA_ROUGH) {
+ CLAMP(ptex->rough1,0.0,1.0);
+ CLAMP(ptex->rough2,0.0,1.0);
+ CLAMP(ptex->roughe,0.0,1.0);
+ }
if(event & MAP_PA_DENS) { CLAMP(ptex->exist,0.0,1.0); }
}
void psys_get_texture(Object *ob, Material *ma, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleData *pa, ParticleTexture *ptex, int event)
@@ -3392,12 +3412,12 @@ float psys_get_size(Object *ob, Material *ma, ParticleSystemModifierData *psmd,
return size*part->size;
}
-float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra)
+float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
{
ParticleSettings *part = psys->part;
+ float time, life;
if(part->childtype==PART_CHILD_FACES){
- float time;
int w=0;
time=0.0;
while(w<4 && cpa->pa[w]>=0){
@@ -3405,12 +3425,21 @@ float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra)
w++;
}
- return (cfra-time)/(part->lifetime*(1.0f-part->randlife*cpa->rand[1]));
+ life = part->lifetime*(1.0f-part->randlife*cpa->rand[1]);
}
else{
ParticleData *pa = psys->particles + cpa->parent;
- return (cfra-pa->time)/pa->lifetime;
+
+ time = pa->time;
+ life = pa->lifetime;
}
+
+ if(birthtime)
+ *birthtime = time;
+ if(dietime)
+ *dietime = time+life;
+
+ return (cfra-time)/life;
}
float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *pa_time)
{
@@ -3427,7 +3456,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra,
if(pa_time)
time=*pa_time;
else
- time=psys_get_child_time(psys,cpa,cfra);
+ time=psys_get_child_time(psys,cpa,cfra,NULL,NULL);
/* correction for lifetime */
calc_ipo(part->ipo, 100*time);
@@ -3449,6 +3478,64 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra,
return size;
}
+static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
+{
+ ptex->length=part->length*(1.0f - part->randlength*cpa->rand[0]);
+ ptex->clump=1.0;
+ ptex->kink=1.0;
+ ptex->rough1= 1.0;
+ ptex->rough2= 1.0;
+ ptex->roughe= 1.0;
+ ptex->exist= 1.0;
+ ptex->effector= 1.0;
+
+ get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex,
+ MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH);
+
+
+ if(ptex->exist < cpa->rand[1])
+ return;
+
+ if(ctx->vg_length)
+ ptex->length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length);
+ if(ctx->vg_clump)
+ ptex->clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump);
+ if(ctx->vg_kink)
+ ptex->kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink);
+ if(ctx->vg_rough1)
+ ptex->rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1);
+ if(ctx->vg_rough2)
+ ptex->rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2);
+ if(ctx->vg_roughe)
+ ptex->roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe);
+ if(ctx->vg_effector)
+ ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector);
+}
+static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t)
+{
+ int guided = 0;
+
+ if(part->flag & PART_CHILD_EFFECT)
+ /* state is safe to cast, since only co and vel are used */
+ guided = do_guide(scene, (ParticleKey*)state, cpa->parent, t, &(psys->effectors));
+
+ if(guided==0){
+ if(part->kink)
+ do_prekink(state, par, par_rot, t, part->kink_freq * ptex->kink, part->kink_shape,
+ part->kink_amp, part->kink, part->kink_axis, ob->obmat);
+
+ do_clump(state, par, t, part->clumpfac, part->clumppow, ptex->clump);
+ }
+
+ if(part->rough1 != 0.0 && ptex->rough1 != 0.0)
+ do_rough(orco, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state);
+
+ if(part->rough2 != 0.0 && ptex->rough2 != 0.0)
+ do_rough(cpa->rand, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state);
+
+ if(part->rough_end != 0.0 && ptex->roughe != 0.0)
+ do_rough_end(cpa->rand, t, ptex->roughe*part->rough_end, part->rough_end_shape, state, par);
+}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel)
{
@@ -3460,7 +3547,8 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
ParticleTexture ptex;
ParticleKey *kkey[2] = {NULL, NULL};
HairKey *hkey[2] = {NULL, NULL};
- ParticleKey *par=0, keys[4];
+ ParticleKey *par=0, keys[4], tstate;
+ ParticleThreadContext ctx; /* fake thread context for child modifiers */
float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec;
float co[3], orco[3];
@@ -3471,6 +3559,9 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
int totchild = psys->totchild;
short between = 0, edit = 0;
+ int keyed = psys->flag & PSYS_KEYED;
+ int cached = !keyed && part->type != PART_HAIR;
+
float *cpa_fuv; int cpa_num; short cpa_from;
//if(psys_in_edit_mode(scene, psys)){
@@ -3479,12 +3570,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
// edit=1;
//}
- /* user want's cubic interpolation but only without sb it possible */
- //if(interpolation==PART_INTER_CUBIC && baked && psys->softflag==OB_SB_ENABLE)
- // interpolation=PART_INTER_BSPLINE;
- //else if(baked==0) /* it doesn't make sense to use other types for keyed */
- // interpolation=PART_INTER_CUBIC;
-
t=state->time;
CLAMP(t, 0.0, 1.0);
@@ -3497,20 +3582,29 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
return;
}
- if(psys->flag & PSYS_KEYED) {
+ if(keyed) {
kkey[0] = pa->keys;
kkey[1] = kkey[0] + 1;
- real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time);
+ if(state->time < 0.0f)
+ real_t = -state->time;
+ else
+ real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time);
+ }
+ else if(cached) {
+ get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL);
}
else {
hkey[0] = pa->hair;
hkey[1] = pa->hair + 1;
- real_t = hkey[0]->time + (hkey[0][pa->totkey-1].time - hkey[0]->time) * t;
+ if(state->time < 0.0f)
+ real_t = -state->time;
+ else
+ real_t = hkey[0]->time + t * (hkey[0][pa->totkey-1].time - hkey[0]->time);
}
- if(psys->flag & PSYS_KEYED) {
+ if(keyed) {
while(kkey[1]->time < real_t) {
kkey[1]++;
}
@@ -3519,6 +3613,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
memcpy(keys + 1, kkey[0], sizeof(ParticleKey));
memcpy(keys + 2, kkey[1], sizeof(ParticleKey));
}
+ else if(cached) {
+ if(state->time < 0.0f) /* flag for time in frames */
+ real_t = -state->time;
+ else
+ real_t = pa->time + t * (pa->dietime - pa->time);
+
+ get_pointcache_keys_for_time(psys, p, real_t, keys+1, keys+2);
+ }
else {
while(hkey[1]->time < real_t)
hkey[1]++;
@@ -3529,63 +3631,35 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
hair_to_particle(keys + 2, hkey[1]);
}
- if((psys->flag & PSYS_KEYED)==0) {
- //if(soft){
- // if(key[0] != sbel.keys)
- // DB_copy_key(&k1,key[0]-1);
- // else
- // DB_copy_key(&k1,&k2);
- //}
- //else{
+ if(!keyed && !cached) {
if(hkey[0] != pa->hair)
hair_to_particle(keys, hkey[0] - 1);
else
hair_to_particle(keys, hkey[0]);
- //}
- //if(soft){
- // if(key[1] != sbel.keys + sbel.totkey-1)
- // DB_copy_key(&k4,key[1]+1);
- // else
- // DB_copy_key(&k4,&k3);
- //}
- //else {
if(hkey[1] != pa->hair + pa->totkey - 1)
hair_to_particle(keys + 3, hkey[1] + 1);
else
hair_to_particle(keys + 3, hkey[1]);
}
- //}
-
- //psys_get_particle_on_path(scene, bsys,p,t,bkey,ckey[0]);
-
- //if(part->rotfrom==PART_ROT_KEYS)
- // QuatInterpol(state->rot,k2.rot,k3.rot,keytime);
- //else{
- // /* TODO: different rotations */
- // float nvel[3];
- // VECCOPY(nvel,state->vel);
- // VecMulf(nvel,-1.0f);
- // vectoquat(nvel, OB_POSX, OB_POSZ, state->rot);
- //}
dfra = keys[2].time - keys[1].time;
keytime = (real_t - keys[1].time) / dfra;
/* convert velocity to timestep size */
- if(psys->flag & PSYS_KEYED){
+ if(keyed || cached){
VecMulf(keys[1].vel, dfra / frs_sec);
VecMulf(keys[2].vel, dfra / frs_sec);
QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime);
}
- psys_interpolate_particle((psys->flag & PSYS_KEYED) ? -1 /* signal for cubic interpolation */
+ psys_interpolate_particle((keyed || cached) ? -1 /* signal for cubic interpolation */
: ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
,keys, keytime, state, 1);
/* the velocity needs to be converted back from cubic interpolation */
- if(psys->flag & PSYS_KEYED){
+ if(keyed || cached){
VecMulf(state->vel, frs_sec / dfra);
}
else {
@@ -3606,8 +3680,11 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
}
else if(totchild){
//Mat4Invert(imat,ob->obmat);
-
+
cpa=psys->child+p-totpart;
+
+ if(state->time < 0.0f)
+ t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
totparent=(int)(totchild*part->parents*0.3);
@@ -3624,7 +3701,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
/* get parent states */
while(w<4 && cpa->pa[w]>=0){
- keys[w].time = t;
+ keys[w].time = state->time;
psys_get_particle_on_path(scene, ob, psys, cpa->pa[w], keys+w, 1);
w++;
}
@@ -3650,7 +3727,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
else{
/* get the parent state */
- keys->time = t;
+ keys->time = state->time;
psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1);
/* get the original coordinates (orco) for texture usage */
@@ -3672,15 +3749,11 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
#endif // XXX old animation system
/* get different child parameters from textures & vgroups */
- ptex.clump=1.0;
- ptex.kink=1.0;
-
- get_cpa_texture(psmd->dm,ma,cpa_num,cpa_fuv,orco,&ptex,MAP_PA_CLUMP|MAP_PA_KINK);
-
- pa_clump=ptex.clump;
- pa_kink=ptex.kink;
-
- /* TODO: vertex groups */
+ memset(&ctx, 0, sizeof(ParticleThreadContext));
+ ctx.dm = psmd->dm;
+ ctx.ma = ma;
+ /* TODO: assign vertex groups */
+ get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
if(between){
int w=0;
@@ -3708,46 +3781,34 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
}
par = keys;
- //if(totparent){
- // if(p-totpart>=totparent){
- // key.time=t;
- // psys_get_particle_on_path(ob,psys,totpart+cpa->parent,&key,1);
- // bti->convert_dynamic_key(bsys,&key,par,cpar);
- // }
- // else
- // par=0;
- //}
- //else
- // DB_get_key_on_path(bsys,cpa->parent,t,par,cpar);
-
- /* apply different deformations to the child path */
- if(part->kink)
- do_prekink(state, par, par->rot, t, part->kink_freq * pa_kink, part->kink_shape,
- part->kink_amp, part->kink, part->kink_axis, ob->obmat);
-
- do_clump(state, par, t, part->clumpfac, part->clumppow, 1.0f);
-
- if(part->rough1 != 0.0)
- do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state);
- if(part->rough2 != 0.0)
- do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state);
+ if(vel)
+ copy_particle_key(&tstate, state, 1);
- if(part->rough_end != 0.0)
- do_rough_end(cpa->rand, t, part->rough_end, part->rough_end_shape, state, par);
+ /* apply different deformations to the child path */
+ do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, state, t);
+
+ /* try to estimate correct velocity */
+ if(vel){
+ ParticleKey tstate;
+ float length = VecLength(state->vel);
+
+ if(t>=0.001f){
+ tstate.time=t-0.001f;
+ psys_get_particle_on_path(scene,ob,psys,p,&tstate,0);
+ VECSUB(state->vel,state->co,tstate.co);
+ Normalize(state->vel);
+ }
+ else{
+ float length = VecLength(state->vel);
+ tstate.time=t+0.001f;
+ psys_get_particle_on_path(scene, ob,psys,p,&tstate,0);
+ VECSUB(state->vel,tstate.co,state->co);
+ Normalize(state->vel);
+ }
- //if(vel){
- // if(t>=0.001f){
- // tstate.time=t-0.001f;
- // psys_get_particle_on_path(scene,ob,psys,p,&tstate,0);
- // VECSUB(state->vel,state->co,tstate.co);
- // }
- // else{
- // tstate.time=t+0.001f;
- // psys_get_particle_on_path(scene, ob,psys,p,&tstate,0);
- // VECSUB(state->vel,tstate.co,state->co);
- // }
- //}
+ VecMulf(state->vel, length);
+ }
}
}
/* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
@@ -3774,7 +3835,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
pa=psys->particles+p;
if(between){
- state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra);
+ state->time = psys_get_child_time(psys,&psys->child[p-totpart],cfra,NULL,NULL);
if(always==0)
if((state->time<0.0 && (part->flag & PART_UNBORN)==0)
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 591b6ca9be5..92b919f6b0e 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -4254,7 +4254,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif
}
}
- if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR
+ if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR
|| (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){
psys_cache_paths(scene, ob, psys, cfra, 0);
@@ -4371,8 +4371,10 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
dietime = birthtime + (1 + pa->loop) * (pa->dietime - pa->time);
/* update alive status and push events */
- if(pa->time > cfra)
+ if(pa->time > cfra) {
pa->alive = PARS_UNBORN;
+ reset_particle(scene, pa, psys, psmd, ob, 0.0f, cfra, NULL, NULL, NULL);
+ }
else if(dietime <= cfra){
if(dietime > psys->cfra){
state.time = dietime;
@@ -4406,6 +4408,8 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
distribute_particles(scene, ob, psys, PART_FROM_CHILD);
}
+ psys_update_path_cache(scene, ob,psmd,psys,cfra);
+
if(vg_size)
MEM_freeN(vg_size);
}
@@ -4433,10 +4437,17 @@ void psys_changed_type(ParticleSystem *psys)
if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
part->draw_as = PART_DRAW_REND;
+
+ CLAMP(part->path_start, 0.0f, 100.0f);
+ CLAMP(part->path_end, 0.0f, 100.0f);
}
- else
+ else {
free_hair(psys, 1);
+ CLAMP(part->path_start, part->sta, part->end + part->lifetime);
+ CLAMP(part->path_end, part->sta, part->end + part->lifetime);
+ }
+
psys->softflag= 0;
psys_reset(psys, PSYS_RESET_ALL);
@@ -4629,9 +4640,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
totpart = psys->part->totpart;
totchild = get_psys_tot_child(scene, psys);
- if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) {
+ if(oldtotpart != totpart || oldtotchild != totchild) {
only_children_changed = (oldtotpart == totpart);
- realloc_particles(ob, psys, totpart);
alloc = 1;
distr= 1;
init= 1;
@@ -4647,11 +4657,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
if(alloc) {
realloc_particles(ob, psys, totpart);
- if(usecache)
+ if(usecache && !only_children_changed)
BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
}
- distribute_particles(scene, ob, psys, part->from);
+ if(!only_children_changed)
+ distribute_particles(scene, ob, psys, part->from);
if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE))
/* don't generate children while growing hair - waste of time */
@@ -4660,7 +4671,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
distribute_particles(scene, ob, psys, PART_FROM_CHILD);
}
- if(only_children_changed==0) {
+ if(!only_children_changed) {
free_keyed_keys(psys);
initialize_all_particles(ob, psys, psmd);
@@ -4680,19 +4691,10 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
- //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
- // psys_count_keyed_targets(ob,psys);
- // set_keyed_keys(scene, ob, psys);
- //}
-
cached_step(scene, ob, psmd, psys, cfra);
psys->cfra=cfra;
psys->recalc = 0;
- //if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
- // psys_update_path_cache(scene, ob, psmd, psys, framenr);
- //}
-
cache->simframe= framenr;
cache->flag |= PTCACHE_SIMULATION_VALID;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 64473d07151..b8a0b111324 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1209,8 +1209,13 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
for(pid=pidlist.first; pid; pid=pid->next) {
cache = pid->cache;
if((cache->flag & PTCACHE_BAKED)==0) {
- if(pid->type==PTCACHE_TYPE_PARTICLES)
+ if(pid->type==PTCACHE_TYPE_PARTICLES) {
+ /* skip hair particles */
+ if(((ParticleSystem*)pid->data)->part->type == PART_HAIR)
+ continue;
+
psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
+ }
if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
&& ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
@@ -1265,6 +1270,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
BKE_ptcache_ids_from_object(&pidlist, base->object);
for(pid=pidlist.first; pid; pid=pid->next) {
+ /* skip hair particles */
+ if(pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->data)->part->type == PART_HAIR)
+ continue;
+
cache = pid->cache;
if(step > 1)
@@ -1282,7 +1291,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
scene->r.framelen = frameleno;
CFRA = cfrao;
- scene_update_for_newframe(scene, scene->lay);
+
+ if(bake) /* already on cfra unless baking */
+ scene_update_for_newframe(scene, scene->lay);
/* TODO: call redraw all windows somehow */
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index c89f515f319..93de096e7b4 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -9059,6 +9059,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
part->draw_as = PART_DRAW_REND;
}
}
+ part->path_end = 1.0f;
}
/* set old pointcaches to have disk cache flag */
for(ob = main->object.first; ob; ob= ob->id.next) {
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index d9bc2d4d426..1ce352444e6 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -487,7 +487,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, i
ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
if(!(G.f & G_PARTICLEEDIT))
- if(ELEM3(psys->part->draw_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache)
+ if(ELEM3(psys->part->ren_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache)
uiItemO(row, "Convert", 0, "OBJECT_OT_modifier_convert");
}
else
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 8bdfaeb6519..eb723dcca6c 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -226,11 +226,11 @@ int ED_object_modifier_convert(ReportList *reports, Scene *scene, Object *ob, Mo
psys=((ParticleSystemModifierData *)md)->psys;
part= psys->part;
- if(part->draw_as == PART_DRAW_GR || part->draw_as == PART_DRAW_OB) {
+ if(part->ren_as == PART_DRAW_GR || part->ren_as == PART_DRAW_OB) {
; // XXX make_object_duplilist_real(NULL);
}
else {
- if(part->draw_as != PART_DRAW_PATH || psys->pathcache == 0)
+ if(part->ren_as != PART_DRAW_PATH || psys->pathcache == 0)
return 0;
totpart= psys->totcached;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 05490e2fce1..b38575b5ceb 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -2941,6 +2941,228 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
return retval;
}
+/* *********** text drawing for particles ************* */
+static ListBase pstrings= {NULL, NULL};
+
+typedef struct ViewParticleString {
+ struct ViewParticleString *next, *prev;
+ float vec[3], col[4];
+ char str[128];
+ short mval[2];
+ short xoffs;
+} ViewParticleString;
+
+
+void view3d_particle_text_draw_add(float x, float y, float z, char *str, short xoffs)
+{
+ ViewObjectString *vos= MEM_callocN(sizeof(ViewObjectString), "ViewObjectString");
+
+ BLI_addtail(&pstrings, vos);
+ BLI_strncpy(vos->str, str, 128);
+ vos->vec[0]= x;
+ vos->vec[1]= y;
+ vos->vec[2]= z;
+ glGetFloatv(GL_CURRENT_COLOR, vos->col);
+ vos->xoffs= xoffs;
+}
+
+static void view3d_particle_text_draw(View3D *v3d, ARegion *ar)
+{
+ ViewObjectString *vos;
+ int tot= 0;
+
+ /* project first and test */
+ for(vos= pstrings.first; vos; vos= vos->next) {
+ project_short(ar, vos->vec, vos->mval);
+ if(vos->mval[0]!=IS_CLIPPED)
+ tot++;
+ }
+
+ if(tot) {
+ RegionView3D *rv3d= ar->regiondata;
+ int a;
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ for(a=0; a<6; a++)
+ glDisable(GL_CLIP_PLANE0+a);
+
+ wmPushMatrix();
+ ED_region_pixelspace(ar);
+
+ if(v3d->zbuf) glDepthMask(0);
+
+ for(vos= pstrings.first; vos; vos= vos->next) {
+ if(vos->mval[0]!=IS_CLIPPED) {
+ glColor3fv(vos->col);
+ BLF_draw_default((float)vos->mval[0]+vos->xoffs, (float)vos->mval[1], 2.0, vos->str);
+ }
+ }
+
+ if(v3d->zbuf) glDepthMask(1);
+
+ wmPopMatrix();
+
+ if(rv3d->rflag & RV3D_CLIPPING)
+ for(a=0; a<6; a++)
+ glEnable(GL_CLIP_PLANE0+a);
+ }
+
+ if(pstrings.first)
+ BLI_freelistN(&pstrings);
+}
+typedef struct ParticleDrawData {
+ float *vdata, *vd;
+ float *ndata, *nd;
+ float *cdata, *cd;
+ float *vedata, *ved;
+ float *ma_r, *ma_g, *ma_b;
+} ParticleDrawData;
+static void draw_particle(ParticleKey *state, int draw_as, short draw, float pixsize, float imat[4][4], float *draw_line, ParticleBillboardData *bb, ParticleDrawData *pdd)
+{
+ float vec[3], vec2[3];
+ float *vd = pdd->vd;
+ float *nd = pdd->nd;
+ float *cd = pdd->cd;
+ float ma_r;
+ float ma_g;
+ float ma_b;
+
+ if(pdd->ma_r) {
+ ma_r = *pdd->ma_r;
+ ma_g = *pdd->ma_g;
+ ma_b = *pdd->ma_b;
+ }
+
+ switch(draw_as){
+ case PART_DRAW_DOT:
+ {
+ if(vd) {
+ VECCOPY(vd,state->co) pdd->vd+=3;
+ }
+ if(cd) {
+ cd[0]=ma_r;
+ cd[1]=ma_g;
+ cd[2]=ma_b;
+ pdd->cd+=3;
+ }
+ break;
+ }
+ case PART_DRAW_CROSS:
+ case PART_DRAW_AXIS:
+ {
+ vec[0]=2.0f*pixsize;
+ vec[1]=vec[2]=0.0;
+ QuatMulVecf(state->rot,vec);
+ if(draw_as==PART_DRAW_AXIS) {
+ cd[1]=cd[2]=cd[4]=cd[5]=0.0;
+ cd[0]=cd[3]=1.0;
+ cd[6]=cd[8]=cd[9]=cd[11]=0.0;
+ cd[7]=cd[10]=1.0;
+ cd[13]=cd[12]=cd[15]=cd[16]=0.0;
+ cd[14]=cd[17]=1.0;
+ cd+=18;
+
+ VECCOPY(vec2,state->co);
+ }
+ else {
+ if(cd) {
+ cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
+ cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
+ cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
+ pdd->cd+=18;
+ }
+ VECSUB(vec2,state->co,vec);
+ }
+
+ VECADD(vec,state->co,vec);
+ VECCOPY(pdd->vd,vec); pdd->vd+=3;
+ VECCOPY(pdd->vd,vec2); pdd->vd+=3;
+
+ vec[1]=2.0f*pixsize;
+ vec[0]=vec[2]=0.0;
+ QuatMulVecf(state->rot,vec);
+ if(draw_as==PART_DRAW_AXIS){
+ VECCOPY(vec2,state->co);
+ }
+ else VECSUB(vec2,state->co,vec);
+
+ VECADD(vec,state->co,vec);
+ VECCOPY(pdd->vd,vec); pdd->vd+=3;
+ VECCOPY(pdd->vd,vec2); pdd->vd+=3;
+
+ vec[2]=2.0f*pixsize;
+ vec[0]=vec[1]=0.0;
+ QuatMulVecf(state->rot,vec);
+ if(draw_as==PART_DRAW_AXIS){
+ VECCOPY(vec2,state->co);
+ }
+ else VECSUB(vec2,state->co,vec);
+
+ VECADD(vec,state->co,vec);
+
+ VECCOPY(pdd->vd,vec); pdd->vd+=3;
+ VECCOPY(pdd->vd,vec2); pdd->vd+=3;
+ break;
+ }
+ case PART_DRAW_LINE:
+ {
+ VECCOPY(vec,state->vel);
+ Normalize(vec);
+ if(draw & PART_DRAW_VEL_LENGTH)
+ VecMulf(vec,VecLength(state->vel));
+ VECADDFAC(pdd->vd,state->co,vec,-draw_line[0]); pdd->vd+=3;
+ VECADDFAC(pdd->vd,state->co,vec,draw_line[1]); pdd->vd+=3;
+ if(cd) {
+ cd[0]=cd[3]=ma_r;
+ cd[1]=cd[4]=ma_g;
+ cd[2]=cd[5]=ma_b;
+ pdd->cd+=6;
+ }
+ break;
+ }
+ case PART_DRAW_CIRC:
+ {
+ if(pdd->ma_r)
+ glColor3f(ma_r,ma_g,ma_b);
+ drawcircball(GL_LINE_LOOP, state->co, pixsize, imat);
+ break;
+ }
+ case PART_DRAW_BB:
+ {
+ float xvec[3], yvec[3], zvec[3], bb_center[3];
+ if(cd) {
+ cd[0]=cd[3]=cd[6]=cd[9]=ma_r;
+ cd[1]=cd[4]=cd[7]=cd[10]=ma_g;
+ cd[2]=cd[5]=cd[8]=cd[11]=ma_b;
+ pdd->cd+=12;
+ }
+
+
+ VECCOPY(bb->vec, state->co);
+ VECCOPY(bb->vel, state->vel);
+
+ psys_make_billboard(bb, xvec, yvec, zvec, bb_center);
+
+ VECADD(pdd->vd,bb_center,xvec);
+ VECADD(pdd->vd,pdd->vd,yvec); pdd->vd+=3;
+
+ VECSUB(pdd->vd,bb_center,xvec);
+ VECADD(pdd->vd,pdd->vd,yvec); pdd->vd+=3;
+
+ VECSUB(pdd->vd,bb_center,xvec);
+ VECSUB(pdd->vd,pdd->vd,yvec); pdd->vd+=3;
+
+ VECADD(pdd->vd,bb_center,xvec);
+ VECSUB(pdd->vd,pdd->vd,yvec); pdd->vd+=3;
+
+ VECCOPY(pdd->nd, zvec); pdd->nd+=3;
+ VECCOPY(pdd->nd, zvec); pdd->nd+=3;
+ VECCOPY(pdd->nd, zvec); pdd->nd+=3;
+ VECCOPY(pdd->nd, zvec); pdd->nd+=3;
+ break;
+ }
+ }
+}
/* unified drawing of all new particle systems draw types except dupli ob & group */
/* mostly tries to use vertex arrays for speed */
@@ -2951,7 +3173,7 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
/* 5. start filling the arrays */
/* 6. draw the arrays */
/* 7. clean up */
-static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, int dt)
+static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, ParticleSystem *psys, int ob_dt)
{
Object *ob=base->object;
ParticleSystemModifierData *psmd;
@@ -2959,14 +3181,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
ParticleData *pars, *pa;
ParticleKey state, *states=0;
ParticleBillboardData bb;
+ ParticleDrawData pdd;
Material *ma;
- float vel[3], vec[3], vec2[3], imat[4][4], bb_center[3];
- float timestep, pixsize=1.0, pa_size, pa_time, r_tilt;
+ float vel[3], imat[4][4];
+ float timestep, pixsize=1.0, pa_size, r_tilt, r_length;
+ float pa_time, pa_birthtime, pa_dietime;
float cfra= bsystem_time(scene, ob,(float)CFRA,0.0);
- float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3];
float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f;
- int a, totpart, totpoint=0, draw_as, totchild=0;
- int select=ob->flag&SELECT, create_cdata=0;
+ int a, totpart, totpoint=0, totve=0, drawn, draw_as, totchild=0;
+ int select=ob->flag&SELECT, create_cdata=0, need_v=0;
GLint polygonmode[2];
char val[32];
@@ -3015,13 +3238,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
else
totchild=psys->totchild*part->disp/100;
- ma= give_current_material(ob,part->omat);
+ memset(&pdd, 0, sizeof(ParticleDrawData));
- if(ma) {
- ma_r = ma->r;
- ma_g = ma->g;
- ma_b = ma->b;
- }
+ ma= give_current_material(ob,part->omat);
if(v3d->zbuf) glDepthMask(1);
@@ -3029,6 +3248,15 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
cpack(0xFFFFFF);
else if((ma) && (part->draw&PART_DRAW_MAT_COL)) {
glColor3f(ma->r,ma->g,ma->b);
+
+ ma_r = ma->r;
+ ma_g = ma->g;
+ ma_b = ma->b;
+
+ pdd.ma_r = &ma_r;
+ pdd.ma_g = &ma_g;
+ pdd.ma_b = &ma_b;
+
create_cdata = 1;
}
else
@@ -3038,8 +3266,6 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
timestep= psys_get_timestep(part);
- wmLoadMatrix(rv3d->viewmat);
-
if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) ) {
float mat[4][4];
Mat4MulMat4(mat, psys->imat, ob->obmat);
@@ -3119,6 +3345,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
break;
case PART_DRAW_PATH:
break;
+ case PART_DRAW_LINE:
+ need_v=1;
+ break;
}
if(part->draw & PART_DRAW_SIZE && part->draw_as!=PART_DRAW_CIRC){
Mat4CpyMat4(imat, rv3d->viewinv);
@@ -3129,40 +3358,45 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
/* 4. */
if(draw_as && draw_as!=PART_DRAW_PATH) {
int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
+
+ if(part->draw_as == PART_DRAW_REND && part->trail_count > 1)
+ tot_vec_size *= part->trail_count;
if(draw_as!=PART_DRAW_CIRC) {
switch(draw_as) {
case PART_DRAW_AXIS:
case PART_DRAW_CROSS:
if(draw_as != PART_DRAW_CROSS || create_cdata)
- cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata");
- vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata");
+ pdd.cdata = MEM_callocN(tot_vec_size * 6, "particle_cdata");
+ pdd.vdata = MEM_callocN(tot_vec_size * 6, "particle_vdata");
break;
case PART_DRAW_LINE:
if(create_cdata)
- cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata");
- vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata");
+ pdd.cdata = MEM_callocN(tot_vec_size * 2, "particle_cdata");
+ pdd.vdata = MEM_callocN(tot_vec_size * 2, "particle_vdata");
break;
case PART_DRAW_BB:
if(create_cdata)
- cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata");
- vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
- ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
+ pdd.cdata = MEM_callocN(tot_vec_size * 4, "particle_cdata");
+ pdd.vdata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
+ pdd.ndata = MEM_callocN(tot_vec_size * 4, "particle_vdata");
break;
default:
if(create_cdata)
- cdata=MEM_callocN(tot_vec_size, "particle_cdata");
- vdata=MEM_callocN(tot_vec_size, "particle_vdata");
+ pdd.cdata=MEM_callocN(tot_vec_size, "particle_cdata");
+ pdd.vdata=MEM_callocN(tot_vec_size, "particle_vdata");
}
}
- if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE)
- vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata");
+ if(part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
+ pdd.vedata = MEM_callocN(tot_vec_size * 2, "particle_vedata");
+ need_v = 1;
+ }
- vd=vdata;
- ved=vedata;
- cd=cdata;
- nd=ndata;
+ pdd.vd= pdd.vdata;
+ pdd.ved= pdd.vedata;
+ pdd.cd= pdd.cdata;
+ pdd.nd= pdd.ndata;
psys->lattice= psys_get_lattice(scene, ob, psys);
}
@@ -3176,6 +3410,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue;
pa_time=(cfra-pa->time)/pa->lifetime;
+ pa_birthtime=pa->time;
+ pa_dietime = pa->dietime;
pa_size=pa->size;
if((part->flag&PART_ABS_TIME)==0){
@@ -3209,12 +3445,13 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
#endif // XXX old animation system
}
- r_tilt=1.0f+pa->r_ave[0];
+ r_tilt = 1.0f + pa->r_ave[0];
+ r_length = 0.5f * (1.0f + pa->r_ave[1]);
}
else{
ChildParticle *cpa= &psys->child[a-totpart];
- pa_time=psys_get_child_time(psys,cpa,cfra);
+ pa_time=psys_get_child_time(psys,cpa,cfra,&pa_birthtime,&pa_dietime);
if((part->flag&PART_ABS_TIME)==0) {
if(ma && ma->ipo){
@@ -3238,148 +3475,80 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pa_size=psys_get_child_size(psys,cpa,cfra,0);
- r_tilt=2.0f*cpa->rand[2];
+ r_tilt = 2.0f * cpa->rand[2];
+ r_length = cpa->rand[1];
}
if(draw_as!=PART_DRAW_PATH){
- state.time=cfra;
- if(psys_get_particle_state(scene,ob,psys,a,&state,0)){
- if(psys->parent)
- Mat4MulVecfl(psys->parent->obmat, state.co);
-
- /* create actiual particle data */
- switch(draw_as){
- case PART_DRAW_DOT:
- if(vd){
- VECCOPY(vd,state.co) vd+=3;
- }
- if(cd) {
- cd[0]=ma_r;
- cd[1]=ma_g;
- cd[2]=ma_b;
- cd+=3;
- }
- break;
- case PART_DRAW_CROSS:
- case PART_DRAW_AXIS:
- vec[0]=2.0f*pixsize;
- vec[1]=vec[2]=0.0;
- QuatMulVecf(state.rot,vec);
- if(draw_as==PART_DRAW_AXIS){
- cd[1]=cd[2]=cd[4]=cd[5]=0.0;
- cd[0]=cd[3]=1.0;
- cd[6]=cd[8]=cd[9]=cd[11]=0.0;
- cd[7]=cd[10]=1.0;
- cd[13]=cd[12]=cd[15]=cd[16]=0.0;
- cd[14]=cd[17]=1.0;
- cd+=18;
-
- VECCOPY(vec2,state.co);
- }
- else {
- if(cd) {
- cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r;
- cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g;
- cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b;
- cd+=18;
- }
- VECSUB(vec2,state.co,vec);
- }
+ drawn = 0;
+ if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
+ float length = part->path_end * (1.0 - part->randlength * r_length);
+ int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
+ float ct = ((part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time) - length;
+ float dt = length / (trail_count ? (float)trail_count : 1.0f);
+ int i=0;
+
+ ct+=dt;
+ for(i=0; i < trail_count; i++, ct += dt) {
+ if(part->draw & PART_ABS_PATH_TIME) {
+ if(ct < pa_birthtime || ct > pa_dietime)
+ continue;
+ }
+ else if(ct < 0.0f || ct > 1.0f)
+ continue;
- VECADD(vec,state.co,vec);
- VECCOPY(vd,vec); vd+=3;
- VECCOPY(vd,vec2); vd+=3;
-
- vec[1]=2.0f*pixsize;
- vec[0]=vec[2]=0.0;
- QuatMulVecf(state.rot,vec);
- if(draw_as==PART_DRAW_AXIS){
- VECCOPY(vec2,state.co);
- }
- else VECSUB(vec2,state.co,vec);
-
- VECADD(vec,state.co,vec);
- VECCOPY(vd,vec); vd+=3;
- VECCOPY(vd,vec2); vd+=3;
-
- vec[2]=2.0f*pixsize;
- vec[0]=vec[1]=0.0;
- QuatMulVecf(state.rot,vec);
- if(draw_as==PART_DRAW_AXIS){
- VECCOPY(vec2,state.co);
- }
- else VECSUB(vec2,state.co,vec);
-
- VECADD(vec,state.co,vec);
-
- VECCOPY(vd,vec); vd+=3;
- VECCOPY(vd,vec2); vd+=3;
- break;
- case PART_DRAW_LINE:
- VECCOPY(vec,state.vel);
- Normalize(vec);
- if(part->draw & PART_DRAW_VEL_LENGTH)
- VecMulf(vec,VecLength(state.vel));
- VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3;
- VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3;
- if(cd) {
- cd[0]=cd[3]=ma_r;
- cd[1]=cd[4]=ma_g;
- cd[2]=cd[5]=ma_b;
- cd+=3;
- }
- break;
- case PART_DRAW_CIRC:
- if(create_cdata)
- glColor3f(ma_r,ma_g,ma_b);
- drawcircball(GL_LINE_LOOP, state.co, pixsize, imat);
- break;
- case PART_DRAW_BB:
- if(cd) {
- cd[0]=cd[3]=cd[6]=cd[9]=ma_r;
- cd[1]=cd[4]=cd[7]=cd[10]=ma_g;
- cd[2]=cd[5]=cd[8]=cd[11]=ma_b;
- cd+=12;
- }
+ state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct;
+ psys_get_particle_on_path(scene,ob,psys,a,&state,need_v);
+
+ if(psys->parent)
+ Mat4MulVecfl(psys->parent->obmat, state.co);
+ /* create actiual particle data */
+ if(draw_as == PART_DRAW_BB) {
bb.size = pa_size;
bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
- bb.time = pa_time;
- VECCOPY(bb.vec, state.co);
- VECCOPY(bb.vel, state.vel);
-
- psys_make_billboard(&bb, xvec, yvec, zvec, bb_center);
-
- VECADD(vd,bb_center,xvec);
- VECADD(vd,vd,yvec); vd+=3;
+ bb.time = ct;
+ }
- VECSUB(vd,bb_center,xvec);
- VECADD(vd,vd,yvec); vd+=3;
+ draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd);
- VECSUB(vd,bb_center,xvec);
- VECSUB(vd,vd,yvec); vd+=3;
+ totpoint++;
+ drawn = 1;
+ }
+ }
+ else
+ {
+ state.time=cfra;
+ if(psys_get_particle_state(scene,ob,psys,a,&state,0)){
+ if(psys->parent)
+ Mat4MulVecfl(psys->parent->obmat, state.co);
+
+ /* create actiual particle data */
+ if(draw_as == PART_DRAW_BB) {
+ bb.size = pa_size;
+ bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+ bb.time = pa_time;
+ }
- VECADD(vd,bb_center,xvec);
- VECSUB(vd,vd,yvec); vd+=3;
+ draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd);
- VECCOPY(nd, zvec); nd+=3;
- VECCOPY(nd, zvec); nd+=3;
- VECCOPY(nd, zvec); nd+=3;
- VECCOPY(nd, zvec); nd+=3;
- break;
+ totpoint++;
+ drawn = 1;
}
+ }
- totpoint++;
-
+ if(drawn) {
/* additional things to draw for each particle */
/* (velocity, size and number) */
- if(vedata){
- VECCOPY(ved,state.co);
- ved+=3;
+ if(pdd.vedata){
+ VECCOPY(pdd.ved,state.co);
+ pdd.ved+=3;
VECCOPY(vel,state.vel);
VecMulf(vel,timestep);
- VECADD(ved,state.co,vel);
- ved+=3;
+ VECADD(pdd.ved,state.co,vel);
+ pdd.ved+=3;
+
+ totve++;
}
if(part->draw & PART_DRAW_SIZE){
@@ -3391,7 +3560,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if(part->draw&PART_DRAW_NUM && !(G.f & G_RENDER_SHADOW)){
/* in path drawing state.co is the end point */
sprintf(val," %i",a);
- view3d_object_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0);
+ view3d_particle_text_draw_add(state.co[0], state.co[1], state.co[2], val, 0);
}
}
}
@@ -3408,7 +3577,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glEnableClientState(GL_VERTEX_ARRAY);
/* setup gl flags */
- if(dt > OB_WIRE) {
+ if(ob_dt > OB_WIRE) {
glEnableClientState(GL_NORMAL_ARRAY);
if(part->draw&PART_DRAW_MAT_COL)
@@ -3436,7 +3605,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if(path->steps > 0) {
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
- if(dt > OB_WIRE) {
+ if(ob_dt > OB_WIRE) {
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
if(part->draw&PART_DRAW_MAT_COL)
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
@@ -3452,7 +3621,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
path=cache[a];
glVertexPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->co);
- if(dt > OB_WIRE) {
+ if(ob_dt > OB_WIRE) {
glNormalPointer(GL_FLOAT, sizeof(ParticleCacheKey), path->vel);
if(part->draw&PART_DRAW_MAT_COL)
glColorPointer(3, GL_FLOAT, sizeof(ParticleCacheKey), path->col);
@@ -3463,7 +3632,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
/* restore & clean up */
- if(dt > OB_WIRE) {
+ if(ob_dt > OB_WIRE) {
if(part->draw&PART_DRAW_MAT_COL)
glDisable(GL_COLOR_ARRAY);
glDisable(GL_COLOR_MATERIAL);
@@ -3479,16 +3648,17 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glDisableClientState(GL_COLOR_ARRAY);
/* setup created data arrays */
- if(vdata){
+ if(pdd.vdata){
glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, vdata);
+ glVertexPointer(3, GL_FLOAT, 0, pdd.vdata);
}
else
glDisableClientState(GL_VERTEX_ARRAY);
- if(ndata && dt>OB_WIRE){
+ /* billboards are drawn this way */
+ if(pdd.ndata && ob_dt>OB_WIRE){
glEnableClientState(GL_NORMAL_ARRAY);
- glNormalPointer(GL_FLOAT, 0, ndata);
+ glNormalPointer(GL_FLOAT, 0, pdd.ndata);
glEnable(GL_LIGHTING);
}
else{
@@ -3496,9 +3666,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glDisable(GL_LIGHTING);
}
- if(cdata){
+ if(pdd.cdata){
glEnableClientState(GL_COLOR_ARRAY);
- glColorPointer(3, GL_FLOAT, 0, cdata);
+ glColorPointer(3, GL_FLOAT, 0, pdd.cdata);
}
/* draw created data arrays */
@@ -3511,7 +3681,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
glDrawArrays(GL_LINES, 0, 2*totpoint);
break;
case PART_DRAW_BB:
- if(dt<=OB_WIRE)
+ if(ob_dt<=OB_WIRE)
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
glDrawArrays(GL_QUADS, 0, 4*totpoint);
@@ -3522,14 +3692,14 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
}
}
- if(vedata){
+ if(pdd.vedata){
glDisableClientState(GL_COLOR_ARRAY);
cpack(0xC0C0C0);
glEnableClientState(GL_VERTEX_ARRAY);
- glVertexPointer(3, GL_FLOAT, 0, vedata);
+ glVertexPointer(3, GL_FLOAT, 0, pdd.vedata);
- glDrawArrays(GL_LINES, 0, 2*totpoint);
+ glDrawArrays(GL_LINES, 0, 2*totve);
}
glPolygonMode(GL_FRONT, polygonmode[0]);
@@ -3544,14 +3714,14 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if(states)
MEM_freeN(states);
- if(vdata)
- MEM_freeN(vdata);
- if(vedata)
- MEM_freeN(vedata);
- if(cdata)
- MEM_freeN(cdata);
- if(ndata)
- MEM_freeN(ndata);
+ if(pdd.vdata)
+ MEM_freeN(pdd.vdata);
+ if(pdd.vedata)
+ MEM_freeN(pdd.vedata);
+ if(pdd.cdata)
+ MEM_freeN(pdd.cdata);
+ if(pdd.ndata)
+ MEM_freeN(pdd.ndata);
psys->flag &= ~PSYS_DRAWING;
@@ -3560,8 +3730,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
psys->lattice= NULL;
}
- wmLoadMatrix(rv3d->viewmat);
- wmMultMatrix(ob->obmat); // bring back local matrix for dtx
+ if( (base->flag & OB_FROMDUPLI) && (ob->flag & OB_FROMGROUP) )
+ wmLoadMatrix(rv3d->viewmat);
}
static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, ParticleSystem *psys, int dt)
@@ -3596,8 +3766,6 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
if((v3d->flag & V3D_ZBUF_SELECT)==0)
glDisable(GL_DEPTH_TEST);
- wmLoadMatrix(rv3d->viewmat);
-
/* get selection theme colors */
UI_GetThemeColor3ubv(TH_VERTEX_SELECT, sel);
UI_GetThemeColor3ubv(TH_VERTEX, nosel);
@@ -3706,7 +3874,7 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
if(key->flag & PEK_HIDE) continue;
sprintf(val," %.1f",*key->time);
- view3d_object_text_draw_add(key->world_co[0], key->world_co[1], key->world_co[2], val, 0);
+ view3d_particle_text_draw_add(key->world_co[0], key->world_co[1], key->world_co[2], val, 0);
}
}
}
@@ -3729,7 +3897,7 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
if((pset->flag & PE_SHOW_TIME) && !(G.f & G_RENDER_SHADOW)){
sprintf(val," %.1f",*key->time);
- view3d_object_text_draw_add(key->world_co[0], key->world_co[1], key->world_co[2], val, 0);
+ view3d_particle_text_draw_add(key->world_co[0], key->world_co[1], key->world_co[2], val, 0);
}
}
}
@@ -3744,7 +3912,6 @@ static void draw_particle_edit(Scene *scene, View3D *v3d, RegionView3D *rv3d, Ob
glEnable(GL_DEPTH_TEST);
glLineWidth(1.0f);
- wmMultMatrix(ob->obmat); // bring back local matrix for dtx
glPointSize(1.0);
}
@@ -5145,7 +5312,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
) {
ParticleSystem *psys;
if(col || (ob->flag & SELECT)) cpack(0xFFFFFF); /* for visibility, also while wpaint */
- glDepthMask(GL_FALSE);
+ //glDepthMask(GL_FALSE);
+
+ wmLoadMatrix(rv3d->viewmat);
for(psys=ob->particlesystem.first; psys; psys=psys->next)
draw_new_particle_system(scene, v3d, rv3d, base, psys, dt);
@@ -5155,7 +5324,11 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag)
if(psys && !scene->obedit && psys_in_edit_mode(scene, psys))
draw_particle_edit(scene, v3d, rv3d, ob, psys, dt);
}
- glDepthMask(GL_TRUE);
+ view3d_particle_text_draw(v3d, ar);
+
+ wmMultMatrix(ob->obmat);
+
+ //glDepthMask(GL_TRUE);
if(col) cpack(col);
}
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 76f6b980aa2..1fa17760e8d 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -503,12 +503,14 @@ typedef enum {
eParticleInstanceFlag_Unborn = (1<<3),
eParticleInstanceFlag_Alive = (1<<4),
eParticleInstanceFlag_Dead = (1<<5),
+ eParticleInstanceFlag_KeepShape = (1<<6),
} ParticleInstanceModifierFlag;
typedef struct ParticleInstanceModifierData {
ModifierData modifier;
struct Object *ob;
- short psys, flag, rt[2];
+ short psys, flag, axis, rt;
+ float position, random_position;
} ParticleInstanceModifierData;
typedef enum {
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index 05f1cc1f351..c793362c223 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -131,7 +131,7 @@ typedef struct ParticleSettings {
/* general values */
float sta, end, lifetime, randlife;
- float timetweak, jitfac, keyed_time, eff_hair, rt;
+ float timetweak, jitfac, keyed_time, eff_hair;
int totpart, userjit, grid_res;
/* initial velocity factors */
@@ -159,6 +159,8 @@ typedef struct ParticleSettings {
float branch_thres;
/* drawing stuff */
float draw_line[2];
+ float path_start, path_end;
+ int trail_count;
/* boids */
float max_vel, max_lat_acc, max_tan_acc;
@@ -311,8 +313,8 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
#define PART_DRAW_SIZE 4
#define PART_DRAW_EMITTER 8 /* render emitter also */
//#define PART_DRAW_HEALTH 16
-//#define PART_DRAW_TIMED_PATH 32
-//#define PART_DRAW_CACHED_PATH 64
+#define PART_ABS_PATH_TIME 32
+//#define PART_DRAW_TRAIL 64
#define PART_DRAW_BB_LOCK 128
#define PART_DRAW_PARENT 256
#define PART_DRAW_NUM 512
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 48bfdf70171..f4c14a51b13 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1300,6 +1300,13 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ static EnumPropertyItem particleinstance_axis[] = {
+ {0, "X", 0, "X", ""},
+ {1, "Y", 0, "Y", ""},
+ {2, "Z", 0, "Z", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna= RNA_def_struct(brna, "ParticleInstanceModifier", "Modifier");
RNA_def_struct_ui_text(srna, "ParticleInstance Modifier", "Particle system instancing modifier.");
RNA_def_struct_sdna(srna, "ParticleInstanceModifierData");
@@ -1316,6 +1323,12 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Particle System Number", "");
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "axis");
+ RNA_def_property_enum_items(prop, particleinstance_axis);
+ RNA_def_property_ui_text(prop, "Axis", "Pole axis for rotation");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
prop= RNA_def_property(srna, "normal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Parents);
@@ -1346,6 +1359,23 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Dead);
RNA_def_property_ui_text(prop, "Dead", "Show instances when particles are dead.");
RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "keep_shape", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_KeepShape);
+ RNA_def_property_ui_text(prop, "Keep Shape", "Don't stretch the object.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "position", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "position");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Position", "Position along path.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
+
+ prop= RNA_def_property(srna, "random_position", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "random_position");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Random Position", "Randomize position along path.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_MODIFIER, "rna_Modifier_update");
}
static void rna_def_modifier_explode(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index d60a215b498..5c94c81da1f 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -151,6 +151,20 @@ static void rna_particle_settings_set(PointerRNA *ptr, PointerRNA value)
if(psys->part)
psys->part->id.us++;
}
+static void rna_Particle_abspathtime_update(bContext *C, PointerRNA *ptr)
+{
+ ParticleSettings *settings = (ParticleSettings*)ptr->data;
+ float delta = settings->end + settings->lifetime - settings->sta;
+ if(settings->draw & PART_ABS_PATH_TIME) {
+ settings->path_start = settings->sta + settings->path_start * delta;
+ settings->path_end = settings->sta + settings->path_end * delta;
+ }
+ else {
+ settings->path_start = (settings->path_start - settings->sta)/delta;
+ settings->path_end = (settings->path_end - settings->sta)/delta;
+ }
+ rna_Particle_redo(C, ptr);
+}
static void rna_PartSettings_start_set(struct PointerRNA *ptr, float value)
{
ParticleSettings *settings = (ParticleSettings*)ptr->data;
@@ -189,7 +203,19 @@ static float rna_PartSetting_linelentail_get(struct PointerRNA *ptr)
ParticleSettings *settings = (ParticleSettings*)ptr->data;
return settings->draw_line[0];
}
+static void rna_PartSetting_pathstartend_range(PointerRNA *ptr, float *min, float *max)
+{
+ ParticleSettings *settings = (ParticleSettings*)ptr->data;
+ if(settings->type==PART_HAIR) {
+ *min = 0.0f;
+ *max = (settings->draw & PART_ABS_PATH_TIME) ? 100.0f : 1.0;
+ }
+ else {
+ *min = (settings->draw & PART_ABS_PATH_TIME) ? settings->sta : 0.0f;
+ *max= (settings->draw & PART_ABS_PATH_TIME) ? MAXFRAMEF : 1.0f;
+ }
+}
static void rna_PartSetting_linelenhead_set(struct PointerRNA *ptr, float value)
{
ParticleSettings *settings = (ParticleSettings*)ptr->data;
@@ -702,15 +728,15 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Abs Length", "Use maximum length for children");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
- prop= RNA_def_property(srna, "absolute_time", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ABS_TIME);
- RNA_def_property_ui_text(prop, "Absolute Time", "Set all ipos that work on particles to be calculated in absolute/relative time.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ //prop= RNA_def_property(srna, "absolute_time", PROP_BOOLEAN, PROP_NONE);
+ //RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ABS_TIME);
+ //RNA_def_property_ui_text(prop, "Absolute Time", "Set all ipos that work on particles to be calculated in absolute/relative time.");
+ //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
- prop= RNA_def_property(srna, "global_time", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_GLOB_TIME);
- RNA_def_property_ui_text(prop, "Global Time", "Set all ipos that work on particles to be calculated in global/object time.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ //prop= RNA_def_property(srna, "global_time", PROP_BOOLEAN, PROP_NONE);
+ //RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_GLOB_TIME);
+ //RNA_def_property_ui_text(prop, "Global Time", "Set all ipos that work on particles to be calculated in global/object time.");
+ //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "boids_2d", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_BOIDS_2D);
@@ -836,15 +862,10 @@ static void rna_def_particle_settings(BlenderRNA *brna)
//RNA_def_property_ui_text(prop, "Health", "Draw boid health");
//RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
- //prop= RNA_def_property(srna, "timed_path", PROP_BOOLEAN, PROP_NONE);
- //RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_TIMED_PATH);
- //RNA_def_property_ui_text(prop, "Clip with time", "Clip path based on time");
- //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
- //prop= RNA_def_property(srna, "draw_cached_path", PROP_BOOLEAN, PROP_NONE);
- //RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_CACHED_PATH);
- //RNA_def_property_ui_text(prop, "Path", "Draw particle path if the path is baked");
- //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+ prop= RNA_def_property(srna, "abs_path_time", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_ABS_PATH_TIME);
+ RNA_def_property_ui_text(prop, "Absolute Path Time", "Path timing is in absolute frames");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_abspathtime_update");
prop= RNA_def_property(srna, "billboard_lock", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_BB_LOCK);
@@ -1410,6 +1431,24 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Head", "Length of the line's head");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+ prop= RNA_def_property(srna, "path_start", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "path_start");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_PartSetting_pathstartend_range");
+ RNA_def_property_ui_text(prop, "Path Start", "Starting time of drawn path.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+
+ prop= RNA_def_property(srna, "path_end", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "path_end");
+ RNA_def_property_float_funcs(prop, NULL, NULL, "rna_PartSetting_pathstartend_range");
+ RNA_def_property_ui_text(prop, "Path End", "End time of drawn path.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+
+ prop= RNA_def_property(srna, "trail_count", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "trail_count");
+ RNA_def_property_range(prop, 1.0f, 100.0f);
+ RNA_def_property_ui_text(prop, "Trail Count", "Number of trail particles.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+
/* boids */
prop= RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_vel");
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index a00cd2211fc..74686511b21 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1246,6 +1246,19 @@ static void static_particle_wire(ObjectRen *obr, Material *ma, float *vec, float
}
+static void particle_curve(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, float *loc, float *loc1, int seed)
+{
+ HaloRen *har=0;
+
+ if(ma->mode&MA_WIRE)
+ static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line);
+ else if(ma->material_type == MA_TYPE_HALO) {
+ har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed);
+ if(har) har->lay= obr->ob->lay;
+ }
+ else
+ static_particle_strand(re, obr, ma, sd, loc, loc1);
+}
static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, ParticleBillboardData *bb)
{
VlakRen *vlr;
@@ -1368,18 +1381,55 @@ static void particle_billboard(Render *re, ObjectRen *obr, Material *ma, Particl
mtf->uv[3][1] = uvy;
}
}
-static void render_new_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, float *loc, float *loc1, int seed)
+static void particle_normal_ren(short ren_as, ParticleSettings *part, Render *re, ObjectRen *obr, DerivedMesh *dm, Material *ma, ParticleStrandData *sd, ParticleBillboardData *bb, ParticleKey *state, int seed, float hasize)
{
- HaloRen *har=0;
+ float loc[3], loc0[3], loc1[3], vel[3];
+
+ VECCOPY(loc, state->co);
- if(ma->mode&MA_WIRE)
- static_particle_wire(obr, ma, loc, loc1, sd->first, sd->line);
- else if(ma->material_type == MA_TYPE_HALO) {
- har= RE_inithalo_particle(re, obr, dm, ma, loc, loc1, sd->orco, sd->uvco, sd->size, 1.0, seed);
- if(har) har->lay= obr->ob->lay;
+ if(ren_as != PART_DRAW_BB)
+ MTC_Mat4MulVecfl(re->viewmat, loc);
+
+ switch(ren_as) {
+ case PART_DRAW_LINE:
+ sd->line = 1;
+ sd->time = 0.0f;
+ sd->size = hasize;
+
+ VECCOPY(vel, state->vel);
+ MTC_Mat4Mul3Vecfl(re->viewmat, vel);
+ Normalize(vel);
+
+ if(part->draw & PART_DRAW_VEL_LENGTH)
+ VecMulf(vel, VecLength(state->vel));
+
+ VECADDFAC(loc0, loc, vel, -part->draw_line[0]);
+ VECADDFAC(loc1, loc, vel, part->draw_line[1]);
+
+ particle_curve(re, obr, dm, ma, sd, loc0, loc1, seed);
+
+ break;
+
+ case PART_DRAW_BB:
+
+ VECCOPY(bb->vec, loc);
+ VECCOPY(bb->vel, state->vel);
+
+ particle_billboard(re, obr, ma, bb);
+
+ break;
+
+ default:
+ {
+ HaloRen *har=0;
+
+ har = RE_inithalo_particle(re, obr, dm, ma, loc, NULL, sd->orco, sd->uvco, hasize, 0.0, seed);
+
+ if(har) har->lay= obr->ob->lay;
+
+ break;
+ }
}
- else
- static_particle_strand(re, obr, ma, sd, loc, loc1);
}
static void get_particle_uvco_mcol(short from, DerivedMesh *dm, float *fuv, int num, ParticleStrandData *sd)
{
@@ -1436,9 +1486,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
StrandBound *sbound= 0;
StrandRen *strand=0;
RNG *rng= 0;
- float loc[3],loc1[3],loc0[3],vel[3],mat[4][4],nmat[3][3],co[3],nor[3],time;
+ float loc[3],loc1[3],loc0[3],mat[4][4],nmat[3][3],co[3],nor[3],time;
float strandlen=0.0f, curlen=0.0f;
- float hasize, pa_size, pa_time, r_tilt, cfra=bsystem_time(re->scene, ob, (float)re->scene->r.cfra, 0.0);
+ float hasize, pa_size, r_tilt, r_length, cfra=bsystem_time(re->scene, ob, (float)re->scene->r.cfra, 0.0);
+ float pa_time, pa_birthtime, pa_dietime;
float random, simplify[2];
int i, a, k, max_k=0, totpart, dosimplify = 0, dosurfacecache = 0;
int totchild=0;
@@ -1654,6 +1705,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if(pa->flag & PARS_UNEXIST) continue;
pa_time=(cfra-pa->time)/pa->lifetime;
+ pa_birthtime = pa->time;
+ pa_dietime = pa->dietime;
if((part->flag&PART_ABS_TIME) == 0){
#if 0 // XXX old animation system
if(ma->ipo) {
@@ -1691,6 +1744,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
pa_size = pa->size;
r_tilt = 1.0f + pa->r_ave[0];
+ r_length = 0.5f * (1.0f + pa->r_ave[1]);
if(path_nbr) {
cache = psys->pathcache[a];
@@ -1711,7 +1765,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
max_k = (int)cache->steps;
}
- pa_time = psys_get_child_time(psys, cpa, cfra);
+ pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
if((part->flag & PART_ABS_TIME) == 0) {
#if 0 // XXX old animation system
@@ -1731,6 +1785,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time);
r_tilt = 2.0f * cpa->rand[2];
+ r_length = cpa->rand[1];
num = cpa->num;
@@ -1864,14 +1919,14 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
VECSUB(loc0,loc1,loc);
VECADD(loc0,loc1,loc0);
- render_new_particle(re, obr, psmd->dm, ma, &sd, loc1, loc0, seed);
+ particle_curve(re, obr, psmd->dm, ma, &sd, loc1, loc0, seed);
}
sd.first = 0;
sd.time = time;
if(k)
- render_new_particle(re, obr, psmd->dm, ma, &sd, loc, loc1, seed);
+ particle_curve(re, obr, psmd->dm, ma, &sd, loc, loc1, seed);
VECCOPY(loc1,loc);
}
@@ -1880,61 +1935,55 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
}
else {
/* render normal particles */
- time=0.0f;
- state.time=cfra;
- if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0)
- continue;
-
- if(psys->parent)
- Mat4MulVecfl(psys->parent->obmat, state.co);
-
- VECCOPY(loc,state.co);
- if(part->ren_as!=PART_DRAW_BB)
- MTC_Mat4MulVecfl(re->viewmat,loc);
-
- switch(part->ren_as) {
- case PART_DRAW_LINE:
- sd.line = 1;
- sd.time = 0.0f;
- sd.size = hasize;
+ if(part->trail_count > 1) {
+ float length = part->path_end * (1.0 - part->randlength * r_length);
+ int trail_count = part->trail_count * (1.0 - part->randlength * r_length);
+ float ct = (part->draw & PART_ABS_PATH_TIME) ? cfra : pa_time;
+ float dt = length / (trail_count ? (float)trail_count : 1.0f);
+
+ for(i=0; i < trail_count; i++, ct -= dt) {
+ if(part->draw & PART_ABS_PATH_TIME) {
+ if(ct < pa_birthtime || ct > pa_dietime)
+ continue;
+ }
+ else if(ct < 0.0f || ct > 1.0f)
+ continue;
- VECCOPY(vel,state.vel);
- MTC_Mat4Mul3Vecfl(re->viewmat,vel);
- Normalize(vel);
+ state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct;
+ psys_get_particle_on_path(re->scene,ob,psys,a,&state,1);
- if(part->draw & PART_DRAW_VEL_LENGTH)
- VecMulf(vel,VecLength(state.vel));
+ if(psys->parent)
+ Mat4MulVecfl(psys->parent->obmat, state.co);
- VECADDFAC(loc0,loc,vel,-part->draw_line[0]);
- VECADDFAC(loc1,loc,vel,part->draw_line[1]);
+ if(part->ren_as == PART_DRAW_BB) {
+ bb.random = random;
+ bb.size = pa_size;
+ bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
+ bb.time = ct;
+ bb.num = a;
+ }
- render_new_particle(re,obr,psmd->dm,ma,&sd,loc0,loc1,seed);
+ particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize);
+ }
+ }
+ else {
+ time=0.0f;
+ state.time=cfra;
+ if(psys_get_particle_state(re->scene,ob,psys,a,&state,0)==0)
+ continue;
- break;
+ if(psys->parent)
+ Mat4MulVecfl(psys->parent->obmat, state.co);
- case PART_DRAW_BB:
+ if(part->ren_as == PART_DRAW_BB) {
bb.random = random;
bb.size = pa_size;
bb.tilt = part->bb_tilt * (1.0f - part->bb_rand_tilt * r_tilt);
bb.time = pa_time;
bb.num = a;
- VECCOPY(bb.vec, loc);
- VECCOPY(bb.vel, state.vel);
-
- particle_billboard(re, obr, ma, &bb);
-
- break;
-
- default:
- {
- HaloRen *har=0;
-
- har = RE_inithalo_particle(re, obr, psmd->dm, ma, loc, NULL, sd.orco, sd.uvco, hasize, 0.0, seed);
-
- if(har) har->lay= obr->ob->lay;
-
- break;
}
+
+ particle_normal_ren(part->ren_as, part, re, obr, psmd->dm, ma, &sd, &bb, &state, seed, hasize);
}
}