Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-04-14 09:58:15 +0300
committerPhilipp Oeser <info@graphics-engineer.com>2022-04-19 16:58:43 +0300
commitd0bcb6efead49a269d3b9b6f29ef07f5241fa137 (patch)
tree3888a05e83add9f14a24ef5600d15e2510c66ed3
parent7dd15b7113493f002401ee3447a0b52d09889eaf (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.
-rw-r--r--source/blender/blenkernel/intern/particle.c25
-rw-r--r--source/blender/blenkernel/intern/pointcache.c23
-rw-r--r--source/blender/makesdna/DNA_particle_types.h7
3 files changed, 37 insertions, 18 deletions
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index ae685357151..544c80ebc7b 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -1254,7 +1254,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;
/**
@@ -1316,15 +1318,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;
}
@@ -1332,7 +1334,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;
}
@@ -1348,7 +1351,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;
}
}
@@ -1379,14 +1384,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 17434ee8023..98430bc422c 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -300,8 +300,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;
}
}
@@ -414,9 +416,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;
}
@@ -497,12 +502,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 cc40e26b92b..570a2f7cffd 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -123,7 +123,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;
/**