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.
This commit is contained in:
Janne Karhu
2010-12-15 17:05:34 +00:00
parent 2c55dd96ad
commit 6b2b56c35e
5 changed files with 92 additions and 85 deletions

View File

@@ -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);

View File

@@ -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);
BKE_ptcache_id_time(&pid, sim->scene, 0.0f, &startframe, &endframe, NULL);
psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe);
/* 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);
pid = &ptcacheid;
BKE_ptcache_id_from_particles(pid, sim->ob, psys);
BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL);
/* 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);

View File

@@ -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)

View File

@@ -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; p<psys->totpart; 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; p<psys->totpart; 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

View File

@@ -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");
}
}
}
}
*/
}