[Bf-blender-cvs] [b1c93c8608d] new-object-types: Volume: basic on-demand reading of grid tree

Brecht Van Lommel noreply at git.blender.org
Sun Jan 26 19:44:59 CET 2020


Commit: b1c93c8608d784a65a14d074d51cd9b61dc48198
Author: Brecht Van Lommel
Date:   Sun Jan 26 16:52:01 2020 +0100
Branches: new-object-types
https://developer.blender.org/rBb1c93c8608d784a65a14d074d51cd9b61dc48198

Volume: basic on-demand reading of grid tree

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

M	source/blender/blenkernel/BKE_volume.h
M	source/blender/blenkernel/intern/volume.cc
M	source/blender/blenloader/intern/readfile.c

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

diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h
index f984463672e..5e66085ff21 100644
--- a/source/blender/blenkernel/BKE_volume.h
+++ b/source/blender/blenkernel/BKE_volume.h
@@ -77,7 +77,7 @@ extern void (*BKE_volume_batch_cache_free_cb)(struct Volume *volume);
 /* Grids
  *
  * When accessing a grid, it must be specified if the grid will be used for
- * reading only metadata, reading metadata and voxels or full read/write.
+ * reading only metadata, or reading metadata and voxels.
  *
  * This makes it possible to load just the required data on-demand, and share
  * grids between volumes for copy-on-write. */
@@ -85,16 +85,15 @@ extern void (*BKE_volume_batch_cache_free_cb)(struct Volume *volume);
 typedef struct VolumeGrid VolumeGrid;
 
 int BKE_volume_num_grids(struct Volume *volume);
-const VolumeGrid *BKE_volume_grid_for_metadata(struct Volume *volume, int grid_index);
-const VolumeGrid *BKE_volume_grid_for_read(struct Volume *volume, int grid_index);
-VolumeGrid *BKE_volume_grid_for_write(struct Volume *volume, int grid_index);
 
 /* Grid Metadata */
 
+const VolumeGrid *BKE_volume_grid_for_metadata(struct Volume *volume, int grid_index);
 const char *BKE_volume_grid_name(const struct VolumeGrid *grid);
 
-/* Grid Voxels */
+/* Grid Tree and Voxels */
 
+const VolumeGrid *BKE_volume_grid_for_tree(struct Volume *volume, int grid_index);
 bool BKE_volume_grid_bounds(const struct VolumeGrid *grid, float min[3], float max[3]);
 
 #ifdef __cplusplus
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 89a9419f343..73113c70f9a 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -43,13 +43,29 @@
 #include "BKE_volume.h"
 
 #ifdef WITH_OPENVDB
+#  include <mutex>
 #  include <openvdb/openvdb.h>
 
 struct VolumeGrid {
+  VolumeGrid(const openvdb::GridBase::Ptr &vdb, const bool has_tree) : vdb(vdb), has_tree(has_tree)
+  {
+  }
+
+  VolumeGrid(const VolumeGrid &other) : vdb(other.vdb), has_tree(other.has_tree)
+  {
+  }
+
+  /* OpenVDB grid. */
   openvdb::GridBase::Ptr vdb;
+  /* Grid may have only metadata and no tree. */
+  bool has_tree;
+  /* Mutex for on-demand reading of tree. */
+  std::mutex mutex;
 };
 
 struct VolumeGridVector : public std::vector<VolumeGrid> {
+  /* Absolute file path to read voxels from on-demand. */
+  char filepath[FILE_MAX];
 };
 #endif
 
@@ -131,15 +147,14 @@ void BKE_volume_reload(Main *bmain, Volume *volume)
   volume->grids->clear();
 
   /* Get absolute file path. */
-  char filepath[FILE_MAX];
-  STRNCPY(filepath, volume->filepath);
-  BLI_path_abs(filepath, ID_BLEND_PATH(bmain, &volume->id));
+  STRNCPY(volume->grids->filepath, volume->filepath);
+  BLI_path_abs(volume->grids->filepath, ID_BLEND_PATH(bmain, &volume->id));
 
   /* TODO: move this to a better place. */
   openvdb::initialize();
 
   /* Open OpenVDB file. */
