A bunch of fun stuff now possible because of new pointcache code:
* Baked normal particles can now use the "Path" visualization. * Path "max length" & "abs length" are now history: - New option to set path start & end times + random variation to length. - Much more flexible (and calculated better) than previous options. - This works with parents, children, hair & normal particles unlike old length option. - Only known issue for now is that children from faces don't get calculated correctly when using path start time. * New option "trails" for "halo", "line" and "billboard" visualizations: - Draws user controllable number of particle instances along particles path backwards from current position. - Works with children too for cool/weird visualizations that weren't possible before. * Normal particle children's velocities are now approximated better when needed so that "line" visualization trails will look nice. * New particle instance modifier options: - "path"-option works better and has controllable (max)position along path (with random variation possible). - "keep shape"-option for hair, keyed, or baked particles allows to place the instances to a single point (with random variation possible) along particle path. - "axis" option to make rotation handling better (still not perfect, but will have to do for now). Some fixes & cleanup done along the way: * Random path length didn't work for non-child particles. * Cached & unborn particles weren't reset to emit locations. * Particle numbers weren't drawn in the correct place. * Setting proper render & draw visualizations was lost somewhere when initializing new particle settings. * Changing child mode wasn't working correctly. * Some cleanup & modularization of particle child effector code and particle drawing & rendering code. * Object & group visualizations didn't work. * Child simplification didn't work.
This commit is contained in:
parent
2c71b12998
commit
66918b3add
@ -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.")
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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];
|
||||
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]);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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[0] = 0.0;
|
||||
|
||||
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;
|
||||
|
@ -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));
|
||||
do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, (ParticleKey *)state, t);
|
||||
|
||||
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);
|
||||
}
|
||||
/* 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;
|
||||
|
||||
if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
|
||||
rough_t = t * rough_rand;
|
||||
else
|
||||
rough_t = t;
|
||||
/* 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);
|
||||
|
||||
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);
|
||||
// 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(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);
|
||||
|
||||
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);
|
||||
|
||||
if(vel)
|
||||
copy_particle_key(&tstate, state, 1);
|
||||
|
||||
/* 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);
|
||||
do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, state, t);
|
||||
|
||||
if(part->rough1 != 0.0)
|
||||
do_rough(orco, t, part->rough1, part->rough1_size, 0.0, state);
|
||||
/* try to estimate correct velocity */
|
||||
if(vel){
|
||||
ParticleKey tstate;
|
||||
float length = VecLength(state->vel);
|
||||
|
||||
if(part->rough2 != 0.0)
|
||||
do_rough(cpa->rand, t, part->rough2, part->rough2_size, part->rough2_thres, state);
|
||||
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(part->rough_end != 0.0)
|
||||
do_rough_end(cpa->rand, t, part->rough_end, part->rough_end_shape, state, par);
|
||||
|
||||
//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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
/* 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 = ct;
|
||||
}
|
||||
|
||||
VECADD(vec,state.co,vec);
|
||||
VECCOPY(vd,vec); vd+=3;
|
||||
VECCOPY(vd,vec2); vd+=3;
|
||||
draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd);
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
draw_particle(&state, draw_as, part->draw, pixsize, imat, part->draw_line, &bb, &pdd);
|
||||
|
||||
VECSUB(vd,bb_center,xvec);
|
||||
VECADD(vd,vd,yvec); vd+=3;
|
||||
|
||||
VECSUB(vd,bb_center,xvec);
|
||||
VECSUB(vd,vd,yvec); vd+=3;
|
||||
|
||||
VECADD(vd,bb_center,xvec);
|
||||
VECSUB(vd,vd,yvec); vd+=3;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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(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);
|
||||
|
||||
if(psys->parent)
|
||||
Mat4MulVecfl(psys->parent->obmat, state.co);
|
||||
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(loc,state.co);
|
||||
if(part->ren_as!=PART_DRAW_BB)
|
||||
MTC_Mat4MulVecfl(re->viewmat,loc);
|
||||
state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct;
|
||||
psys_get_particle_on_path(re->scene,ob,psys,a,&state,1);
|
||||
|
||||
switch(part->ren_as) {
|
||||
case PART_DRAW_LINE:
|
||||
sd.line = 1;
|
||||
sd.time = 0.0f;
|
||||
sd.size = hasize;
|
||||
if(psys->parent)
|
||||
Mat4MulVecfl(psys->parent->obmat, state.co);
|
||||
|
||||
VECCOPY(vel,state.vel);
|
||||
MTC_Mat4Mul3Vecfl(re->viewmat,vel);
|
||||
Normalize(vel);
|
||||
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;
|
||||
}
|
||||
|
||||
if(part->draw & PART_DRAW_VEL_LENGTH)
|
||||
VecMulf(vel,VecLength(state.vel));
|
||||
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;
|
||||
|
||||
VECADDFAC(loc0,loc,vel,-part->draw_line[0]);
|
||||
VECADDFAC(loc1,loc,vel,part->draw_line[1]);
|
||||
if(psys->parent)
|
||||
Mat4MulVecfl(psys->parent->obmat, state.co);
|
||||
|
||||
render_new_particle(re,obr,psmd->dm,ma,&sd,loc0,loc1,seed);
|
||||
|
||||
break;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user