[Bf-blender-cvs] [d0bcb6efead] blender-v2.93-release: Fix T68290: Baked particles don't render in final frame

Campbell Barton noreply at git.blender.org
Tue Apr 19 16:27:20 CEST 2022


Commit: d0bcb6efead49a269d3b9b6f29ef07f5241fa137
Author: Campbell Barton
Date:   Thu Apr 14 16:58:15 2022 +1000
Branches: blender-v2.93-release
https://developer.blender.org/rBd0bcb6efead49a269d3b9b6f29ef07f5241fa137

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.

===================================================================

M	source/blender/blenkernel/intern/particle.c
M	source/blender/blenkernel/intern/pointcache.c
M	source/blender/makesdna/DNA_particle_types.h

===================================================================

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;
 
   /**



More information about the Bf-blender-cvs mailing list