[Bf-blender-cvs] [e893f5c61ac] new-object-types: Volumes: work on completing the grid access API

Brecht Van Lommel noreply at git.blender.org
Fri Jan 31 11:02:43 CET 2020


Commit: e893f5c61ac0f67e7cf1f6729966b59bec539986
Author: Brecht Van Lommel
Date:   Wed Jan 29 20:48:33 2020 +0100
Branches: new-object-types
https://developer.blender.org/rBe893f5c61ac0f67e7cf1f6729966b59bec539986

Volumes: work on completing the grid access API

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

M	source/blender/blenkernel/BKE_volume.h
M	source/blender/blenkernel/intern/volume.cc
M	source/blender/draw/intern/draw_cache_impl_volume.c
M	source/blender/makesrna/intern/rna_volume.c
M	source/creator/creator.c

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

diff --git a/source/blender/blenkernel/BKE_volume.h b/source/blender/blenkernel/BKE_volume.h
index 7b85fdb3d0e..75b8db09c21 100644
--- a/source/blender/blenkernel/BKE_volume.h
+++ b/source/blender/blenkernel/BKE_volume.h
@@ -38,6 +38,12 @@ struct Object;
 struct Scene;
 struct Volume;
 
+/* Module */
+
+void BKE_volumes_init(void);
+
+/* Datablock Management */
+
 void BKE_volume_init(struct Volume *volume);
 void BKE_volume_init_grids(struct Volume *volume);
 void *BKE_volume_add(struct Main *bmain, const char *name);
@@ -49,9 +55,6 @@ struct Volume *BKE_volume_copy(struct Main *bmain, const struct Volume *volume);
 void BKE_volume_make_local(struct Main *bmain, struct Volume *volume, const bool lib_local);
 void BKE_volume_free(struct Volume *volume);
 
-void BKE_volume_load(struct Volume *volume, struct Main *bmain);
-void BKE_volume_unload(struct Volume *volume);
-
 struct BoundBox *BKE_volume_boundbox_get(struct Object *ob);
 
 /* Depsgraph */
@@ -77,27 +80,64 @@ 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, 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. */
+ * For volumes referencing a file, the list of grids and metadata must be
+ * loaded before it can be accessed. This happens on-demand, only when needed
+ * by the user interface, dependency graph or render engine. */
 
 typedef struct VolumeGrid VolumeGrid;
 
+bool BKE_volume_load(struct Volume *volume, struct Main *bmain);
+void BKE_volume_unload(struct Volume *volume);
+bool BKE_volume_is_loaded(const struct Volume *volume);
+
 int BKE_volume_num_grids(struct Volume *volume);
 const char *BKE_volume_grids_error_msg(const struct Volume *volume);
+VolumeGrid *BKE_volume_grid_get(struct Volume *volume, int grid_index);
+VolumeGrid *BKE_volume_grid_find(struct Volume *volume, const char *name);
 
-/* Grid Metadata */
-
-const VolumeGrid *BKE_volume_grid_for_metadata(struct Volume *volume, int grid_index);
+/* Grid
+ *
+ * By default only grid metadata is loaded, for access to the tree and voxels
+ * the BKE_volume_grid_load must be called first. */
+
+typedef enum VolumeGridType {
+  VOLUME_GRID_UNKNOWN = 0,
+  VOLUME_GRID_BOOLEAN,
+  VOLUME_GRID_FLOAT,
+  VOLUME_GRID_DOUBLE,
+  VOLUME_GRID_INT,
+  VOLUME_GRID_INT64,
+  VOLUME_GRID_MASK,
+  VOLUME_GRID_STRING,
+  VOLUME_GRID_VECTOR_FLOAT,
+  VOLUME_GRID_VECTOR_DOUBLE,
+  VOLUME_GRID_VECTOR_INT,
+} VolumeGridType;
+
+bool BKE_volume_grid_load(struct Volume *volume, struct VolumeGrid *grid);
+void BKE_volume_grid_unload(struct VolumeGrid *volume);
+bool BKE_volume_grid_is_loaded(const struct VolumeGrid *grid);
+
+/* Metadata */
 const char *BKE_volume_grid_name(const struct VolumeGrid *grid);