-  openvdb::io::File file(filepath);
+  openvdb::io::File file(volume->grids->filepath);
   openvdb::GridPtrVec vdb_grids;
 
   try {
@@ -155,9 +170,7 @@ void BKE_volume_reload(Main *bmain, Volume *volume)
   /* Add grids read from file to own vector, filtering out any NULL pointers. */
   for (const openvdb::GridBase::Ptr vdb_grid : vdb_grids) {
     if (vdb_grid) {
-      VolumeGrid grid;
-      grid.vdb = vdb_grid;
-      volume->grids->push_back(std::move(grid));
+      volume->grids->emplace_back(vdb_grid, false);
     }
   }
 #else
@@ -187,12 +200,12 @@ BoundBox *BKE_volume_boundbox_get(Object *ob)
       /* TODO: this is quite expensive, how often is it computed? Is there a faster
        * way without actually reading grids? We should ensure copy-on-write does not
        * compute this over and over for static files. */
-      const VolumeGrid *grid = BKE_volume_grid_for_read(volume, i);
+      const VolumeGrid *grid = BKE_volume_grid_for_tree(volume, i);
       float grid_min[3], grid_max[3];
 
       if (BKE_volume_grid_bounds(grid, grid_min, grid_max)) {
-        DO_MIN(min, grid_min);
-        DO_MAX(max, grid_max);
+        DO_MIN(grid_min, min);
+        DO_MAX(grid_max, max);
         have_minmax = true;
       }
     }
@@ -285,22 +298,36 @@ const VolumeGrid *BKE_volume_grid_for_metadata(Volume *volume, int grid_index)
 #endif
 }
 
-const VolumeGrid *BKE_volume_grid_for_read(Volume *volume, int grid_index)
+const VolumeGrid *BKE_volume_grid_for_tree(Volume *volume, int grid_index)
 {
 #ifdef WITH_OPENVDB
-  /* TODO: implement */
-  return BKE_volume_grid_for_metadata(volume, grid_index);
-#else
-  UNUSED_VARS(volume, grid_index);
-  return NULL;
-#endif
-}
+  VolumeGrid &grid = volume->grids->at(grid_index);
+
+  if (!grid.has_tree) {
+    std::lock_guard<std::mutex> lock(grid.mutex);
+
+    if (!grid.has_tree) {
+      /* Read OpenVDB grid on-demand. */
+      /* TODO: avoid repeating this for multiple grids when we know we will
+       * need them? How best to do it without keeping the file open forever? */
+      openvdb::io::File file(volume->grids->filepath);
+      openvdb::GridPtrVec vdb_grids;
+
+      try {
+        file.setCopyMaxBytes(0);
+        file.open();
+        grid.vdb = file.readGrid(grid.vdb->getName());
+      }
+      catch (const openvdb::IoError &e) {
+        /* TODO: log error with clog. */
+        std::cerr << e.what() << '\n';
+      }
 
-VolumeGrid *BKE_volume_grid_for_write(Volume *volume, int grid_index)
-{
-#ifdef WITH_OPENVDB
-  /* TODO: implement */
-  return (VolumeGrid *)BKE_volume_grid_for_metadata(volume, grid_index);
+      grid.has_tree = true;
+    }
+  }
+
+  return &grid;
 #else
   UNUSED_VARS(volume, grid_index);
   return NULL;
@@ -324,12 +351,14 @@ const char *BKE_volume_grid_name(const VolumeGrid *volume_grid)
 #endif
 }
 
-/* Grid Voxels */
+/* Grid Tree and Voxels */
 
 bool BKE_volume_grid_bounds(const VolumeGrid *volume_grid, float min[3], float max[3])
 {
 #ifdef WITH_OPENVDB
   const openvdb::GridBase::Ptr &grid = volume_grid->vdb;
+  BLI_assert(volume_grid->has_tree);
+
   if (grid->empty()) {
     INIT_MINMAX(min, max);
     return false;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1bf2c2453f6..9c7dd9b3192 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -9328,7 +9328,7 @@ static void direct_link_volume(FileData *fd, Volume *volume)
 
   volume->packedfile = direct_link_packedfile(fd, volume->packedfile);
   volume->grids = (fd->volumemap) ? newvolumeadr(fd, volume->grids) : NULL;
-  BKE_volume_init_grids(volume->grids);
+  BKE_volume_init_grids(volume);
 
   /* materials */
   volume->mat = newdataadr(fd, volume->mat);



More information about the Bf-blender-cvs mailing list