Revert part of commit 29079, cleanup of particle path drawing logic

This commit and other commits attempting to fix it broke various things. The
main thing that changed was that instead of computing children/paths in
advance as part of particle_system_update, this was moved to do it just before
drawing or rendering. I've changed back that behavior and tried to keep the
other fixes in the commit.

When the new particle system was just committed, it also worked this way but
gave various problems, and I had to remove that behavior to get things working
stable. Basically it meant that you could get have a path cache that was
outdated in various situations, and it doesn't fit well with dependency graph
evaluation order.

This fixes:
#22823: Children Particle Rendering is broken
#22733: Particle objects not displayed
#22888: SigSegV when rending hair particles
#22820: Another SigSegV when undo adding hairs in particel edit mode
Some particle setups in dupligroups.

The three bugs that the original commit fixed are now also still working in
my tests:
#21316: Hair weight drawing is wrong
#21923: Consistent Crash When Rendering Particle Scene.
#21950: Path rendering option for particles causes crash
This commit is contained in:
Brecht Van Lommel 2010-07-17 17:07:50 +00:00
parent 02ef91a619
commit 21cb1f82db
5 changed files with 74 additions and 47 deletions

@ -255,11 +255,9 @@ void psys_threads_free(ParticleThread *threads);
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
/* particle_system.c */
void psys_update_path_cache(struct ParticleSimulationData *sim, float cfra);
struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
void psys_count_keyed_targets(struct ParticleSimulationData *sim);
void psys_update_particle_tree(struct ParticleSystem *psys, float cfra);
void psys_update_children(struct ParticleSimulationData *sim);
void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, int *sfra, int *efra);

@ -433,7 +433,7 @@ void free_keyed_keys(ParticleSystem *psys)
}
}
}
void psys_free_child_path_cache(ParticleSystem *psys)
static void free_child_path_cache(ParticleSystem *psys)
{
psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs);
psys->childcache = NULL;
@ -451,7 +451,7 @@ void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit)
psys->pathcache= NULL;
psys->totcached= 0;
psys_free_child_path_cache(psys);
free_child_path_cache(psys);
}
}
void psys_free_children(ParticleSystem *psys)
@ -462,7 +462,7 @@ void psys_free_children(ParticleSystem *psys)
psys->totchild=0;
}
psys_free_child_path_cache(psys);
free_child_path_cache(psys);
}
void psys_free_particles(ParticleSystem *psys)
{
@ -2721,7 +2721,7 @@ void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupd
}
else {
/* clear out old and create new empty path cache */
psys_free_child_path_cache(sim->psys);
free_child_path_cache(sim->psys);
sim->psys->childcache= psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps+1);
sim->psys->totchildcache = totchild;
}

