Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/volume.cc')
-rw-r--r--source/blender/blenkernel/intern/volume.cc168
1 files changed, 153 insertions, 15 deletions
diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc
index 32f6a94aa7f..64d053c0e30 100644
--- a/source/blender/blenkernel/intern/volume.cc
+++ b/source/blender/blenkernel/intern/volume.cc
@@ -29,6 +29,7 @@
#include "BLI_compiler_compat.h"
#include "BLI_fileops.h"
#include "BLI_ghash.h"
+#include "BLI_map.hh"
#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
@@ -70,6 +71,7 @@ static CLG_LogRef LOG = {"bke.volume"};
# include <openvdb/openvdb.h>
# include <openvdb/points/PointDataGrid.h>
+# include <openvdb/tools/GridTransformer.h>
/* Global Volume File Cache
*
@@ -115,12 +117,32 @@ static struct VolumeFileCache {
{
}
+ /* Returns the original grid or a simplified version depending on the given #simplify_level. */
+ openvdb::GridBase::Ptr simplified_grid(const int simplify_level)
+ {
+ BLI_assert(simplify_level >= 0);
+ if (simplify_level == 0 || !is_loaded) {
+ return grid;
+ }
+
+ std::lock_guard<std::mutex> lock(mutex);
+ return simplified_grids.lookup_or_add_cb(simplify_level, [&]() {
+ const float resolution_factor = 1.0f / (1 << simplify_level);
+ const VolumeGridType grid_type = BKE_volume_grid_type_openvdb(grid);
+ return BKE_volume_grid_create_with_changed_resolution(grid_type, *grid, resolution_factor);
+ });
+ }
+
/* Unique key: filename + grid name. */
std::string filepath;
std::string grid_name;
/* OpenVDB grid. */
openvdb::GridBase::Ptr grid;
+
+ /* Simplified versions of #grid. The integer key is the simplification level. */
+ blender::Map<int, openvdb::GridBase::Ptr> simplified_grids;
+
/* Has the grid tree been loaded? */
bool is_loaded;
/* Error message if an error occured during loading. */
@@ -224,6 +246,7 @@ static struct VolumeFileCache {
/* Note we replace the grid rather than clearing, so that if there is
* any other shared pointer to the grid it will keep the tree. */
entry.grid = entry.grid->copyGridWithNewTree();
+ entry.simplified_grids.clear();
entry.is_loaded = false;
}
}
@@ -241,7 +264,8 @@ static struct VolumeFileCache {
* stored in the global cache. Procedurally generated grids are not. */
struct VolumeGrid {
- VolumeGrid(const VolumeFileCache::Entry &template_entry) : entry(NULL), is_loaded(false)
+ VolumeGrid(const VolumeFileCache::Entry &template_entry, const int simplify_level)
+ : entry(NULL), simplify_level(simplify_level), is_loaded(false)
{
entry = GLOBAL_CACHE.add_metadata_user(template_entry);
}
@@ -251,7 +275,10 @@ struct VolumeGrid {
}
VolumeGrid(const VolumeGrid &other)
- : entry(other.entry), local_grid(other.local_grid), is_loaded(other.is_loaded)
+ : entry(other.entry),
+ simplify_level(other.simplify_level),
+ local_grid(other.local_grid),
+ is_loaded(other.is_loaded)
{
if (entry) {
GLOBAL_CACHE.copy_user(*entry, is_loaded);
@@ -360,8 +387,8 @@ struct VolumeGrid {
{
/* Don't use vdb.getName() since it copies the string, we want a pointer to the
* original so it doesn't get freed out of scope. */
- openvdb::StringMetadata::ConstPtr name_meta = grid()->getMetadata<openvdb::StringMetadata>(
- openvdb::GridBase::META_GRID_NAME);
+ openvdb::StringMetadata::ConstPtr name_meta =
+ main_grid()->getMetadata<openvdb::StringMetadata>(openvdb::GridBase::META_GRID_NAME);
return (name_meta) ? name_meta->value().c_str() : "";
}
@@ -379,7 +406,22 @@ struct VolumeGrid {
return is_loaded;
}
- const openvdb::GridBase::Ptr &grid() const
+ openvdb::GridBase::Ptr grid() const
+ {
+ if (entry) {
+ return entry->simplified_grid(simplify_level);
+ }
+ return local_grid;
+ }
+
+ void set_simplify_level(const int simplify_level)
+ {
+ BLI_assert(simplify_level >= 0);
+ this->simplify_level = simplify_level;
+ }
+
+ private:
+ const openvdb::GridBase::Ptr &main_grid() const
{
return (entry) ? entry->grid : local_grid;
}
@@ -388,6 +430,9 @@ struct VolumeGrid {
/* File cache entry when grid comes directly from a file and may be shared
* with other volume datablocks. */
VolumeFileCache::Entry *entry;
+ /* If this volume grid is in the global file cache, we can reference a simplified version of it,
+ * instead of the original high resolution grid. */
+ int simplify_level = 0;
/* OpenVDB grid if it's not shared through the file cache. */
openvdb::GridBase::Ptr local_grid;
/* Indicates if the tree has been loaded for this grid. Note that vdb.tree()
@@ -761,7 +806,7 @@ bool BKE_volume_load(Volume *volume, Main *bmain)
for (const openvdb::GridBase::Ptr &vdb_grid : vdb_grids) {
if (vdb_grid) {
VolumeFileCache::Entry template_entry(grids.filepath, vdb_grid);
- grids.emplace_back(template_entry);
+ grids.emplace_back(template_entry, volume->runtime.default_simplify_level);
}
}
@@ -906,6 +951,17 @@ bool BKE_volume_is_points_only(const Volume *volume)
/* Dependency Graph */
+static void volume_update_simplify_level(Volume *volume, const Depsgraph *depsgraph)
+{
+ const int simplify_level = BKE_volume_simplify_level(depsgraph);
+ if (volume->runtime.grids) {
+ for (VolumeGrid &grid : *volume->runtime.grids) {
+ grid.set_simplify_level(simplify_level);
+ }
+ }
+ volume->runtime.default_simplify_level = simplify_level;
+}
+
static Volume *volume_evaluate_modifiers(struct Depsgraph *depsgraph,
struct Scene *scene,
Object *object,
@@ -956,6 +1012,8 @@ static Volume *volume_evaluate_modifiers(struct Depsgraph *depsgraph,
void BKE_volume_eval_geometry(struct Depsgraph *depsgraph, Volume *volume)
{
+ volume_update_simplify_level(volume, depsgraph);
+
/* TODO: can we avoid modifier re-evaluation when frame did not change? */
int frame = volume_sequence_frame(depsgraph, volume);
if (frame != volume->runtime.frame) {
@@ -1157,11 +1215,9 @@ const char *BKE_volume_grid_name(const VolumeGrid *volume_grid)
#endif
}
-VolumeGridType BKE_volume_grid_type(const VolumeGrid *volume_grid)
-{
#ifdef WITH_OPENVDB
- const openvdb::GridBase::Ptr &grid = volume_grid->grid();
-
+VolumeGridType BKE_volume_grid_type_openvdb(const openvdb::GridBase::Ptr &grid)
+{
if (grid->isType<openvdb::FloatGrid>()) {
return VOLUME_GRID_FLOAT;
}
@@ -1195,10 +1251,16 @@ VolumeGridType BKE_volume_grid_type(const VolumeGrid *volume_grid)
if (grid->isType<openvdb::points::PointDataGrid>()) {
return VOLUME_GRID_POINTS;
}
-#else
- UNUSED_VARS(volume_grid);
+ return VOLUME_GRID_UNKNOWN;
+}
#endif
+VolumeGridType BKE_volume_grid_type(const VolumeGrid *volume_grid)
+{
+#ifdef WITH_OPENVDB
+ const openvdb::GridBase::Ptr grid = volume_grid->grid();
+ return BKE_volume_grid_type_openvdb(grid);
+#endif
return VOLUME_GRID_UNKNOWN;
}
@@ -1229,7 +1291,7 @@ int BKE_volume_grid_channels(const VolumeGrid *grid)
void BKE_volume_grid_transform_matrix(const VolumeGrid *volume_grid, float mat[4][4])
{
#ifdef WITH_OPENVDB
- const openvdb::GridBase::Ptr &grid = volume_grid->grid();
+ const openvdb::GridBase::Ptr grid = volume_grid->grid();
const openvdb::math::Transform &transform = grid->transform();
/* Perspective not supported for now, getAffineMap() will leave out the
@@ -1253,7 +1315,7 @@ bool BKE_volume_grid_bounds(const VolumeGrid *volume_grid, float min[3], float m
{
#ifdef WITH_OPENVDB
/* TODO: we can get this from grid metadata in some cases? */
- const openvdb::GridBase::Ptr &grid = volume_grid->grid();
+ const openvdb::GridBase::Ptr grid = volume_grid->grid();
BLI_assert(BKE_volume_grid_is_loaded(volume_grid));
openvdb::CoordBBox coordbbox;
@@ -1302,7 +1364,6 @@ Volume *BKE_volume_copy_for_eval(Volume *volume_src, bool reference)
}
Volume *result = (Volume *)BKE_id_copy_ex(NULL, &volume_src->id, NULL, flags);
- result->filepath[0] = '\0';
return result;
}
@@ -1357,6 +1418,33 @@ void BKE_volume_grid_remove(Volume *volume, VolumeGrid *grid)
#endif
}
+int BKE_volume_simplify_level(const Depsgraph *depsgraph)
+{
+ if (DEG_get_mode(depsgraph) != DAG_EVAL_RENDER) {
+ const Scene *scene = DEG_get_input_scene(depsgraph);
+ if (scene->r.mode & R_SIMPLIFY) {
+ const float simplify = scene->r.simplify_volumes;
+ if (simplify == 0.0f) {
+ /* log2 is not defined at 0.0f, so just use some high simplify level. */
+ return 16;
+ }
+ return ceilf(-log2(simplify));
+ }
+ }
+ return 0;
+}
+
+float BKE_volume_simplify_factor(const Depsgraph *depsgraph)
+{
+ if (DEG_get_mode(depsgraph) != DAG_EVAL_RENDER) {
+ const Scene *scene = DEG_get_input_scene(depsgraph);
+ if (scene->r.mode & R_SIMPLIFY) {
+ return scene->r.simplify_volumes;
+ }
+ }
+ return 1.0f;
+}
+
/* OpenVDB Grid Access */
#ifdef WITH_OPENVDB
@@ -1387,4 +1475,54 @@ openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const Volume *volume,
return grid->grid();
}
+
+/* Changing the resolution of a grid. */
+
+/**
+ * Returns a grid of the same type as the input, but with more/less resolution. If
+ * resolution_factor is 1/2, the resolution on each axis is halved. The transform of the returned
+ * grid is adjusted to match the original grid. */
+template<typename GridType>
+static typename GridType::Ptr create_grid_with_changed_resolution(const GridType &old_grid,
+ const float resolution_factor)
+{
+ BLI_assert(resolution_factor > 0.0f);
+
+ openvdb::Mat4R xform;
+ xform.setToScale(openvdb::Vec3d(resolution_factor));
+ openvdb::tools::GridTransformer transformer{xform};
+
+ typename GridType::Ptr new_grid = old_grid.copyWithNewTree();
+ transformer.transformGrid<openvdb::tools::BoxSampler>(old_grid, *new_grid);
+ new_grid->transform() = old_grid.transform();
+ new_grid->transform().preScale(1.0f / resolution_factor);
+ new_grid->transform().postTranslate(-new_grid->voxelSize() / 2.0f);
+ return new_grid;
+}
+
+struct CreateGridWithChangedResolutionOp {
+ const openvdb::GridBase &grid;
+ const float resolution_factor;
+
+ template<typename GridType> typename openvdb::GridBase::Ptr operator()()
+ {
+ if constexpr (std::is_same_v<GridType, openvdb::StringGrid>) {
+ return {};
+ }
+ else {
+ return create_grid_with_changed_resolution(static_cast<const GridType &>(grid),
+ resolution_factor);
+ }
+ }
+};
+
+openvdb::GridBase::Ptr BKE_volume_grid_create_with_changed_resolution(
+ const VolumeGridType grid_type,
+ const openvdb::GridBase &old_grid,
+ const float resolution_factor)
+{
+ CreateGridWithChangedResolutionOp op{old_grid, resolution_factor};
+ return BKE_volume_grid_type_operation(grid_type, op);
+}
+
#endif