[Bf-blender-cvs] [b6f49ec208d] new-object-types: Volumes: API functions to modify grids in the modifiers stack

Brecht Van Lommel noreply at git.blender.org
Mon Feb 10 14:37:58 CET 2020


Commit: b6f49ec208d91da29c6fb1e67b5f37308c10b666
Author: Brecht Van Lommel
Date:   Sun Feb 9 17:25:11 2020 +0100
Branches: new-object-types
https://developer.blender.org/rBb6f49ec208d91da29c6fb1e67b5f37308c10b666

Volumes: API functions to modify grids in the modifiers stack

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

M	source/blender/blenkernel/BKE_volume.h
M	source/blender/blenkernel/intern/volume.cc

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

diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h
index a76996afe20..cf0260b417b 100644
--- a/source/blender/blenkernel/BKE_volume.h
+++ b/source/blender/blenkernel/BKE_volume.h
@@ -60,9 +60,6 @@ struct BoundBox *BKE_volume_boundbox_get(struct Object *ob);
 
 /* Depsgraph */
 
-struct Volume *BKE_volume_new_for_eval(const struct Volume *volume_src);
-struct Volume *BKE_volume_copy_for_eval(struct Volume *volume_src, bool reference);
-
 void BKE_volume_eval_geometry(struct Depsgraph *depsgraph, struct Volume *volume);
 void BKE_volume_data_update(struct Depsgraph *depsgraph,
                             struct Scene *scene,
@@ -105,7 +102,7 @@ VolumeGrid *BKE_volume_grid_find(struct Volume *volume, const char *name);
 /* Grid
  *
  * By default only grid metadata is loaded, for access to the tree and voxels
- * the BKE_volume_grid_load must be called first. */
+ * BKE_volume_grid_load must be called first. */
 
 typedef enum VolumeGridType {
   VOLUME_GRID_UNKNOWN = 0,
@@ -146,8 +143,44 @@ void BKE_volume_grid_dense_voxels(const struct VolumeGrid *volume_grid,
                                   const size_t max[3],
                                   float *voxels);
 
+/* Volume Editing
+ *
+ * These are intended for modifiers to use on evaluated datablocks.
+ *
+ * new_for_eval creates a volume datablock with no grids or file path, but
+ * preserves other settings such as viewport display options.
+ *
+ * copy_for_eval creates a volume datablock preserving everything except the
+ * file path. Grids are shared with the source datablock, not copied.
+ *
+ * Before modifying grids after copy_for_eval, call ensure_writable first.
+ * It will duplicate (or clear) the grid if it is shared with any other
+ * datablocks, so that it can be safely modified. */
+
+struct Volume *BKE_volume_new_for_eval(const struct Volume *volume_src);
+struct Volume *BKE_volume_copy_for_eval(struct Volume *volume_src, bool reference);
+
+struct VolumeGrid *BKE_volume_grid_add(struct Volume *volume,
+                                       const char *name,
+                                       VolumeGridType type);
+void BKE_volume_grid_remove(struct Volume *volume, struct VolumeGrid *grid);
+void BKE_volume_grid_ensure_writable(struct Volume *volume,
+                                     struct VolumeGrid *grid,
+                                     const bool clear);
+
 #ifdef __cplusplus
 }
 #endif
 
+/* OpenVDB Grid
+ *
+ * Access to OpenVDB grid for C++. This will call BKE_volume_grid_load if the
+ * grid has not already been loaded into memory. */
+
+#if defined(__cplusplus) && defined(WITH_OPENVDB)
+#  include <openvdb/openvdb.h>
+openvdb::GridBase::Ptr BKE_volume_grid_ensure_openvdb(struct Volume *volume,
+                                                      struct VolumeGrid *grid);
+#endif
+
 #endif
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index dfc485596a5..a5622323f68 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -58,6 +58,7 @@ static CLG_LogRef LOG = {"bke.volume"};
 
 #ifdef WITH_OPENVDB
 #  include <atomic>
+#  include <list>
 #  include <mutex>
 #  include <unordered_set>
 
@@ -328,6 +329,31 @@ struct VolumeGrid {
     is_loaded = false;
   }
 
+  void clear_reference(const char *UNUSED(volume_name))
+  {
+    /* Clear any reference to a grid in the file cache. */
+    vdb = vdb->copyGridWithNewTree();
+    if (entry) {
+      GLOBAL_CACHE.remove_user(*entry, is_loaded);
+      entry = NULL;
+    }
+    is_loaded = true;
+  }
+
+  void duplicate_reference(const char *volume_name, const char *filepath)
+  {
+    /* Make a deep copy of the grid and remove any reference to a grid in the
+     * file cache. Load file grid into memory first if needed. */
+    load(volume_name, filepath);
+    // TODO: avoid deep copy if we are the only user
+    vdb = vdb->deepCopyGrid();
+    if (entry) {
+      GLOBAL_CACHE.remove_user(*entry, is_loaded);
+      entry = NULL;
+    }
+    is_loaded = true;
+  }
+
   const char *name() const
   {
     /* Don't use vdb.getName() since it copies the string, we want a pointer to the
@@ -362,7 +388,7 @@ struct VolumeGrid {
  * List of grids contained in a volume datablock. This is runtime-only data,
  * the actual grids are always saved in a VDB file. */
 
-struct VolumeGridVector : public std::vector<VolumeGrid> {
+struct VolumeGridVector : public std::list<VolumeGrid> {
   VolumeGridVector()
   {
     filepath[0] = '\0';
@@ -710,33 +736,6 @@ BoundBox *BKE_volume_boundbox_get(Object *ob)
 
 /* Dependency Graph */
 
-Volume *BKE_volume_new_for_eval(const Volume *volume_src)
-{
-  Volume *volume_dst = (Volume *)BKE_id_new_nomain(ID_VO, NULL);
-
-  STRNCPY(volume_dst->id.name, volume_src->id.name);
-  volume_dst->mat = (Material **)MEM_dupallocN(volume_src->mat);
-  volume_dst->totcol = volume_src->totcol;
-  BKE_volume_init_grids(volume_dst);
-
-  return volume_dst;
-}
-
-Volume *BKE_volume_copy_for_eval(Volume *volume_src, bool reference)
-{
-  int flags = LIB_ID_COPY_LOCALIZE;
-
-  if (reference) {
-    flags |= LIB_ID_COPY_CD_REFERENCE;
-  }
-
-  Volume *result;
-  BKE_id_copy_ex(NULL, &volume_src->id, (ID **)&result, flags);
-  result->filepath[0] = '\0';
-
-  return result;
-}
-
 static Volume *volume_evaluate_modifiers(struct Depsgraph *depsgraph,
                                          struct Scene *scene,
                                          Object *object,
@@ -886,7 +885,13 @@ const char *BKE_volume_grids_error_msg(const Volume *volume)
 VolumeGrid *BKE_volume_grid_get(Volume *volume, int grid_index)
 {
 #ifdef WITH_OPENVDB
-  return &volume->runtime.grids->at(grid_index);
+  VolumeGridVector &grids = *volume->runtime.grids;
+  for (VolumeGrid &grid : grids) {
+    if (grid_index-- == 0) {
+      return &grid;
+    }
+  }
+  return NULL;
 #else
   UNUSED_VARS(volume, grid_index);
   return NULL;
@@ -1226,3 +1231,122 @@ void BKE_volume_grid_dense_voxels(const VolumeGrid *volume_grid,
   UNUSED_VARS(volume_grid, min, max, voxels);
 #endif
 }
+
+/* Volume Editing */
+
+Volume *BKE_volume_new_for_eval(const Volume *volume_src)
+{
+  Volume *volume_dst = (Volume *)BKE_id_new_nomain(ID_VO, NULL);
+
+  STRNCPY(volume_dst->id.name, volume_src->id.name);
+  volume_dst->mat = (Material **)MEM_dupallocN(volume_src->mat);
+  volume_dst->totcol = volume_src->totcol;
+  BKE_volume_init_grids(volume_dst);
+
+  return volume_dst;
+}
+
+Volume *BKE_volume_copy_for_eval(Volume *volume_src, bool reference)
+{
+  int flags = LIB_ID_COPY_LOCALIZE;
+
+  if (reference) {
+    flags |= LIB_ID_COPY_CD_REFERENCE;
+  }
+
+  Volume *result;
+  BKE_id_copy_ex(NULL, &volume_src->id, (ID **)&result, flags);
+  result->filepath[0] = '\0';
+
+  return result;
+}
+
+VolumeGrid *BKE_volume_grid_add(Volume *volume, const char *name, VolumeGridType type)
+{
+#ifdef WITH_OPENVDB
+  VolumeGridVector &grids = *volume->runtime.grids;
+  BLI_assert(BKE_volume_grid_find(volume, name) == NULL);
+
+  openvdb::GridBase::Ptr vdb_grid;
+  switch (type) {
+    case VOLUME_GRID_FLOAT:
+      vdb_grid = openvdb::FloatGrid::create();
+      break;
+    case VOLUME_GRID_VECTOR_FLOAT:
+      vdb_grid = openvdb::Vec3fGrid::create();
+      break;
+    case VOLUME_GRID_BOOLEAN:
+      vdb_grid = openvdb::BoolGrid::create();
+      break;
+    case VOLUME_GRID_DOUBLE:
+      vdb_grid = openvdb::DoubleGrid::create();
+      break;
+    case VOLUME_GRID_INT:
+      vdb_grid = openvdb::Int32Grid::create();
+      break;
+    case VOLUME_GRID_INT64:
+      vdb_grid = openvdb::Int64Grid::create();
+      break;
+    case VOLUME_GRID_VECTOR_INT:
+      vdb_grid = openvdb::Vec3IGrid::create();
+      break;
+    case VOLUME_GRID_VECTOR_DOUBLE:
+      vdb_grid = openvdb::Vec3dGrid::create();
+      break;
+    case VOLUME_GRID_STRING:
+      vdb_grid = openvdb::StringGrid::create();
+      break;
+    case VOLUME_GRID_MASK:
+      vdb_grid = openvdb::MaskGrid::create();
+      break;
+    case VOLUME_GRID_UNKNOWN:
+      return NULL;
+  }
+
+  vdb_grid->setName(name);
+  grids.emplace_back(vdb_grid);
+  return &grids.back();
+#else
+  UNUSED_VARS(volume, name, type);
+  return NULL;
+#endif
+}
+
+void BKE_volume_grid_remove(Volume *volume, VolumeGrid *grid)
+{
+#ifdef WITH_OPENVDB
+  VolumeGridVector &grids = *volume->runtime.grids;
+  for (VolumeGridVector::iterator it = grids.begin(); it != grids.end(); it++) {
+    if (&*it == grid) {
+      grids.erase(it);
+      break;
+    }
+  }
+#else
+  UNUSED_VARS(volume, grid);
+#endif
+}
+
+void BKE_volume_grid_ensure_writable(Volume *volume, VolumeGrid *grid, bool clear)
+{
+#ifdef WITH_OPENVDB
+  const char *volume_name = volume->id.name + 2;
+  if (clear) {
+    grid->clear_reference(volume_name);
+  }
+  else {
+    VolumeGridVector &grids = *volume->runtime.grids;
+    grid->duplicate_reference(volume_name, grids.filepath);
+  }
+#else
+  UNUSED_VARS(volume, grid);
+#endif
+}
+
+#ifdef WITH_OPENVDB
+openvdb::GridBase::Ptr BKE_volume_grid_ensure_openvdb(Volume *volume, VolumeGrid *grid)
+{
+  BKE_volume_grid_load(volume, grid);
+  return grid->vdb;
+}
+#endif



More information about the Bf-blender-cvs mailing list