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:
authorJacques Lucke <jacques@blender.org>2020-10-20 12:00:16 +0300
committerJacques Lucke <jacques@blender.org>2020-10-20 12:00:16 +0300
commit63a9f24b55d0b5d84d625bdbb44d498fb1f2ae01 (patch)
tree217fa45ec9b0c66f856dd8b32d8ab3d5cbc18d3d /source/blender/blenkernel/intern/volume.cc
parentf3ecb4c91e159caff2e6d335adb1ccf06423c90f (diff)
Volumes: simplify volumes in modifiers or on load
This changes how the simplify volumes setting works. Before, it only affeted viewport rendering. This was an issue, because all internal computations would still have to happen on the high resolution volumes. With this patch, the simplify setting already affects file loading and procedural generation of volumes. Rendering does not have to care about the simplify option anymore, it just gets the correct simplified version from the depsgraph. Reviewers: brecht Differential Revision: https://developer.blender.org/D9176
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