tornavis/source/blender/blenkernel/BKE_volume_grid_type_traits.hh

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

120 lines
3.1 KiB
C++
Raw Normal View History

Volumes: refactor volume grid storage This refactors how volume grids are stored with the following new goals in mind: * Get a **stand-alone volume grid** data structure that can be used by geometry nodes. Previously, the `VolumeGrid` data structure was tightly coupled with the `Volume` data block. * Support **implicit sharing of grids and trees**. Previously, it was possible to share data when multiple `Volume` data blocks loaded grids from the same `.vdb` files but this was not flexible enough. * Get a safe API for **lazy-loading and unloading** of grids without requiring explicit calls to some "load" function all the time. * Get a safe API for **caching grids from files** that is not coupled to the `Volume` data block. * Get a **tiered API** for different levels of `openvdb` involvement: * No `OpenVDB`: Since `WITH_OPENVDB` is optional, it's helpful to have parts of the API that still work in this case. This makes it possible to write high level code for volumes that does not require `#ifdef WITH_OPENVDB` checks everywhere. This is in `BKE_volume_grid_fwd.hh`. * Shallow `OpenVDB`: Code using this API requires `WITH_OPENVDB` checks. However, care is taken to not include the expensive parts of `OpenVDB` and to use forward declarations as much as possible. This is in `BKE_volume_grid.hh` and uses `openvdb_fwd.hh`. * "Full" `OpenVDB`: This API requires more heavy `OpenVDB` includes. Fortunately, it turned out to be not necessary for the common API. So this is only used for task specific APIs. At the core of the new API is the `VolumeGridData` type. It's a wrapper around an `openvdb::Grid` and adds some features on top like implicit sharing, lazy-loading and unloading. Then there are `GVolumeGrid` and `VolumeGrid` which are containers for a volume grid. Semantically, each `VolumeGrid` has its own independent grid, but this is cheap due to implicit sharing. At highest level we currently have the `Volume` data-block which contains a list of `VolumeGrid`. ```mermaid flowchart LR Volume --> VolumeGrid --> VolumeGridData --> openvdb::Grid ``` The loading of `.vdb` files is abstracted away behind the volume file cache API. This API makes it easy to load and reuse entire files and individual grids from disk. It also supports caching simplify levels for grids on disk. An important new concept are the "tree access tokens". Whenever some code wants to work with an openvdb tree, it has to retrieve an access token from the corresponding `VolumeGridData`. This access token has to be kept alive for as long as the code works with the grid data. The same token is valid for read and write access. The purpose of these access tokens is to make it possible to detect when some code is currently working with the openvdb tree. This allows freeing it if it's possible to reload it later on (e.g. from disk). It's possible to free a tree that is referenced by multiple owners, but only no one is actively working with. In some sense, this is similar to the existing `ImageUser` concept. The most important new files to read are `BKE_volume_grid.hh` and `BKE_volume_grid_file_cache.hh`. Most other changes are updates to existing code to use the new API. Pull Request: https://projects.blender.org/blender/blender/pulls/116315
2023-12-20 15:32:52 +01:00
/* SPDX-FileCopyrightText: 2023 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup bke
*/
#ifdef WITH_OPENVDB
# include "BLI_math_quaternion_types.hh"
# include "BLI_math_vector_types.hh"
# include "BKE_volume_enums.hh"
# include "openvdb_fwd.hh"
namespace blender::bke {
/**
* We uses the native math types from OpenVDB when working with grids. For example, vector grids
* contain `openvdb::Vec3f`. #VolumeGridTraits allows mapping between Blender's math types and the
* ones from OpenVDB. This allows e.g. using `VolumeGrid<float3>` when the actual grid is a
* `openvdb::Vec3SGrid`. The benefit of this is that most places in Blender can keep using our own
* types, while only the code that deals with OpenVDB specifically has to care about the mapping
* between math type representations.
*
* \param T The Blender type that we want to get the grid traits for (e.g. `blender::float3`).
*/
template<typename T> struct VolumeGridTraits {
/**
* The type that Blender uses to represent values of the voxel type (e.g. `blender::float3`).
*/
using BlenderType = void;
/**
* The type that OpenVDB uses.
*/
using PrimitiveType = void;
/**
* The standard tree type we use for grids of the given type.
*/
using TreeType = void;
/**
* The corresponding #VolumeGridType for the type.
*/
static constexpr VolumeGridType EnumType = VOLUME_GRID_UNKNOWN;
};
template<> struct VolumeGridTraits<bool> {
using BlenderType = bool;
using PrimitiveType = bool;
using TreeType = openvdb::BoolTree;
static constexpr VolumeGridType EnumType = VOLUME_GRID_BOOLEAN;
static bool to_openvdb(const bool &value)
{
return value;
}
static bool to_blender(const bool &value)
{
return value;
}
};
template<> struct VolumeGridTraits<int> {
using BlenderType = int;
using PrimitiveType = int;
using TreeType = openvdb::Int32Tree;
static constexpr VolumeGridType EnumType = VOLUME_GRID_INT;
static int to_openvdb(const int &value)
{
return value;
}
static int to_blender(const int &value)
{
return value;
}
};
template<> struct VolumeGridTraits<float> {
using BlenderType = float;
using PrimitiveType = float;
using TreeType = openvdb::FloatTree;
static constexpr VolumeGridType EnumType = VOLUME_GRID_FLOAT;
static float to_openvdb(const float &value)
{
return value;
}
static float to_blender(const float &value)
{
return value;
}
};
template<> struct VolumeGridTraits<float3> {
using BlenderType = float3;
using PrimitiveType = openvdb::Vec3f;
using TreeType = openvdb::Vec3STree;
static constexpr VolumeGridType EnumType = VOLUME_GRID_VECTOR_FLOAT;
static openvdb::Vec3f to_openvdb(const float3 &value)
{
return openvdb::Vec3f(*value);
}
static float3 to_blender(const openvdb::Vec3f &value)
{
return float3(value.asV());
}
};
template<typename T> using OpenvdbTreeType = typename VolumeGridTraits<T>::TreeType;
template<typename T> using OpenvdbGridType = openvdb::Grid<OpenvdbTreeType<T>>;
} // namespace blender::bke
#endif /* WITH_OPENVDB */