From 6b2b56c35eaf1ea8d2b0d0edd2412288f0e67e19 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Wed, 15 Dec 2010 17:05:34 +0000 Subject: Fix for [#25218] No smoke is emitted when particle system starts and ends on same frame * Depsgraph wasn't updated properly for smoke flow collision object dependencies. * Smoke also wasn't properly using the actual emission frame of the flow particles. * There was a lot of bloated logic in some parts of particle code so this fix turned into a small scale cleanup operation. ** As a result particle updating and cache usage should be a bit more stable too. --- source/blender/blenkernel/intern/particle.c | 17 +++-- source/blender/blenkernel/intern/particle_system.c | 81 ++++++++-------------- source/blender/blenkernel/intern/pointcache.c | 8 ++- source/blender/blenkernel/intern/smoke.c | 39 +++++++---- source/blender/modifiers/intern/MOD_smoke.c | 30 ++++++-- 5 files changed, 91 insertions(+), 84 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 187071941bf..a7506f2114b 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4193,11 +4193,11 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta if(pa) { if(!always) - if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0) - || (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0)) + if((cfra < pa->time && (part->flag & PART_UNBORN)==0) + || (cfra > pa->dietime && (part->flag & PART_DIED)==0)) return 0; - state->time = MIN2(state->time, pa->dietime); + cfra = MIN2(cfra, pa->dietime); } if(sim->psys->flag & PSYS_KEYED){ @@ -4223,16 +4223,15 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta calc_latt_deform(sim->psys->lattice, state->co,1.0f); } else{ - if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) - || pa->prev_state.time <= 0.0f) + if(pa->state.time==cfra || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)) copy_particle_key(state, &pa->state, 1); - else if(pa->prev_state.time==state->time) + else if(pa->prev_state.time==cfra) copy_particle_key(state, &pa->prev_state, 1); else { float dfra, frs_sec = sim->scene->r.frs_sec; /* let's interpolate to try to be as accurate as possible */ - if(pa->state.time + 2.0f >= state->time && pa->prev_state.time - 2.0f <= state->time) { - if(pa->prev_state.time >= pa->state.time) { + if(pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) { + if(pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) { /* prev_state is wrong so let's not use it, this can happen at frames 1, 0 or particle birth */ dfra = state->time - pa->state.time; @@ -4258,7 +4257,7 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ - mul_v3_fl(state->vel, 1.0f / (dfra * timestep)); + mul_v3_fl(state->vel, 1.f / (dfra * timestep)); interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime); interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 9eed401adbb..7e65cf26fd2 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3749,80 +3749,59 @@ static void system_step(ParticleSimulationData *sim, float cfra) ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; PointCache *cache = psys->pointcache; - PTCacheID pid, *use_cache = NULL; + PTCacheID ptcacheid, *pid = NULL; PARTICLE_P; - int oldtotpart; - float disp; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */ - int init= 0, emit= 0; //, only_children_changed= 0; - int framenr, framedelta, startframe = 0, endframe = 100; - - framenr= (int)sim->scene->r.cfra; - framedelta= framenr - cache->simframe; + float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */ + int startframe = 0, endframe = 100; /* cache shouldn't be used for hair or "continue physics" */ if(part->type != PART_HAIR && BKE_ptcache_get_continue_physics() == 0) { - BKE_ptcache_id_from_particles(&pid, sim->ob, psys); - use_cache = &pid; - } - - if(use_cache) { - psys_clear_temp_pointcache(sim->psys); + psys_clear_temp_pointcache(psys); /* set suitable cache range automatically */ if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0) - psys_get_pointcache_start_end(sim->scene, sim->psys, &cache->startframe, &cache->endframe); + psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe); + + pid = &ptcacheid; + BKE_ptcache_id_from_particles(pid, sim->ob, psys); - BKE_ptcache_id_time(&pid, sim->scene, 0.0f, &startframe, &endframe, NULL); + BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL); - /* simulation is only active during a specific period */ - if(framenr < startframe) { - BKE_ptcache_read_cache(use_cache, startframe, sim->scene->r.frs_sec); - /* set correct particle state and reset particles */ - cached_step(sim, cfra); - return; - } - else if(framenr > endframe) { - framenr= endframe; - } - else if(framenr == startframe) { - BKE_ptcache_id_reset(sim->scene, use_cache, PTCACHE_RESET_OUTDATED); - BKE_ptcache_validate(cache, framenr); + /* clear everythin on start frame */ + if((int)cfra == startframe) { + BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_validate(cache, startframe); cache->flag &= ~PTCACHE_REDO_NEEDED; } + + CLAMP(cache_cfra, startframe, endframe); } -/* 1. emit particles */ - - /* verify if we need to reallocate */ - oldtotpart = psys->totpart; - - emit = emit_particles(sim, use_cache, cfra); - if(use_cache && emit > 0) - BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, cfra); - init = emit*emit + (psys->recalc & PSYS_RECALC_RESET); - - if(init) { +/* 1. emit particles and redo particles if needed */ + if(emit_particles(sim, pid, cfra) || psys->recalc & PSYS_RECALC_RESET) { distribute_particles(sim, part->from); initialize_all_particles(sim); - reset_all_particles(sim, 0.0, cfra, oldtotpart); + reset_all_particles(sim, 0.0, cfra, 0); /* flag for possible explode modifiers after this system */ sim->psmd->flag |= eParticleSystemFlag_Pars; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); } /* 2. try to read from the cache */ - if(use_cache) { - int cache_result = BKE_ptcache_read_cache(use_cache, cfra, sim->scene->r.frs_sec); + if(pid) { + int cache_result = BKE_ptcache_read_cache(pid, cache_cfra, sim->scene->r.frs_sec); 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); + BKE_ptcache_validate(cache, (int)cache_cfra); if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) - BKE_ptcache_write_cache(use_cache, framenr); + BKE_ptcache_write_cache(pid, (int)cache_cfra); return; } @@ -3837,7 +3816,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) /* if on second frame, write cache for first frame */ if(psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write_cache(use_cache, startframe); + BKE_ptcache_write_cache(pid, startframe); } else BKE_ptcache_invalidate(cache); @@ -3860,7 +3839,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) /* handle negative frame start at the first frame by doing * all the steps before the first frame */ - if(framenr == startframe && part->sta < startframe) + if((int)cfra == startframe && part->sta < startframe) totframesback = (startframe - (int)part->sta); for(dframe=-totframesback; dframe<=0; dframe++) { @@ -3875,10 +3854,10 @@ static void system_step(ParticleSimulationData *sim, float cfra) } /* 4. only write cache starting from second frame */ - if(use_cache) { - BKE_ptcache_validate(cache, framenr); - if(framenr != startframe) - BKE_ptcache_write_cache(use_cache, framenr); + if(pid) { + BKE_ptcache_validate(cache, (int)cache_cfra); + if((int)cache_cfra != startframe) + BKE_ptcache_write_cache(pid, (int)cache_cfra); } update_children(sim); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 4711e61c767..c43f53cc4af 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -1883,8 +1883,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) { int len; /* store the length of the string */ int i; - int sta = pid->cache->startframe; - int end = pid->cache->endframe; + int sta, end; /* mode is same as fopen's modes */ DIR *dir; @@ -1894,9 +1893,12 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) char path_full[MAX_PTCACHE_FILE]; char ext[MAX_PTCACHE_PATH]; - if(!pid->cache || pid->cache->flag & PTCACHE_BAKED) + if(!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) return; + sta = pid->cache->startframe; + end = pid->cache->endframe; + #ifndef DURIAN_POINTCACHE_LIB_OK /* don't allow clearing for linked objects */ if(pid->ob->id.lib) diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 1833cc4eeac..08871cfeec7 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -973,9 +973,9 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) if(sfs && sfs->psys && sfs->psys->part && sfs->psys->part->type==PART_EMITTER) // is particle system selected { + ParticleSimulationData sim; ParticleSystem *psys = sfs->psys; ParticleSettings *part=psys->part; - ParticleData *pa = NULL; int p = 0; float *density = smoke_get_density(sds->fluid); float *bigdensity = smoke_turbulence_get_density(sds->wt); @@ -995,6 +995,10 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) */ float *temp_emission_map = NULL; + sim.scene = scene; + sim.ob = otherobj; + sim.psys = psys; + // initialize temp emission map if(!(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW)) { @@ -1007,19 +1011,26 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) } // mostly copied from particle code - for(p=0, pa=psys->particles; ptotpart; p++, pa++) - { - int cell[3]; - size_t i = 0; - size_t index = 0; - int badcell = 0; - if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0) continue; - else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0) continue; - else if(pa->flag & (PARS_UNEXIST+PARS_NO_DISP)) continue; + for(p=0; ptotpart; p++) + { + int cell[3]; + size_t i = 0; + size_t index = 0; + int badcell = 0; + ParticleKey state; + + if(psys->particles[p].flag & (PARS_NO_DISP|PARS_UNEXIST)) + continue; + + state.time = smd->time; + + if(psys_get_particle_state(&sim, p, &state, 0) == 0) + continue; + // VECCOPY(pos, pa->state.co); // mul_m4_v3(ob->imat, pos); // 1. get corresponding cell - get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, pa->state.co, cell, 0); + get_cell(smd->domain->p0, smd->domain->res, smd->domain->dx, state.co, cell, 0); // check if cell is valid (in the domain boundary) for(i = 0; i < 3; i++) { @@ -1045,9 +1056,9 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd) // Uses particle velocity as initial velocity for smoke if(sfs->flags & MOD_SMOKE_FLOW_INITVELOCITY && (psys->part->phystype != PART_PHYS_NO)) { - velocity_x[index] = pa->state.vel[0]*sfs->vel_multi; - velocity_y[index] = pa->state.vel[1]*sfs->vel_multi; - velocity_z[index] = pa->state.vel[2]*sfs->vel_multi; + velocity_x[index] = state.vel[0]*sfs->vel_multi; + velocity_y[index] = state.vel[1]*sfs->vel_multi; + velocity_z[index] = state.vel[2]*sfs->vel_multi; } } else if(sfs->type & MOD_SMOKE_FLOW_TYPE_OUTFLOW) // outflow diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index a183018da30..91197376ae9 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -34,7 +34,10 @@ #include "MEM_guardedalloc.h" +#include "DNA_group_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_smoke_types.h" #include "BKE_utildefines.h" #include "BKE_cdderivedmesh.h" @@ -93,12 +96,13 @@ static int dependsOnTime(ModifierData *UNUSED(md)) return 1; } -static void updateDepgraph(ModifierData *UNUSED(md), DagForest *UNUSED(forest), - struct Scene *UNUSED(scene), - Object *UNUSED(ob), - DagNode *UNUSED(obNode)) +static void updateDepgraph(ModifierData *md, DagForest *forest, + struct Scene *scene, + Object *ob, + DagNode *obNode) { - /*SmokeModifierData *smd = (SmokeModifierData *) md; + SmokeModifierData *smd = (SmokeModifierData *) md; + if(smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) { if(smd->domain->fluid_group) @@ -112,7 +116,7 @@ static void updateDepgraph(ModifierData *UNUSED(md), DagForest *UNUSED(forest), SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(go->ob, eModifierType_Smoke); // check for initialized smoke object - if(smd2 && (smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) + if(smd2 && (((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) || ((smd->type & MOD_SMOKE_TYPE_COLL) && smd2->coll))) { DagNode *curNode = dag_get_node(forest, go->ob); dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Smoke Flow"); @@ -120,8 +124,20 @@ static void updateDepgraph(ModifierData *UNUSED(md), DagForest *UNUSED(forest), } } } + else { + Base *base = scene->base.first; + + for(; base; base = base->next) { + SmokeModifierData *smd2 = (SmokeModifierData *)modifiers_findByType(base->object, eModifierType_Smoke); + + if(smd2 && (((smd2->type & MOD_SMOKE_TYPE_FLOW) && smd2->flow) || ((smd->type & MOD_SMOKE_TYPE_COLL) && smd2->coll))) + { + DagNode *curNode = dag_get_node(forest, base->object); + dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Smoke Flow"); + } + } + } } - */ } -- cgit v1.2.3