@ -3075,18 +3075,66 @@ static void deflect_particle(ParticleSimulationData *sim, int p, float dfra, flo
/* Hair */
/************************************************/
/* check if path cache or children need updating and do it if needed */
void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
static void psys_update_path_cache(ParticleSimulationData *sim, float cfra)
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
/* only hair, keyed and baked stuff can have paths */
if(part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->mem_cache.first) {
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
int distr=0, alloc=0, skip=0;
if((psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
alloc=1;
if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT)))
distr=1;
if(distr){
if(alloc)
realloc_particles(sim, sim->psys->totpart);
if(get_psys_tot_child(sim->scene, psys)) {
/* don't generate children while computing the hair keys */
if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
distribute_particles(sim, PART_FROM_CHILD);
if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
psys_find_parents(sim);
}
}
else
psys_free_children(psys);
}
if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0)
skip = 1; /* only hair, keyed and baked stuff can have paths */
else if(part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
skip = 1; /* particle visualization must be set as path */
else if(!psys->renderdata) {
if(part->draw_as != PART_DRAW_REND)
skip = 1; /* draw visualization */
else if(psys->pointcache->flag & PTCACHE_BAKING)
skip = 1; /* no need to cache paths while baking dynamics */
else if(psys_in_edit_mode(sim->scene, psys)) {
if((pset->flag & PE_DRAW_PART)==0)
skip = 1;
else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */
}
}
if(!skip) {
psys_cache_paths(sim, cfra);
/* for render, child particle paths are computed on the fly */
if(part->childtype && psys->totchild)
psys_cache_child_paths(sim, cfra, 0);
if(part->childtype) {
if(!psys->totchild)
skip = 1;
else if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)==0)
skip = 1;
if(!skip)
psys_cache_child_paths(sim, cfra, 0);
}
}
else if(psys->pathcache)
psys_free_path_cache(psys, NULL);
@ -3201,8 +3249,6 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm, 0, 0);
psys->clmd->sim_parms->effector_weights = NULL;
psys_free_path_cache(psys, NULL);
}
static void hair_step(ParticleSimulationData *sim, float cfra)
{
@ -3454,19 +3500,14 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
}
free_collider_cache(&sim->colliders);
if(psys->pathcache)
psys_free_path_cache(psys, NULL);
}
void psys_update_children(ParticleSimulationData *sim)
static void update_children(ParticleSimulationData *sim)
{
if((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0)
/* don't generate children while growing hair - waste of time */
psys_free_children(sim->psys);
else if(sim->psys->part->childtype) {
if(sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys))
distribute_particles(sim, PART_FROM_CHILD);
}
else if(sim->psys->part->childtype && sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys))
distribute_particles(sim, PART_FROM_CHILD);
else
psys_free_children(sim->psys);
}
@ -3721,6 +3762,8 @@ static void system_step(ParticleSimulationData *sim, float cfra)
if(ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
cached_step(sim, cfra);
update_children(sim);
psys_update_path_cache(sim, cfra);
BKE_ptcache_validate(cache, framenr);
@ -3784,6 +3827,9 @@ static void system_step(ParticleSimulationData *sim, float cfra)
BKE_ptcache_write_cache(use_cache, framenr);
}
if(init)
update_children(sim);
/* cleanup */
if(psys->lattice){
end_latt_deform(psys->lattice);
@ -3946,13 +3992,6 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
/* execute drivers only, as animation has already been done */
BKE_animsys_evaluate_animdata(&part->id, part->adt, cfra, ADT_RECALC_DRIVERS);
/* TODO: only free child paths in case of PSYS_RECALC_CHILD */
if(psys->recalc & PSYS_RECALC || ob->recalc & OB_RECALC_ALL)
psys_free_path_cache(psys, NULL);
if(psys->recalc & PSYS_RECALC_CHILD)
psys_free_children(psys);
if(psys->recalc & PSYS_RECALC_TYPE)
psys_changed_type(&sim);
else if(psys->recalc & PSYS_RECALC_PHYS)
@ -4009,6 +4048,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
if(part->phystype == PART_PHYS_KEYED) {
psys_count_keyed_targets(&sim);
set_keyed_keys(&sim);
psys_update_path_cache(&sim,(int)cfra);
}
break;
}

@ -3475,11 +3475,12 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
select=1;
}
psys_update_children(&sim);
psys->flag|=PSYS_DRAWING;
totchild=psys->totchild*part->disp/100;
if(part->type==PART_HAIR && !psys->childcache)
totchild=0;
else
totchild=psys->totchild*part->disp/100;
ma= give_current_material(ob,part->omat);
@ -3516,16 +3517,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
if(draw_as==PART_DRAW_PATH) {
if(psys->pathcache==NULL && psys->childcache==NULL)
psys_update_path_cache(&sim, cfra);
/* can't create pathcache for some reason*/
if(psys->pathcache==NULL && psys->childcache==NULL)
draw_as=PART_DRAW_DOT;
else if(psys->childcache==NULL)
totchild = 0;
}
if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL && psys->childcache==NULL)
draw_as=PART_DRAW_DOT;
/* 3. */
switch(draw_as){
@ -3877,7 +3870,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
UI_ThemeColor(TH_WIRE);
}*/
if(totchild && ((part->draw&PART_DRAW_PARENT)==0 || psys_in_edit_mode(scene, psys)))
if(totchild && (part->draw&PART_DRAW_PARENT)==0)
totpart=0;
else if(psys->pathcache==NULL)
totpart=0;

@ -1550,7 +1550,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
if(part->phystype==PART_PHYS_KEYED)
psys_count_keyed_targets(&sim);
psys_update_children(&sim);
totchild=psys->totchild;
if(G.rendering == 0) { /* preview render */
@ -1655,9 +1654,6 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
transpose_m3(nmat);
/* 2.6 setup strand rendering */
if(part->ren_as == PART_DRAW_PATH && psys->pathcache==NULL)
psys_update_path_cache(&sim, cfra);
if(part->ren_as == PART_DRAW_PATH && psys->pathcache){
path_nbr=(int)pow(2.0,(double) part->ren_step);