diff options
author | Campbell Barton <campbell@blender.org> | 2022-04-14 09:58:15 +0300 |
---|---|---|
committer | Campbell Barton <campbell@blender.org> | 2022-04-14 09:58:15 +0300 |
commit | 405bff7fd8ed5df8d44a1362763fac7c00e2060b (patch) | |
tree | 8293e05a1ebb0774bba60157a985f3a2de9bff62 /source | |
parent | bc8dcf6db7698505d61d9bd2c010b187b909704c (diff) |
Fix T68290: Baked particles don't render in final frame
Particles baked into memory would never load the final frame because
of an off-by-one error calculating the particles `dietime`.
This value indicates the frame which the particle ceases to exist but
was being set to the end-frame which caused this bug as the scenes
end-frame is inclusive.
While the last frame was properly written and read from memory,
the `dietime` was set to the last frame causing all the particles to be
considered dead when calculating the cached particle system.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 25 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 23 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_particle_types.h | 7 |
3 files changed, 37 insertions, 18 deletions
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 9ea1336a95a..500596e6d42 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1249,7 +1249,9 @@ typedef struct ParticleInterpolationData { PTCacheEditPoint *epoint; PTCacheEditKey *ekey[2]; - float birthtime, dietime; + float birthtime; + /** Die on this frame, see #ParticleData.dietime for details. */ + float dietime; int bspline; } ParticleInterpolationData; /** @@ -1311,15 +1313,15 @@ static void get_pointcache_keys_for_time(Object *UNUSED(ob), } static int get_pointcache_times_for_particle(PointCache *cache, int index, - float *start, - float *end) + float *r_start, + float *r_dietime) { PTCacheMem *pm; int ret = 0; for (pm = cache->mem_cache.first; pm; pm = pm->next) { if (BKE_ptcache_mem_index_find(pm, index) >= 0) { - *start = pm->frame; + *r_start = pm->frame; ret++; break; } @@ -1327,7 +1329,8 @@ static int get_pointcache_times_for_particle(PointCache *cache, for (pm = cache->mem_cache.last; pm; pm = pm->prev) { if (BKE_ptcache_mem_index_find(pm, index) >= 0) { - *end = pm->frame; + /* Die *after* the last available frame. */ + *r_dietime = pm->frame + 1; ret++; break; } @@ -1343,7 +1346,9 @@ float psys_get_dietime_from_cache(PointCache *cache, int index) for (pm = cache->mem_cache.last; pm; pm = pm->prev) { if (BKE_ptcache_mem_index_find(pm, index) >= 0) { - return (float)pm->frame; + /* Die *after* the last available frame. */ + dietime = pm->frame + 1; + break; } } @@ -1374,14 +1379,14 @@ static void init_particle_interpolation(Object *ob, pind->dietime = (key + pa->totkey - 1)->time; } else if (pind->cache) { - float start = 0.0f, end = 0.0f; + float start = 0.0f, dietime = 0.0f; get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL); pind->birthtime = pa ? pa->time : pind->cache->startframe; - pind->dietime = pa ? pa->dietime : pind->cache->endframe; + pind->dietime = pa ? pa->dietime : (pind->cache->endframe + 1); - if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &end)) { + if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &dietime)) { pind->birthtime = MAX2(pind->birthtime, start); - pind->dietime = MIN2(pind->dietime, end); + pind->dietime = MIN2(pind->dietime, dietime + 1); } } else { diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 19abff19b77..d5d304343df 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -285,8 +285,10 @@ static int ptcache_particle_write(int index, void *psys_v, void **data, int cfra } } else { - /* Particles are only stored in their lifetime. */ - if (cfra < pa->time - step || cfra > pa->dietime + step) { + /* Inclusive ranges for particle lifetime (`dietime - 1` for an inclusive end-frame). */ + const int pa_sfra = (int)pa->time - step; + const int pa_efra = ((int)pa->dietime - 1) + step; + if (!(cfra >= pa_sfra && cfra <= pa_efra)) { return 0; } } @@ -399,9 +401,12 @@ static void ptcache_particle_interpolate(int index, pa = psys->particles + index; - /* particle wasn't read from first cache so can't interpolate */ - if ((int)cfra1 < pa->time - psys->pointcache->step || - (int)cfra1 > pa->dietime + psys->pointcache->step) { + /* Inclusive ranges for particle lifetime (`dietime - 1` for an inclusive end-frame). */ + const int pa_sfra = (int)pa->time - psys->pointcache->step; + const int pa_efra = ((int)pa->dietime - 1) + psys->pointcache->step; + + /* Particle wasn't read from first cache so can't interpolate. */ + if (!(cfra1 >= pa_sfra && cfra1 <= pa_efra)) { return; } @@ -482,12 +487,16 @@ static int ptcache_particle_totwrite(void *psys_v, int cfra) if (psys->part->flag & PART_DIED) { /* Also store dead particles when they are displayed. */ for (p = 0; p < psys->totpart; p++, pa++) { - totwrite += (cfra >= pa->time - step); + const int pa_sfra = (int)pa->time - step; + totwrite += (cfra >= pa_sfra); } } else { for (p = 0; p < psys->totpart; p++, pa++) { - totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step); + /* Inclusive ranges for particle lifetime (`dietime - 1` for an inclusive end-frame). */ + const int pa_sfra = (int)pa->time - step; + const int pa_efra = ((int)pa->dietime - 1) + step; + totwrite += (cfra >= pa_sfra) && (cfra <= pa_efra); } } diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index f3d342e4849..268e1412eef 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -109,7 +109,12 @@ typedef struct ParticleData { /** Die-time is not necessarily time+lifetime as. */ float time, lifetime; - /** Particles can die unnaturally (collision). */ + /** + * Particles can die unnaturally (collision). + * + * \note Particles die on this frame, be sure to add 1 when clamping the lifetime of particles + * to inclusive ranges such as the scenes end frame. See: T68290. + */ float dietime; /** |