+VolumeGridType BKE_volume_grid_type(const struct VolumeGrid *grid);
+int BKE_volume_grid_channels(const struct VolumeGrid *grid);
+void BKE_volume_grid_transform_matrix(const struct VolumeGrid *grid, float mat[4][4]);
 
-/* Grid Tree and Voxels */
-
-const VolumeGrid *BKE_volume_grid_for_tree(struct Volume *volume, int grid_index);
+/* Tree and Voxels */
 bool BKE_volume_grid_bounds(const struct VolumeGrid *grid, float min[3], float max[3]);
-float *BKE_volume_grid_to_dense_voxels(const struct VolumeGrid *volume_grid, size_t size[3]);
+
+bool BKE_volume_grid_dense_bounds(const struct VolumeGrid *volume_grid,
+                                  size_t min[3],
+                                  size_t max[3]);
+void BKE_volume_grid_dense_transform_matrix(const struct VolumeGrid *volume_grid,
+                                            const size_t min[3],
+                                            const size_t max[3],
+                                            float mat[4][4]);
+void BKE_volume_grid_dense_voxels(const struct VolumeGrid *volume_grid,
+                                  const size_t min[3],
+                                  const size_t max[3],
+                                  float *voxels);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 5ecb5ae6904..7a867099560 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -48,18 +48,19 @@
 #  include <openvdb/tools/Dense.h>
 
 struct VolumeGrid {
-  VolumeGrid(const openvdb::GridBase::Ptr &vdb, const bool has_tree) : vdb(vdb), has_tree(has_tree)
+  VolumeGrid(const openvdb::GridBase::Ptr &vdb, const bool is_loaded)
+      : vdb(vdb), is_loaded(is_loaded)
   {
   }
 
-  VolumeGrid(const VolumeGrid &other) : vdb(other.vdb), has_tree(other.has_tree)
+  VolumeGrid(const VolumeGrid &other) : vdb(other.vdb), is_loaded(other.is_loaded)
   {
   }
 
   /* OpenVDB grid. */
   openvdb::GridBase::Ptr vdb;
   /* Grid may have only metadata and no tree. */
-  bool has_tree;
+  bool is_loaded;
   /* Mutex for on-demand reading of tree. */
   std::mutex mutex;
 };
@@ -70,13 +71,29 @@ struct VolumeGridVector : public std::vector<VolumeGrid> {
     filepath[0] = '\0';
   }
 
+  VolumeGridVector(const VolumeGridVector &other) : error_msg(other.error_msg)
+  {
+    memcpy(filepath, other.filepath, sizeof(filepath));
+  }
+
   /* Absolute file path that grids have been loaded from. */
   char filepath[FILE_MAX];
   /* File loading error message. */
   std::string error_msg;
+  /* Mutex for file loading of grids list. */
+  std::mutex mutex;
 };
 #endif
 
+/* Module */
+
+void BKE_volumes_init()
+{
+#ifdef WITH_OPENVDB
+  openvdb::initialize();
+#endif
+}
+
 /* Volume datablock */
 
 void BKE_volume_init(Volume *volume)
@@ -149,24 +166,36 @@ void BKE_volume_free(Volume *volume)
 #endif
 }
 
-void BKE_volume_load(Volume *volume, Main *bmain)
+bool BKE_volume_is_loaded(const Volume *volume)
+{
+#ifdef WITH_OPENVDB
+  /* Test if there is a file to load, or if already loaded. */
+  return (volume->filepath[0] == '\0' || volume->grids->filepath[0] != '\0');
+#else
+  UNUSED_VARS(volume);
+  return true;
+#endif
+}
+
+bool BKE_volume_load(Volume *volume, Main *bmain)
 {
 #ifdef WITH_OPENVDB
   VolumeGridVector &grids = *volume->grids;
 
-  /* Test if there is a file to load, or if already loaded. */
-  if (volume->filepath[0] == '\0' || grids.filepath[0] != '\0') {
-    return;
+  if (BKE_volume_is_loaded(volume)) {
+    return grids.error_msg.empty();
+  }
+
+  /* Double-checked lock. */
+  std::lock_guard<std::mutex> lock(grids.mutex);
+  if (BKE_volume_is_loaded(volume)) {
+    return grids.error_msg.empty();
   }
 
   /* Get absolute file path. */
   STRNCPY(grids.filepath, volume->filepath);
   BLI_path_abs(grids.filepath, ID_BLEND_PATH(bmain, &volume->id));
 
-  /* Initialize the first time we use it. This is thread safe and can be safely
-   * called multiple times. */
-  openvdb::initialize();
-
   /* Open OpenVDB file. */
   openvdb::io::File file(grids.filepath);
   openvdb::GridPtrVec vdb_grids;
@@ -186,8 +215,11 @@ void BKE_volume_load(Volume *volume, Main *bmain)
       volume->grids->emplace_back(vdb_grid, false);
     }
   }
