[Bf-blender-cvs] [c2a632cd410] geometry-nodes-simulation: Basic working simulation and in-memory caching

Hans Goudey noreply at git.blender.org
Thu Nov 24 00:20:06 CET 2022


Commit: c2a632cd4103eba2a7db7b191d4a80589639921b
Author: Hans Goudey
Date:   Wed Nov 23 17:19:25 2022 -0600
Branches: geometry-nodes-simulation
https://developer.blender.org/rBc2a632cd4103eba2a7db7b191d4a80589639921b

Basic working simulation and in-memory caching

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

M	source/blender/blenkernel/BKE_compute_cache.hh
M	source/blender/nodes/geometry/nodes/node_geo_simulation_input.cc
M	source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc

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

diff --git a/source/blender/blenkernel/BKE_compute_cache.hh b/source/blender/blenkernel/BKE_compute_cache.hh
index 7fd0d6225c7..33b7f7f3b59 100644
--- a/source/blender/blenkernel/BKE_compute_cache.hh
+++ b/source/blender/blenkernel/BKE_compute_cache.hh
@@ -17,6 +17,7 @@ struct GeometryCacheValue {
   GeometrySet geometry_set;
 };
 
+/* TODO: Clear cache when editing nodes? Only sometimes, when persistent caching is turned off. */
 struct SimulationCache {
   Vector<GeometryCacheValue> geometry_per_frame;
 
@@ -29,6 +30,15 @@ struct SimulationCache {
     return &geometry_per_frame[index];
   }
 
+  GeometryCacheValue *value_at_or_before_time(const int frame)
+  {
+    const int index = this->index_at_or_before_time(frame);
+    if (index >= geometry_per_frame.size()) {
+      return nullptr;
+    }
+    return &geometry_per_frame[index];
+  }
+
   const GeometryCacheValue *value_before_time(const int frame) const
   {
     const int index = this->index_before_time(frame);
@@ -80,7 +90,7 @@ struct SimulationCache {
     }
     int insert_index = 0;
     for (const int i : geometry_per_frame.index_range()) {
-      if (geometry_per_frame[i].frame >= frame) {
+      if (geometry_per_frame[i].frame <= frame) {
         break;
       }
       insert_index++;
@@ -94,7 +104,7 @@ struct SimulationCache {
     }
     int insert_index = 0;
     for (const int i : geometry_per_frame.index_range()) {
-      if (geometry_per_frame[i].frame > frame) {
+      if (geometry_per_frame[i].frame < frame) {
         break;
       }
       insert_index++;
@@ -121,6 +131,10 @@ struct ComputeCaches {
     return cache_per_context.lookup_ptr(context_hash);
   }
 
+  /* TODO: Do we need to use the same context for multiple simulation inputs and outputs in the
+   * same node group? If so this won't work at all-- we would need some way to link the two nodes,
+   * which might be necessary for the "Run" socket anyway, since it needs to know whether the
+   * simulation is running in order to know whether to use the last cache or request a new one. */
   SimulationCache &ensure_for_context(const ComputeContextHash &context_hash)
   {
     std::scoped_lock lock{mutex};
diff --git a/source/blender/nodes/geometry/nodes/node_geo_simulation_input.cc b/source/blender/nodes/geometry/nodes/node_geo_simulation_input.cc
index fc3901f359e..2d6a13de980 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_simulation_input.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_simulation_input.cc
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 
+#include "BKE_compute_cache.hh"
 #include "BKE_scene.h"
 
 #include "DEG_depsgraph_query.h"
@@ -34,7 +35,8 @@ static void node_geo_exec(GeoNodeExecParams params)
   const float scene_ctime = BKE_scene_ctime_get(scene);
   const int scene_frame = int(scene_ctime);
 
-  /* TODO: Somehow use "Run" input. */
+  /* TODO: Somehow use "Run" input. We also need to pass through the simulation state directly to
+   * the output node on the first frame the "Run" input is true. */
 
   const GeoNodesLFUserData &lf_data = *params.user_data();
   bke::ComputeCaches &all_caches = *lf_data.modifier_data->cache_per_frame;
diff --git a/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc b/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc
index 5a0331cc2f1..a72d1f31983 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_simulation_output.cc
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-or-later */
 
+#include "BKE_compute_cache.hh"
 #include "BKE_scene.h"
 
 #include "DEG_depsgraph_query.h"
@@ -94,15 +95,19 @@ static void node_geo_exec(GeoNodeExecParams params)
 
   GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
   geometry_set.ensure_owns_direct_data();
-  if (storage.use_cache) {
+  /* TODO: The "Use cache" input should probably become a "Persistent Cache" option. */
+  if (storage.use_cache || cache.geometry_per_frame.is_empty()) {
+    /* If using the cache or there is no cached data yet, write the input in a new cache value. */
     cache.insert(geometry_set, scene_frame, scene_ctime);
   }
   else {
-    bke::GeometryCacheValue &data = cache.value_at_time_ensure(scene_frame);
-    data.frame = scene_frame;
-    data.geometry_set = geometry_set;
+    /* If we aren't using the cache, overrite the cache to only store the last frame. */
     /* TODO: This breaks the elapsed time. */
-    data.time = scene_ctime;
+    /* TODO: Should we allow turning on and off caching procedurally? In that case we wouldn't be
+     * able to clear the whole cache, we would have to check if persistent caching was enabled for
+     * the *last* frame and then decide to replace it or not. */
+    cache.geometry_per_frame.clear();
+    cache.insert(geometry_set, scene_frame, scene_ctime);
   }
 
   params.set_output("Geometry", std::move(geometry_set));



More information about the Bf-blender-cvs mailing list