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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user