+
+  return grids.error_msg.empty();
 #else
   UNUSED_VARS(bmain, volume);
+  return true;
 #endif
 }
 
@@ -226,11 +258,13 @@ BoundBox *BKE_volume_boundbox_get(Object *ob)
     const int num_grids = BKE_volume_num_grids(volume);
 
     for (int i = 0; i < num_grids; i++) {
+      VolumeGrid *grid = BKE_volume_grid_get(volume, i);
+      float grid_min[3], grid_max[3];
+
       /* 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_tree(volume, i);
-      float grid_min[3], grid_max[3];
+      BKE_volume_grid_load(volume, grid);
 
       if (BKE_volume_grid_bounds(grid, grid_min, grid_max)) {
         DO_MIN(grid_min, min);
@@ -329,10 +363,15 @@ int BKE_volume_num_grids(Volume *volume)
 
 const char *BKE_volume_grids_error_msg(const Volume *volume)
 {
+#ifdef WITH_OPENVDB
   return volume->grids->error_msg.c_str();
+#else
+  UNUSED_VARS(volume);
+  return "";
+#endif
 }
 
-const VolumeGrid *BKE_volume_grid_for_metadata(Volume *volume, int grid_index)
+VolumeGrid *BKE_volume_grid_get(Volume *volume, int grid_index)
 {
 #ifdef WITH_OPENVDB
   return &volume->grids->at(grid_index);
@@ -342,38 +381,75 @@ const VolumeGrid *BKE_volume_grid_for_metadata(Volume *volume, int grid_index)
 #endif
 }
 
-const VolumeGrid *BKE_volume_grid_for_tree(Volume *volume, int grid_index)
+VolumeGrid *BKE_volume_grid_find(Volume *volume, const char *name)
+{
+  int num_grids = BKE_volume_num_grids(volume);
+  for (int i = 0; i < num_grids; i++) {
+    VolumeGrid *grid = BKE_volume_grid_get(volume, i);
+    if (STREQ(BKE_volume_grid_name(grid), name)) {
+      return grid;
+    }
+  }
+
+  return NULL;
+}
+
+/* Grid Loading */
+
+bool BKE_volume_grid_load(Volume *volume, VolumeGrid *grid)
 {
 #ifdef WITH_OPENVDB
   VolumeGridVector &grids = *volume->grids;
-  VolumeGrid &grid = grids.at(grid_index);
-
-  if (!grid.has_tree && grids.error_msg.empty()) {
-    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(grids.filepath);
-      openvdb::GridPtrVec vdb_grids;
-
-      try {
-        file.setCopyMaxBytes(0);
-        file.open();
-        grid.vdb = file.readGrid(grid.vdb->getName());
-        grid.has_tree = true;
-      }
-      catch (const openvdb::IoError &e) {
-        grids.error_msg = e.what();
-      }
-    }
+
+  if (BKE_volume_grid_is_loaded(grid)) {
+    return grids.error_msg.empty();
+  }
+
+  /* Double-checked lock. */
+  std::lock_guard<std::mutex> lock(grid->mutex);
+  if (BKE_volume_grid_is_loaded(grid)) {
+    return grids.error_msg.empty();
+  }
+
+  /* Read OpenVDB grid on-demand. */
+  /* TODO: avoid repeating this for multiple g

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list