2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2020-03-17 14:41:48 +01:00
|
|
|
|
2020-03-20 12:19:09 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2020-03-17 14:41:48 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "DNA_defaults.h"
|
2020-05-20 16:58:56 +02:00
|
|
|
#include "DNA_material_types.h"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "DNA_object_types.h"
|
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
#include "DNA_volume_types.h"
|
|
|
|
|
|
2023-11-27 16:14:49 +01:00
|
|
|
#include "BLI_bounds.hh"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BLI_compiler_compat.h"
|
|
|
|
|
#include "BLI_fileops.h"
|
|
|
|
|
#include "BLI_ghash.h"
|
2021-04-08 13:28:35 -05:00
|
|
|
#include "BLI_index_range.hh"
|
2020-10-20 11:00:16 +02:00
|
|
|
#include "BLI_map.hh"
|
2023-08-10 14:21:22 +02:00
|
|
|
#include "BLI_math_matrix.h"
|
2023-02-06 21:25:45 +01:00
|
|
|
#include "BLI_math_matrix_types.hh"
|
2023-01-04 00:14:55 +01:00
|
|
|
#include "BLI_math_vector_types.hh"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BLI_path_util.h"
|
|
|
|
|
#include "BLI_string.h"
|
2021-10-26 11:25:44 -05:00
|
|
|
#include "BLI_string_ref.hh"
|
2021-06-16 16:29:21 +02:00
|
|
|
#include "BLI_task.hh"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
2020-04-03 13:07:36 +02:00
|
|
|
#include "BKE_anim_data.h"
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
#include "BKE_bpath.h"
|
2021-04-20 09:30:53 +02:00
|
|
|
#include "BKE_geometry_set.hh"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BKE_global.h"
|
2024-01-20 19:17:36 +01:00
|
|
|
#include "BKE_idtype.hh"
|
2024-01-15 12:44:04 -05:00
|
|
|
#include "BKE_lib_id.hh"
|
2024-01-18 12:20:42 +01:00
|
|
|
#include "BKE_lib_query.hh"
|
2023-11-30 19:51:22 +01:00
|
|
|
#include "BKE_lib_remap.hh"
|
2023-12-01 19:43:16 +01:00
|
|
|
#include "BKE_main.hh"
|
2023-11-14 09:30:40 +01:00
|
|
|
#include "BKE_modifier.hh"
|
2023-10-09 23:41:53 +02:00
|
|
|
#include "BKE_object.hh"
|
2023-11-15 18:46:07 +01:00
|
|
|
#include "BKE_object_types.hh"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BKE_packedFile.h"
|
2020-10-07 16:39:51 +02:00
|
|
|
#include "BKE_report.h"
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "BKE_scene.h"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_volume.hh"
|
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
|
|
|
#include "BKE_volume_grid.hh"
|
|
|
|
|
#include "BKE_volume_grid_file_cache.hh"
|
2023-06-30 08:49:53 +02:00
|
|
|
#include "BKE_volume_openvdb.hh"
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
#include "BLT_translation.h"
|
|
|
|
|
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph_query.hh"
|
2020-03-17 14:41:48 +01:00
|
|
|
|
2023-08-28 15:01:05 +02:00
|
|
|
#include "BLO_read_write.hh"
|
2020-09-11 11:39:06 +02:00
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
#include "CLG_log.h"
|
|
|
|
|
|
2020-03-21 14:40:51 +01:00
|
|
|
#ifdef WITH_OPENVDB
|
2020-03-17 14:41:48 +01:00
|
|
|
static CLG_LogRef LOG = {"bke.volume"};
|
2020-03-21 14:40:51 +01:00
|
|
|
#endif
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
#define VOLUME_FRAME_NONE INT_MAX
|
|
|
|
|
|
2021-04-08 13:28:35 -05:00
|
|
|
using blender::float3;
|
|
|
|
|
using blender::float4x4;
|
|
|
|
|
using blender::IndexRange;
|
2021-10-26 11:25:44 -05:00
|
|
|
using blender::StringRef;
|
2022-04-19 16:28:14 +02:00
|
|
|
using blender::StringRefNull;
|
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
|
|
|
using blender::bke::GVolumeGrid;
|
2021-04-08 13:28:35 -05:00
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
#ifdef WITH_OPENVDB
|
|
|
|
|
# include <atomic>
|
|
|
|
|
# include <list>
|
|
|
|
|
# include <mutex>
|
|
|
|
|
# include <unordered_set>
|
|
|
|
|
|
|
|
|
|
# include <openvdb/openvdb.h>
|
|
|
|
|
# include <openvdb/points/PointDataGrid.h>
|
2020-10-20 11:00:16 +02:00
|
|
|
# include <openvdb/tools/GridTransformer.h>
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
/* Volume Grid Vector
|
|
|
|
|
*
|
|
|
|
|
* List of grids contained in a volume datablock. This is runtime-only data,
|
|
|
|
|
* the actual grids are always saved in a VDB file. */
|
|
|
|
|
|
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
|
|
|
struct VolumeGridVector : public std::list<GVolumeGrid> {
|
2020-10-07 16:39:51 +02:00
|
|
|
VolumeGridVector() : metadata(new openvdb::MetaMap())
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
filepath[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VolumeGridVector(const VolumeGridVector &other)
|
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
|
|
|
: std::list<GVolumeGrid>(other), error_msg(other.error_msg), metadata(other.metadata)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
memcpy(filepath, other.filepath, sizeof(filepath));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool is_loaded() const
|
|
|
|
|
{
|
|
|
|
|
return filepath[0] != '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void clear_all()
|
|
|
|
|
{
|
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
|
|
|
std::list<GVolumeGrid>::clear();
|
2020-03-17 14:41:48 +01:00
|
|
|
filepath[0] = '\0';
|
|
|
|
|
error_msg.clear();
|
|
|
|
|
metadata.reset();
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-19 12:52:55 +11:00
|
|
|
/* Mutex for file loading of grids list. `const` write access to the fields after this must be
|
2021-04-08 12:00:26 -05:00
|
|
|
* protected by locking with this mutex. */
|
|
|
|
|
mutable std::mutex mutex;
|
2020-03-17 14:41:48 +01:00
|
|
|
/* Absolute file path that grids have been loaded from. */
|
|
|
|
|
char filepath[FILE_MAX];
|
|
|
|
|
/* File loading error message. */
|
|
|
|
|
std::string error_msg;
|
|
|
|
|
/* File Metadata. */
|
|
|
|
|
openvdb::MetaMap::Ptr metadata;
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Module */
|
|
|
|
|
|
|
|
|
|
void BKE_volumes_init()
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
|
|
|
|
openvdb::initialize();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Volume datablock */
|
|
|
|
|
|
|
|
|
|
static void volume_init_data(ID *id)
|
|
|
|
|
{
|
|
|
|
|
Volume *volume = (Volume *)id;
|
|
|
|
|
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(volume, id));
|
|
|
|
|
|
|
|
|
|
MEMCPY_STRUCT_AFTER(volume, DNA_struct_default_get(Volume), id);
|
|
|
|
|
|
2024-01-06 13:26:59 +01:00
|
|
|
volume->runtime = MEM_new<blender::bke::VolumeRuntime>(__func__);
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
BKE_volume_init_grids(volume);
|
2022-04-19 16:28:14 +02:00
|
|
|
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(volume->velocity_grid, "velocity");
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
2022-10-03 17:37:25 -05:00
|
|
|
static void volume_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, const int /*flag*/)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
Volume *volume_dst = (Volume *)id_dst;
|
|
|
|
|
const Volume *volume_src = (const Volume *)id_src;
|
2024-01-06 13:26:59 +01:00
|
|
|
volume_dst->runtime = MEM_new<blender::bke::VolumeRuntime>(__func__);
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
if (volume_src->packedfile) {
|
|
|
|
|
volume_dst->packedfile = BKE_packedfile_duplicate(volume_src->packedfile);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
volume_dst->mat = (Material **)MEM_dupallocN(volume_src->mat);
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
if (volume_src->runtime->grids) {
|
|
|
|
|
const VolumeGridVector &grids_src = *(volume_src->runtime->grids);
|
|
|
|
|
volume_dst->runtime->grids = MEM_new<VolumeGridVector>(__func__, grids_src);
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
2021-01-21 10:32:42 +01:00
|
|
|
|
2024-01-06 13:26:59 +01:00
|
|
|
volume_dst->runtime->frame = volume_src->runtime->frame;
|
|
|
|
|
STRNCPY(volume_dst->runtime->velocity_x_grid, volume_src->runtime->velocity_x_grid);
|
|
|
|
|
STRNCPY(volume_dst->runtime->velocity_y_grid, volume_src->runtime->velocity_y_grid);
|
|
|
|
|
STRNCPY(volume_dst->runtime->velocity_z_grid, volume_src->runtime->velocity_z_grid);
|
|
|
|
|
|
2021-01-21 10:32:42 +01:00
|
|
|
volume_dst->batch_cache = nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void volume_free_data(ID *id)
|
|
|
|
|
{
|
|
|
|
|
Volume *volume = (Volume *)id;
|
|
|
|
|
BKE_animdata_free(&volume->id, false);
|
|
|
|
|
BKE_volume_batch_cache_free(volume);
|
|
|
|
|
MEM_SAFE_FREE(volume->mat);
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
MEM_delete(volume->runtime->grids);
|
|
|
|
|
volume->runtime->grids = nullptr;
|
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
|
|
|
/* Deleting the volume might have made some grids completely unused, so they can be freed. */
|
|
|
|
|
blender::bke::volume_grid::file_cache::unload_unused();
|
2020-03-17 14:41:48 +01:00
|
|
|
#endif
|
2024-01-06 13:26:59 +01:00
|
|
|
MEM_delete(volume->runtime);
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-20 16:58:56 +02:00
|
|
|
static void volume_foreach_id(ID *id, LibraryForeachIDData *data)
|
|
|
|
|
{
|
|
|
|
|
Volume *volume = (Volume *)id;
|
|
|
|
|
for (int i = 0; i < volume->totcol; i++) {
|
2021-10-26 10:40:36 +02:00
|
|
|
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, volume->mat[i], IDWALK_CB_USER);
|
2020-05-20 16:58:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-03 15:27:12 +02:00
|
|
|
static void volume_foreach_cache(ID *id,
|
|
|
|
|
IDTypeForeachCacheFunctionCallback function_callback,
|
|
|
|
|
void *user_data)
|
|
|
|
|
{
|
|
|
|
|
Volume *volume = (Volume *)id;
|
|
|
|
|
IDCacheKey key = {
|
2024-01-22 13:47:13 +01:00
|
|
|
/*id_session_uid*/ id->session_uid,
|
2024-01-18 22:50:40 +01:00
|
|
|
/*identifier*/ 1,
|
2020-07-03 15:27:12 +02:00
|
|
|
};
|
|
|
|
|
|
2024-01-06 13:26:59 +01:00
|
|
|
function_callback(id, &key, (void **)&volume->runtime->grids, 0, user_data);
|
2020-07-03 15:27:12 +02:00
|
|
|
}
|
|
|
|
|
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
static void volume_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
|
|
|
|
{
|
|
|
|
|
Volume *volume = reinterpret_cast<Volume *>(id);
|
|
|
|
|
|
2021-11-30 09:18:41 +11:00
|
|
|
if (volume->packedfile != nullptr &&
|
2024-01-02 18:12:54 +01:00
|
|
|
(bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0)
|
|
|
|
|
{
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-23 10:09:01 +10:00
|
|
|
BKE_bpath_foreach_path_fixed_process(bpath_data, volume->filepath, sizeof(volume->filepath));
|
Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`,
and move each ID-specific part of the `foreach_path` looper into their
own IDTypeInfo struct, using a new `foreach_path` callback.
Additionally, following improvements/cleanups are included:
* Attempt to get better, more consistent namings.
** In particular, move from `path_visitor` to more standard `foreach_path`.
* Update and extend documentation.
** API doc was moved to header, according to recent discussions on this
topic.
* Remove `BKE_bpath_relocate_visitor` from API, this is specific
callback that belongs in `lib_id.c` user code.
NOTE: This commit is expected to be 100% non-behavioral-change. This
implies that several potential further changes were only noted as
comments (like using a more generic solution for
`lib_id_library_local_paths`, addressing inconsistencies like path of
packed libraries always being skipped, regardless of the
`BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value,
etc.).
NOTE: basic unittests were added to master already in
rBdcc500e5a265093bc9cc.
Reviewed By: brecht
Differential Revision: https://developer.blender.org/D13381
2021-11-29 14:20:58 +01:00
|
|
|
}
|
|
|
|
|
|
2020-09-11 11:39:06 +02:00
|
|
|
static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
|
|
|
|
{
|
|
|
|
|
Volume *volume = (Volume *)id;
|
2020-12-14 11:28:08 +01:00
|
|
|
const bool is_undo = BLO_write_is_undo(writer);
|
2020-09-11 11:39:06 +02:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
/* Do not store packed files in case this is a library override ID. */
|
|
|
|
|
if (ID_IS_OVERRIDE_LIBRARY(volume) && !is_undo) {
|
|
|
|
|
volume->packedfile = nullptr;
|
|
|
|
|
}
|
2020-09-11 11:39:06 +02:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
/* write LibData */
|
|
|
|
|
BLO_write_id_struct(writer, Volume, id_address, &volume->id);
|
|
|
|
|
BKE_id_blend_write(writer, &volume->id);
|
2020-09-11 11:39:06 +02:00
|
|
|
|
2021-08-19 11:13:55 +02:00
|
|
|
/* direct data */
|
|
|
|
|
BLO_write_pointer_array(writer, volume->totcol, volume->mat);
|
|
|
|
|
|
|
|
|
|
BKE_packedfile_blend_write(writer, volume->packedfile);
|
2020-09-11 11:39:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void volume_blend_read_data(BlendDataReader *reader, ID *id)
|
|
|
|
|
{
|
|
|
|
|
Volume *volume = (Volume *)id;
|
2024-01-06 13:26:59 +01:00
|
|
|
volume->runtime = MEM_new<blender::bke::VolumeRuntime>(__func__);
|
2020-09-11 11:39:06 +02:00
|
|
|
|
|
|
|
|
BKE_packedfile_blend_read(reader, &volume->packedfile);
|
2024-01-06 13:26:59 +01:00
|
|
|
volume->runtime->frame = 0;
|
2020-09-11 11:39:06 +02:00
|
|
|
|
|
|
|
|
/* materials */
|
|
|
|
|
BLO_read_pointer_array(reader, (void **)&volume->mat);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-11 18:07:59 +01:00
|
|
|
static void volume_blend_read_after_liblink(BlendLibReader * /*reader*/, ID *id)
|
2020-09-11 11:39:06 +02:00
|
|
|
{
|
2023-03-11 18:07:59 +01:00
|
|
|
Volume *volume = reinterpret_cast<Volume *>(id);
|
|
|
|
|
|
2020-09-11 11:39:06 +02:00
|
|
|
/* Needs to be done *after* cache pointers are restored (call to
|
|
|
|
|
* `foreach_cache`/`blo_cache_storage_entry_restore_in_new`), easier for now to do it in
|
|
|
|
|
* lib_link... */
|
|
|
|
|
BKE_volume_init_grids(volume);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
IDTypeInfo IDType_ID_VO = {
|
2023-01-16 12:41:11 +11:00
|
|
|
/*id_code*/ ID_VO,
|
|
|
|
|
/*id_filter*/ FILTER_ID_VO,
|
|
|
|
|
/*main_listbase_index*/ INDEX_ID_VO,
|
|
|
|
|
/*struct_size*/ sizeof(Volume),
|
|
|
|
|
/*name*/ "Volume",
|
2023-10-04 02:53:31 +02:00
|
|
|
/*name_plural*/ N_("volumes"),
|
2023-01-16 12:41:11 +11:00
|
|
|
/*translation_context*/ BLT_I18NCONTEXT_ID_VOLUME,
|
|
|
|
|
/*flags*/ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
|
|
|
|
|
/*asset_type_info*/ nullptr,
|
|
|
|
|
|
|
|
|
|
/*init_data*/ volume_init_data,
|
|
|
|
|
/*copy_data*/ volume_copy_data,
|
|
|
|
|
/*free_data*/ volume_free_data,
|
|
|
|
|
/*make_local*/ nullptr,
|
|
|
|
|
/*foreach_id*/ volume_foreach_id,
|
|
|
|
|
/*foreach_cache*/ volume_foreach_cache,
|
|
|
|
|
/*foreach_path*/ volume_foreach_path,
|
|
|
|
|
/*owner_pointer_get*/ nullptr,
|
|
|
|
|
|
|
|
|
|
/*blend_write*/ volume_blend_write,
|
|
|
|
|
/*blend_read_data*/ volume_blend_read_data,
|
2023-03-11 18:07:59 +01:00
|
|
|
/*blend_read_after_liblink*/ volume_blend_read_after_liblink,
|
2023-01-16 12:41:11 +11:00
|
|
|
|
|
|
|
|
/*blend_read_undo_preserve*/ nullptr,
|
|
|
|
|
|
|
|
|
|
/*lib_override_apply_post*/ nullptr,
|
2020-03-17 14:41:48 +01:00
|
|
|
};
|
|
|
|
|
|
2020-05-20 16:45:47 +02:00
|
|
|
void BKE_volume_init_grids(Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
if (volume->runtime->grids == nullptr) {
|
|
|
|
|
volume->runtime->grids = MEM_new<VolumeGridVector>(__func__);
|
2020-05-20 16:45:47 +02:00
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *BKE_volume_add(Main *bmain, const char *name)
|
|
|
|
|
{
|
2020-10-08 12:50:04 +02:00
|
|
|
Volume *volume = (Volume *)BKE_id_new(bmain, ID_VO, name);
|
2020-05-20 16:45:47 +02:00
|
|
|
|
|
|
|
|
return volume;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
/* Sequence */
|
|
|
|
|
|
|
|
|
|
static int volume_sequence_frame(const Depsgraph *depsgraph, const Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
if (!volume->is_sequence) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int path_frame, path_digits;
|
2023-04-19 12:32:42 +10:00
|
|
|
if (!(volume->is_sequence && BLI_path_frame_get(volume->filepath, &path_frame, &path_digits))) {
|
2020-03-17 14:41:48 +01:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int scene_frame = DEG_get_ctime(depsgraph);
|
|
|
|
|
const VolumeSequenceMode mode = (VolumeSequenceMode)volume->sequence_mode;
|
|
|
|
|
const int frame_duration = volume->frame_duration;
|
|
|
|
|
const int frame_start = volume->frame_start;
|
|
|
|
|
const int frame_offset = volume->frame_offset;
|
|
|
|
|
|
|
|
|
|
if (frame_duration == 0) {
|
|
|
|
|
return VOLUME_FRAME_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int frame = scene_frame - frame_start + 1;
|
|
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
|
case VOLUME_SEQUENCE_CLIP: {
|
|
|
|
|
if (frame < 1 || frame > frame_duration) {
|
|
|
|
|
return VOLUME_FRAME_NONE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case VOLUME_SEQUENCE_EXTEND: {
|
|
|
|
|
frame = clamp_i(frame, 1, frame_duration);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case VOLUME_SEQUENCE_REPEAT: {
|
|
|
|
|
frame = frame % frame_duration;
|
|
|
|
|
if (frame < 0) {
|
|
|
|
|
frame += frame_duration;
|
|
|
|
|
}
|
|
|
|
|
if (frame == 0) {
|
|
|
|
|
frame = frame_duration;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case VOLUME_SEQUENCE_PING_PONG: {
|
|
|
|
|
const int pingpong_duration = frame_duration * 2 - 2;
|
|
|
|
|
frame = frame % pingpong_duration;
|
|
|
|
|
if (frame < 0) {
|
|
|
|
|
frame += pingpong_duration;
|
|
|
|
|
}
|
|
|
|
|
if (frame == 0) {
|
|
|
|
|
frame = pingpong_duration;
|
|
|
|
|
}
|
|
|
|
|
if (frame > frame_duration) {
|
|
|
|
|
frame = frame_duration * 2 - frame;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-22 10:42:32 -07:00
|
|
|
/* Important to apply after, else we can't loop on e.g. frames 100 - 110. */
|
2020-03-17 14:41:48 +01:00
|
|
|
frame += frame_offset;
|
|
|
|
|
|
|
|
|
|
return frame;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-21 14:40:51 +01:00
|
|
|
#ifdef WITH_OPENVDB
|
2020-03-17 14:41:48 +01:00
|
|
|
static void volume_filepath_get(const Main *bmain, const Volume *volume, char r_filepath[FILE_MAX])
|
|
|
|
|
{
|
|
|
|
|
BLI_strncpy(r_filepath, volume->filepath, FILE_MAX);
|
|
|
|
|
BLI_path_abs(r_filepath, ID_BLEND_PATH(bmain, &volume->id));
|
|
|
|
|
|
|
|
|
|
int path_frame, path_digits;
|
|
|
|
|
if (volume->is_sequence && BLI_path_frame_get(r_filepath, &path_frame, &path_digits)) {
|
|
|
|
|
char ext[32];
|
2023-04-20 11:45:05 +10:00
|
|
|
BLI_path_frame_strip(r_filepath, ext, sizeof(ext));
|
2024-01-06 13:26:59 +01:00
|
|
|
BLI_path_frame(r_filepath, FILE_MAX, volume->runtime->frame, path_digits);
|
2020-03-17 14:41:48 +01:00
|
|
|
BLI_path_extension_ensure(r_filepath, FILE_MAX, ext);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-21 14:40:51 +01:00
|
|
|
#endif
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
/* File Load */
|
|
|
|
|
|
|
|
|
|
bool BKE_volume_is_loaded(const Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
|
|
|
|
/* Test if there is a file to load, or if already loaded. */
|
2024-01-06 13:26:59 +01:00
|
|
|
return (volume->filepath[0] == '\0' || volume->runtime->grids->is_loaded());
|
2020-03-17 14:41:48 +01:00
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume);
|
|
|
|
|
return true;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-19 16:28:14 +02:00
|
|
|
bool BKE_volume_set_velocity_grid_by_name(Volume *volume, const char *base_name)
|
|
|
|
|
{
|
|
|
|
|
const StringRefNull ref_base_name = base_name;
|
|
|
|
|
|
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
|
|
|
if (BKE_volume_grid_find(volume, base_name)) {
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(volume->velocity_grid, base_name);
|
2024-01-06 13:26:59 +01:00
|
|
|
volume->runtime->velocity_x_grid[0] = '\0';
|
|
|
|
|
volume->runtime->velocity_y_grid[0] = '\0';
|
|
|
|
|
volume->runtime->velocity_z_grid[0] = '\0';
|
2022-04-19 16:28:14 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* It could be that the velocity grid is split in multiple grids, try with known postfixes. */
|
|
|
|
|
const StringRefNull postfixes[][3] = {{"x", "y", "z"}, {".x", ".y", ".z"}, {"_x", "_y", "_z"}};
|
|
|
|
|
|
|
|
|
|
for (const StringRefNull *postfix : postfixes) {
|
|
|
|
|
bool found = true;
|
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
|
std::string post_fixed_name = ref_base_name + postfix[i];
|
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
|
|
|
if (!BKE_volume_grid_find(volume, post_fixed_name.c_str())) {
|
2022-04-19 16:28:14 +02:00
|
|
|
found = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Save the base name as well. */
|
2023-05-09 12:50:37 +10:00
|
|
|
STRNCPY(volume->velocity_grid, base_name);
|
2024-01-06 13:26:59 +01:00
|
|
|
STRNCPY(volume->runtime->velocity_x_grid, (ref_base_name + postfix[0]).c_str());
|
|
|
|
|
STRNCPY(volume->runtime->velocity_y_grid, (ref_base_name + postfix[1]).c_str());
|
|
|
|
|
STRNCPY(volume->runtime->velocity_z_grid, (ref_base_name + postfix[2]).c_str());
|
2022-04-19 16:28:14 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Reset to avoid potential issues. */
|
|
|
|
|
volume->velocity_grid[0] = '\0';
|
2024-01-06 13:26:59 +01:00
|
|
|
volume->runtime->velocity_x_grid[0] = '\0';
|
|
|
|
|
volume->runtime->velocity_y_grid[0] = '\0';
|
|
|
|
|
volume->runtime->velocity_z_grid[0] = '\0';
|
2022-04-19 16:28:14 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-08 12:00:26 -05:00
|
|
|
bool BKE_volume_load(const Volume *volume, const Main *bmain)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
const VolumeGridVector &const_grids = *volume->runtime->grids;
|
2020-03-17 14:41:48 +01:00
|
|
|
|
2024-01-06 13:26:59 +01:00
|
|
|
if (volume->runtime->frame == VOLUME_FRAME_NONE) {
|
2020-03-17 14:41:48 +01:00
|
|
|
/* Skip loading this frame, outside of sequence range. */
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BKE_volume_is_loaded(volume)) {
|
2021-04-08 12:00:26 -05:00
|
|
|
return const_grids.error_msg.empty();
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Double-checked lock. */
|
2021-04-08 12:00:26 -05:00
|
|
|
std::lock_guard<std::mutex> lock(const_grids.mutex);
|
2020-03-17 14:41:48 +01:00
|
|
|
if (BKE_volume_is_loaded(volume)) {
|
2021-04-08 12:00:26 -05:00
|
|
|
return const_grids.error_msg.empty();
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
2021-04-08 12:00:26 -05:00
|
|
|
/* Guarded by the lock, we can continue to access the grid vector,
|
|
|
|
|
* adding error messages or a new grid, etc. */
|
|
|
|
|
VolumeGridVector &grids = const_cast<VolumeGridVector &>(const_grids);
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
/* Get absolute file path at current frame. */
|
|
|
|
|
const char *volume_name = volume->id.name + 2;
|
2021-01-19 18:01:22 +01:00
|
|
|
char filepath[FILE_MAX];
|
|
|
|
|
volume_filepath_get(bmain, volume, filepath);
|
2020-03-17 14:41:48 +01:00
|
|
|
|
2021-01-19 18:01:22 +01:00
|
|
|
CLOG_INFO(&LOG, 1, "Volume %s: load %s", volume_name, filepath);
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
/* Test if file exists. */
|
2021-01-19 18:01:22 +01:00
|
|
|
if (!BLI_exists(filepath)) {
|
2020-03-17 14:41:48 +01:00
|
|
|
char filename[FILE_MAX];
|
2023-05-02 20:47:26 +10:00
|
|
|
BLI_path_split_file_part(filepath, filename, sizeof(filename));
|
2020-03-17 14:41:48 +01:00
|
|
|
grids.error_msg = filename + std::string(" not found");
|
|
|
|
|
CLOG_INFO(&LOG, 1, "Volume %s: %s", volume_name, grids.error_msg.c_str());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
blender::bke::volume_grid::file_cache::GridsFromFile grids_from_file =
|
|
|
|
|
blender::bke::volume_grid::file_cache::get_all_grids_from_file(filepath, 0);
|
2020-03-17 14:41:48 +01:00
|
|
|
|
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
|
|
|
if (!grids_from_file.error_message.empty()) {
|
|
|
|
|
grids.error_msg = grids_from_file.error_message;
|
2023-05-24 17:44:52 +02:00
|
|
|
CLOG_INFO(&LOG, 1, "Volume %s: %s", volume_name, grids.error_msg.c_str());
|
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
|
|
|
return false;
|
2023-05-24 17:44:52 +02:00
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
|
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
|
|
|
grids.metadata = std::move(grids_from_file.file_meta_data);
|
|
|
|
|
for (GVolumeGrid &volume_grid : grids_from_file.grids) {
|
|
|
|
|
grids.emplace_back(std::move(volume_grid));
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
2022-04-19 16:28:14 +02:00
|
|
|
/* Try to detect the velocity grid. */
|
|
|
|
|
const char *common_velocity_names[] = {"velocity", "vel", "v"};
|
|
|
|
|
for (const char *common_velocity_name : common_velocity_names) {
|
|
|
|
|
if (BKE_volume_set_velocity_grid_by_name(const_cast<Volume *>(volume), common_velocity_name)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-17 16:24:36 +11:00
|
|
|
STRNCPY(grids.filepath, filepath);
|
2021-01-19 18:01:22 +01:00
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
return grids.error_msg.empty();
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(bmain, volume);
|
|
|
|
|
return true;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_volume_unload(Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume->runtime->grids;
|
2020-03-17 14:41:48 +01:00
|
|
|
if (grids.filepath[0] != '\0') {
|
|
|
|
|
const char *volume_name = volume->id.name + 2;
|
|
|
|
|
CLOG_INFO(&LOG, 1, "Volume %s: unload", volume_name);
|
|
|
|
|
grids.clear_all();
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-07 16:39:51 +02:00
|
|
|
/* File Save */
|
|
|
|
|
|
2021-04-08 12:00:26 -05:00
|
|
|
bool BKE_volume_save(const Volume *volume,
|
|
|
|
|
const Main *bmain,
|
|
|
|
|
ReportList *reports,
|
|
|
|
|
const char *filepath)
|
2020-10-07 16:39:51 +02:00
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
|
|
|
|
if (!BKE_volume_load(volume, bmain)) {
|
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Could not load volume for writing");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume->runtime->grids;
|
2020-10-07 16:39:51 +02:00
|
|
|
openvdb::GridCPtrVec vdb_grids;
|
|
|
|
|
|
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
|
|
|
/* Tree users need to be kept alive for as long as the grids may be accessed. */
|
2024-01-10 15:20:08 +01:00
|
|
|
blender::Vector<blender::bke::VolumeTreeAccessToken> tree_tokens;
|
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
|
|
|
|
|
|
|
|
for (const GVolumeGrid &grid : grids) {
|
2024-01-10 15:20:08 +01:00
|
|
|
tree_tokens.append_as();
|
|
|
|
|
vdb_grids.push_back(grid->grid_ptr(tree_tokens.last()));
|
2020-10-07 16:39:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
openvdb::io::File file(filepath);
|
|
|
|
|
file.write(vdb_grids, *grids.metadata);
|
|
|
|
|
file.close();
|
|
|
|
|
}
|
|
|
|
|
catch (const openvdb::IoError &e) {
|
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Could not write volume: %s", e.what());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-05-24 17:44:52 +02:00
|
|
|
catch (...) {
|
|
|
|
|
BKE_reportf(reports, RPT_ERROR, "Could not write volume: Unknown error writing VDB file");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-10-07 16:39:51 +02:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume, bmain, reports, filepath);
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-27 16:14:49 +01:00
|
|
|
std::optional<blender::Bounds<blender::float3>> BKE_volume_min_max(const Volume *volume)
|
2021-04-08 13:44:54 -05:00
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
|
|
|
|
/* TODO: if we know the volume is going to be displayed, it may be good to
|
|
|
|
|
* load it as part of dependency graph evaluation for better threading. We
|
|
|
|
|
* could also share the bounding box computation in the global volume cache. */
|
|
|
|
|
if (BKE_volume_load(const_cast<Volume *>(volume), G.main)) {
|
2023-11-27 16:14:49 +01:00
|
|
|
std::optional<blender::Bounds<blender::float3>> result;
|
2021-04-08 13:44:54 -05:00
|
|
|
for (const int i : IndexRange(BKE_volume_num_grids(volume))) {
|
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
|
|
|
const blender::bke::VolumeGridData *volume_grid = BKE_volume_grid_get(volume, i);
|
2024-01-10 15:20:08 +01:00
|
|
|
blender::bke::VolumeTreeAccessToken tree_token;
|
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
|
|
|
result = blender::bounds::merge(result,
|
2024-01-10 15:20:08 +01:00
|
|
|
BKE_volume_grid_bounds(volume_grid->grid_ptr(tree_token)));
|
2021-04-08 13:44:54 -05:00
|
|
|
}
|
2023-11-27 16:14:49 +01:00
|
|
|
return result;
|
2021-04-08 13:44:54 -05:00
|
|
|
}
|
|
|
|
|
#else
|
2023-11-27 16:14:49 +01:00
|
|
|
UNUSED_VARS(volume);
|
2021-04-08 13:44:54 -05:00
|
|
|
#endif
|
2023-11-27 16:14:49 +01:00
|
|
|
return std::nullopt;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BKE_volume_is_y_up(const Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
/* Simple heuristic for common files to open the right way up. */
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume->runtime->grids;
|
2020-03-17 14:41:48 +01:00
|
|
|
if (grids.metadata) {
|
|
|
|
|
openvdb::StringMetadata::ConstPtr creator =
|
|
|
|
|
grids.metadata->getMetadata<openvdb::StringMetadata>("creator");
|
|
|
|
|
if (!creator) {
|
|
|
|
|
creator = grids.metadata->getMetadata<openvdb::StringMetadata>("Creator");
|
|
|
|
|
}
|
|
|
|
|
return (creator && creator->str().rfind("Houdini", 0) == 0);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BKE_volume_is_points_only(const Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
int num_grids = BKE_volume_num_grids(volume);
|
|
|
|
|
if (num_grids == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < num_grids; i++) {
|
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
|
|
|
const blender::bke::VolumeGridData *grid = BKE_volume_grid_get(volume, i);
|
|
|
|
|
if (blender::bke::volume_grid::get_type(*grid) != VOLUME_GRID_POINTS) {
|
2020-03-17 14:41:48 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Dependency Graph */
|
|
|
|
|
|
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
|
|
|
static void volume_update_simplify_level(Main *bmain, Volume *volume, const Depsgraph *depsgraph)
|
2020-10-20 11:00:16 +02:00
|
|
|
{
|
2020-10-20 15:07:12 +02:00
|
|
|
#ifdef WITH_OPENVDB
|
2020-10-20 11:00:16 +02:00
|
|
|
const int simplify_level = BKE_volume_simplify_level(depsgraph);
|
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
|
|
|
|
|
|
|
|
/* Replace grids with the new simplify level variants from the cache. */
|
|
|
|
|
if (BKE_volume_load(volume, bmain)) {
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume->runtime->grids;
|
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
|
|
|
std::list<GVolumeGrid> new_grids;
|
|
|
|
|
for (const GVolumeGrid &old_grid : grids) {
|
|
|
|
|
GVolumeGrid simple_grid = blender::bke::volume_grid::file_cache::get_grid_from_file(
|
|
|
|
|
grids.filepath, old_grid->name(), simplify_level);
|
|
|
|
|
BLI_assert(simple_grid);
|
|
|
|
|
new_grids.push_back(std::move(simple_grid));
|
2020-10-20 11:00:16 +02:00
|
|
|
}
|
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
|
|
|
grids.swap(new_grids);
|
2020-10-20 11:00:16 +02:00
|
|
|
}
|
2020-10-20 15:07:12 +02:00
|
|
|
#else
|
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
|
|
|
UNUSED_VARS(bmain, volume, depsgraph);
|
2020-10-20 15:07:12 +02:00
|
|
|
#endif
|
2020-10-20 11:00:16 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
static void volume_evaluate_modifiers(Depsgraph *depsgraph,
|
|
|
|
|
Scene *scene,
|
2021-04-20 09:30:53 +02:00
|
|
|
Object *object,
|
2023-06-15 22:18:28 +02:00
|
|
|
blender::bke::GeometrySet &geometry_set)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
2020-04-21 13:09:41 +02:00
|
|
|
/* Modifier evaluation modes. */
|
|
|
|
|
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
|
|
|
|
|
const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
|
|
|
|
|
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
|
|
|
|
|
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
|
|
|
|
|
|
2022-07-26 13:01:30 +02:00
|
|
|
BKE_modifiers_clear_errors(object);
|
|
|
|
|
|
2020-04-21 13:09:41 +02:00
|
|
|
/* Get effective list of modifiers to execute. Some effects like shape keys
|
|
|
|
|
* are added as virtual modifiers before the user created modifiers. */
|
2023-07-27 12:04:18 +10:00
|
|
|
VirtualModifierData virtual_modifier_data;
|
|
|
|
|
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtual_modifier_data);
|
2020-04-21 13:09:41 +02:00
|
|
|
|
|
|
|
|
/* Evaluate modifiers. */
|
|
|
|
|
for (; md; md = md->next) {
|
2020-05-08 10:14:02 +02:00
|
|
|
const ModifierTypeInfo *mti = (const ModifierTypeInfo *)BKE_modifier_get_info(
|
2020-04-21 13:09:41 +02:00
|
|
|
(ModifierType)md->type);
|
|
|
|
|
|
2020-05-08 10:14:02 +02:00
|
|
|
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
|
2020-04-21 13:09:41 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
Modifiers: measure execution time and provide Python access
The goal is to give technical artists the ability to optimize modifier usage
and/or geometry node groups for performance. In the long term, it
would be useful if Blender could provide its own UI to display profiling
information to users. However, right now, there are too many open
design questions making it infeasible to tackle this in the short term.
This commit uses a simpler approach: Instead of adding new ui for
profiling data, it exposes the execution-time of modifiers in the Python
API. This allows technical artists to access the information and to build
their own UI to display the relevant information. In the long term this
will hopefully also help us to integrate a native ui for this in Blender
by observing how users use this information.
Note: The execution time of a modifier highly depends on what other
things the CPU is doing at the same time. For example, in many more
complex files, many objects and therefore modifiers are evaluated at
the same time by multiple threads which makes the measurement
much less reliable. For best results, make sure that only one object
is evaluated at a time (e.g. by changing it in isolation) and that no
other process on the system keeps the CPU busy.
As shown below, the execution time has to be accessed on the
evaluated object, not the original object.
```lang=python
import bpy
depsgraph = bpy.context.view_layer.depsgraph
ob = bpy.context.active_object
ob_eval = ob.evaluated_get(depsgraph)
modifier_eval = ob_eval.modifiers[0]
print(modifier_eval.execution_time, "s")
```
Differential Revision: https://developer.blender.org/D17185
2023-02-06 15:39:59 +01:00
|
|
|
blender::bke::ScopedModifierTimer modifier_timer{*md};
|
|
|
|
|
|
2023-07-27 12:04:18 +10:00
|
|
|
if (mti->modify_geometry_set) {
|
|
|
|
|
mti->modify_geometry_set(md, &mectx, &geometry_set);
|
2021-04-20 09:30:53 +02:00
|
|
|
}
|
2020-04-21 13:09:41 +02:00
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void BKE_volume_eval_geometry(Depsgraph *depsgraph, Volume *volume)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
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
|
|
|
Main *bmain = DEG_get_bmain(depsgraph);
|
|
|
|
|
volume_update_simplify_level(bmain, volume, depsgraph);
|
2020-10-20 11:00:16 +02:00
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
/* TODO: can we avoid modifier re-evaluation when frame did not change? */
|
|
|
|
|
int frame = volume_sequence_frame(depsgraph, volume);
|
2024-01-06 13:26:59 +01:00
|
|
|
if (frame != volume->runtime->frame) {
|
2020-03-17 14:41:48 +01:00
|
|
|
BKE_volume_unload(volume);
|
2024-01-06 13:26:59 +01:00
|
|
|
volume->runtime->frame = frame;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Flush back to original. */
|
|
|
|
|
if (DEG_is_active(depsgraph)) {
|
|
|
|
|
Volume *volume_orig = (Volume *)DEG_get_original_id(&volume->id);
|
2024-01-06 13:26:59 +01:00
|
|
|
if (volume_orig->runtime->frame != volume->runtime->frame) {
|
2020-05-07 21:13:14 +02:00
|
|
|
BKE_volume_unload(volume_orig);
|
2024-01-06 13:26:59 +01:00
|
|
|
volume_orig->runtime->frame = volume->runtime->frame;
|
2020-05-07 21:13:14 +02:00
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-15 22:18:28 +02:00
|
|
|
static Volume *take_volume_ownership_from_geometry_set(blender::bke::GeometrySet &geometry_set)
|
2021-04-20 09:30:53 +02:00
|
|
|
{
|
2023-06-15 22:18:28 +02:00
|
|
|
if (!geometry_set.has<blender::bke::VolumeComponent>()) {
|
2021-04-20 09:30:53 +02:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
2023-06-15 22:18:28 +02:00
|
|
|
auto &volume_component = geometry_set.get_component_for_write<blender::bke::VolumeComponent>();
|
2021-04-20 09:30:53 +02:00
|
|
|
Volume *volume = volume_component.release();
|
|
|
|
|
if (volume != nullptr) {
|
|
|
|
|
/* Add back, but only as read-only non-owning component. */
|
2023-06-15 22:18:28 +02:00
|
|
|
volume_component.replace(volume, blender::bke::GeometryOwnershipType::ReadOnly);
|
2021-04-20 09:30:53 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* The component was empty, we can remove it. */
|
2023-06-15 22:18:28 +02:00
|
|
|
geometry_set.remove<blender::bke::VolumeComponent>();
|
2021-04-20 09:30:53 +02:00
|
|
|
}
|
|
|
|
|
return volume;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
void BKE_volume_data_update(Depsgraph *depsgraph, Scene *scene, Object *object)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
/* Free any evaluated data and restore original data. */
|
|
|
|
|
BKE_object_free_derived_caches(object);
|
|
|
|
|
|
|
|
|
|
/* Evaluate modifiers. */
|
|
|
|
|
Volume *volume = (Volume *)object->data;
|
2023-06-15 22:18:28 +02:00
|
|
|
blender::bke::GeometrySet geometry_set;
|
|
|
|
|
geometry_set.replace_volume(volume, blender::bke::GeometryOwnershipType::ReadOnly);
|
2021-04-26 14:42:03 -05:00
|
|
|
volume_evaluate_modifiers(depsgraph, scene, object, geometry_set);
|
2021-04-20 09:30:53 +02:00
|
|
|
|
|
|
|
|
Volume *volume_eval = take_volume_ownership_from_geometry_set(geometry_set);
|
|
|
|
|
|
|
|
|
|
/* If the geometry set did not contain a volume, we still create an empty one. */
|
|
|
|
|
if (volume_eval == nullptr) {
|
|
|
|
|
volume_eval = BKE_volume_new_for_eval(volume);
|
|
|
|
|
}
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
/* Assign evaluated object. */
|
2021-04-20 09:30:53 +02:00
|
|
|
const bool eval_is_owned = (volume != volume_eval);
|
|
|
|
|
BKE_object_eval_assign_data(object, &volume_eval->id, eval_is_owned);
|
2023-11-15 18:46:07 +01:00
|
|
|
object->runtime->geometry_set_eval = new blender::bke::GeometrySet(std::move(geometry_set));
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_volume_grids_backup_restore(Volume *volume, VolumeGridVector *grids, const char *filepath)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
|
|
|
|
/* Restore grids after datablock was re-copied from original by depsgraph,
|
|
|
|
|
* we don't want to load them again if possible. */
|
|
|
|
|
BLI_assert(volume->id.tag & LIB_TAG_COPIED_ON_WRITE);
|
2024-01-06 13:26:59 +01:00
|
|
|
BLI_assert(volume->runtime->grids != nullptr && grids != nullptr);
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
if (!grids->is_loaded()) {
|
|
|
|
|
/* No grids loaded in CoW datablock, nothing lost by discarding. */
|
2021-12-17 15:38:15 +01:00
|
|
|
MEM_delete(grids);
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
else if (!STREQ(volume->filepath, filepath)) {
|
|
|
|
|
/* Filepath changed, discard grids from CoW datablock. */
|
2021-12-17 15:38:15 +01:00
|
|
|
MEM_delete(grids);
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Keep grids from CoW datablock. We might still unload them a little
|
|
|
|
|
* later in BKE_volume_eval_geometry if the frame changes. */
|
2024-01-06 13:26:59 +01:00
|
|
|
MEM_delete(volume->runtime->grids);
|
|
|
|
|
volume->runtime->grids = grids;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
#else
|
2020-03-26 15:36:24 +11:00
|
|
|
UNUSED_VARS(volume, grids, filepath);
|
2020-03-17 14:41:48 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Draw Cache */
|
|
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
void (*BKE_volume_batch_cache_dirty_tag_cb)(Volume *volume, int mode) = nullptr;
|
|
|
|
|
void (*BKE_volume_batch_cache_free_cb)(Volume *volume) = nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
|
2020-10-09 07:25:43 +02:00
|
|
|
void BKE_volume_batch_cache_dirty_tag(Volume *volume, int mode)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
if (volume->batch_cache) {
|
|
|
|
|
BKE_volume_batch_cache_dirty_tag_cb(volume, mode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BKE_volume_batch_cache_free(Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
if (volume->batch_cache) {
|
|
|
|
|
BKE_volume_batch_cache_free_cb(volume);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Grids */
|
|
|
|
|
|
|
|
|
|
int BKE_volume_num_grids(const Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
return volume->runtime->grids->size();
|
2020-03-17 14:41:48 +01:00
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume);
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *BKE_volume_grids_error_msg(const Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
return volume->runtime->grids->error_msg.c_str();
|
2020-03-17 14:41:48 +01:00
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume);
|
|
|
|
|
return "";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-05 21:25:33 +02:00
|
|
|
const char *BKE_volume_grids_frame_filepath(const Volume *volume)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
return volume->runtime->grids->filepath;
|
2020-04-05 21:25:33 +02:00
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume);
|
|
|
|
|
return "";
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
const blender::bke::VolumeGridData *BKE_volume_grid_get(const Volume *volume, int grid_index)
|
2021-04-08 12:00:26 -05:00
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
const VolumeGridVector &grids = *volume->runtime->grids;
|
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
|
|
|
for (const GVolumeGrid &grid : grids) {
|
2021-04-08 12:00:26 -05:00
|
|
|
if (grid_index-- == 0) {
|
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
|
|
|
return &grid.get();
|
2021-04-08 12:00:26 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume, grid_index);
|
|
|
|
|
return nullptr;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
blender::bke::VolumeGridData *BKE_volume_grid_get_for_write(Volume *volume, int grid_index)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume->runtime->grids;
|
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
|
|
|
for (GVolumeGrid &grid_ptr : grids) {
|
2020-03-17 14:41:48 +01:00
|
|
|
if (grid_index-- == 0) {
|
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
|
|
|
return &grid_ptr.get_for_write();
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-11-06 17:49:09 +01:00
|
|
|
return nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume, grid_index);
|
2020-11-09 20:42:36 +05:30
|
|
|
return nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
const blender::bke::VolumeGridData *BKE_volume_grid_active_get_for_read(const Volume *volume)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
const int num_grids = BKE_volume_num_grids(volume);
|
|
|
|
|
if (num_grids == 0) {
|
2020-11-06 17:49:09 +01:00
|
|
|
return nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int index = clamp_i(volume->active_grid, 0, num_grids - 1);
|
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
|
|
|
return BKE_volume_grid_get(volume, index);
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
const blender::bke::VolumeGridData *BKE_volume_grid_find(const Volume *volume, const char *name)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
int num_grids = BKE_volume_num_grids(volume);
|
|
|
|
|
for (int i = 0; i < num_grids; i++) {
|
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
|
|
|
const blender::bke::VolumeGridData *grid = BKE_volume_grid_get(volume, i);
|
|
|
|
|
if (blender::bke::volume_grid::get_name(*grid) == name) {
|
2020-03-17 14:41:48 +01:00
|
|
|
return grid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 17:49:09 +01:00
|
|
|
return nullptr;
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
blender::bke::VolumeGridData *BKE_volume_grid_find_for_write(Volume *volume, const char *name)
|
2023-03-19 11:21:08 +01:00
|
|
|
{
|
|
|
|
|
int num_grids = BKE_volume_num_grids(volume);
|
|
|
|
|
for (int i = 0; i < num_grids; i++) {
|
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
|
|
|
const blender::bke::VolumeGridData *grid = BKE_volume_grid_get(volume, i);
|
|
|
|
|
if (blender::bke::volume_grid::get_name(*grid) == name) {
|
|
|
|
|
return BKE_volume_grid_get_for_write(volume, i);
|
2023-03-19 11:21:08 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
/* Grid Tree and Voxels */
|
|
|
|
|
|
|
|
|
|
/* Volume Editing */
|
|
|
|
|
|
|
|
|
|
Volume *BKE_volume_new_for_eval(const Volume *volume_src)
|
|
|
|
|
{
|
2020-11-06 17:49:09 +01:00
|
|
|
Volume *volume_dst = (Volume *)BKE_id_new_nomain(ID_VO, nullptr);
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
STRNCPY(volume_dst->id.name, volume_src->id.name);
|
|
|
|
|
volume_dst->mat = (Material **)MEM_dupallocN(volume_src->mat);
|
|
|
|
|
volume_dst->totcol = volume_src->totcol;
|
2020-10-01 15:42:11 +02:00
|
|
|
volume_dst->render = volume_src->render;
|
|
|
|
|
volume_dst->display = volume_src->display;
|
2020-03-17 14:41:48 +01:00
|
|
|
|
|
|
|
|
return volume_dst;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-12 14:26:27 -04:00
|
|
|
Volume *BKE_volume_copy_for_eval(const Volume *volume_src)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
2023-04-19 15:49:13 -04:00
|
|
|
return reinterpret_cast<Volume *>(
|
|
|
|
|
BKE_id_copy_ex(nullptr, &volume_src->id, nullptr, LIB_ID_COPY_LOCALIZE));
|
2020-03-17 14:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
2020-10-05 23:01:38 +11:00
|
|
|
#ifdef WITH_OPENVDB
|
2020-10-05 10:29:34 +02:00
|
|
|
struct CreateGridOp {
|
|
|
|
|
template<typename GridType> typename openvdb::GridBase::Ptr operator()()
|
|
|
|
|
{
|
|
|
|
|
if constexpr (std::is_same_v<GridType, openvdb::points::PointDataGrid>) {
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return GridType::create();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-10-05 23:01:38 +11:00
|
|
|
#endif
|
2020-10-05 10:29:34 +02:00
|
|
|
|
2021-10-26 11:25:44 -05:00
|
|
|
#ifdef WITH_OPENVDB
|
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
|
|
|
blender::bke::VolumeGridData *BKE_volume_grid_add_vdb(Volume &volume,
|
|
|
|
|
const StringRef name,
|
|
|
|
|
openvdb::GridBase::Ptr vdb_grid)
|
2021-10-26 11:25:44 -05:00
|
|
|
{
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume.runtime->grids;
|
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
|
|
|
BLI_assert(BKE_volume_grid_find(&volume, name.data()) == nullptr);
|
|
|
|
|
BLI_assert(blender::bke::volume_grid::get_type(*vdb_grid) != VOLUME_GRID_UNKNOWN);
|
2021-10-26 11:25:44 -05:00
|
|
|
|
|
|
|
|
vdb_grid->setName(name);
|
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
|
|
|
grids.emplace_back(GVolumeGrid(std::move(vdb_grid)));
|
|
|
|
|
return &grids.back().get_for_write();
|
2021-10-26 11:25:44 -05:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
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
|
|
|
void BKE_volume_grid_remove(Volume *volume, const blender::bke::VolumeGridData *grid)
|
2020-03-17 14:41:48 +01:00
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume->runtime->grids;
|
2020-03-17 14:41:48 +01:00
|
|
|
for (VolumeGridVector::iterator it = grids.begin(); it != grids.end(); it++) {
|
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
|
|
|
if (&it->get() == grid) {
|
2020-03-17 14:41:48 +01:00
|
|
|
grids.erase(it);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume, grid);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
void BKE_volume_grid_add(Volume *volume, const blender::bke::VolumeGridData &grid)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2024-01-06 13:26:59 +01:00
|
|
|
VolumeGridVector &grids = *volume->runtime->grids;
|
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
|
|
|
grids.push_back(GVolumeGrid(&grid));
|
|
|
|
|
#else
|
|
|
|
|
UNUSED_VARS(volume, grid);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-29 17:00:08 +02:00
|
|
|
bool BKE_volume_grid_determinant_valid(const double determinant)
|
|
|
|
|
{
|
|
|
|
|
#ifdef WITH_OPENVDB
|
|
|
|
|
/* Limit taken from openvdb/math/Maps.h. */
|
|
|
|
|
return std::abs(determinant) >= 3.0 * openvdb::math::Tolerance<double>::value();
|
|
|
|
|
#else
|
2022-08-29 12:12:16 -05:00
|
|
|
UNUSED_VARS(determinant);
|
2022-08-29 17:00:08 +02:00
|
|
|
return true;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 11:00:16 +02:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
/* OpenVDB Grid Access */
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_OPENVDB
|
2021-04-08 13:28:35 -05:00
|
|
|
|
2023-11-27 16:14:49 +01:00
|
|
|
std::optional<blender::Bounds<float3>> BKE_volume_grid_bounds(openvdb::GridBase::ConstPtr grid)
|
2021-04-08 13:44:54 -05:00
|
|
|
{
|
|
|
|
|
/* TODO: we can get this from grid metadata in some cases? */
|
|
|
|
|
openvdb::CoordBBox coordbbox;
|
|
|
|
|
if (!grid->baseTree().evalLeafBoundingBox(coordbbox)) {
|
2023-11-27 16:14:49 +01:00
|
|
|
return std::nullopt;
|
2021-04-08 13:44:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
openvdb::BBoxd bbox = grid->transform().indexToWorld(coordbbox);
|
|
|
|
|
|
2023-11-27 16:14:49 +01:00
|
|
|
return blender::Bounds<float3>{float3(bbox.min().asPointer()), float3(bbox.max().asPointer())};
|
2021-04-08 13:44:54 -05:00
|
|
|
}
|
|
|
|
|
|
2021-04-08 13:28:35 -05:00
|
|
|
openvdb::GridBase::ConstPtr BKE_volume_grid_shallow_transform(openvdb::GridBase::ConstPtr grid,
|
|
|
|
|
const blender::float4x4 &transform)
|
|
|
|
|
{
|
|
|
|
|
openvdb::math::Transform::Ptr grid_transform = grid->transform().copy();
|
2023-02-06 21:25:45 +01:00
|
|
|
grid_transform->postMult(openvdb::Mat4d((float *)transform.ptr()));
|
2021-04-08 13:28:35 -05:00
|
|
|
|
|
|
|
|
/* Create a transformed grid. The underlying tree is shared. */
|
|
|
|
|
return grid->copyGridReplacingTransform(grid_transform);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 11:00:16 +02:00
|
|
|
/* 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()()
|
|
|
|
|
{
|
2022-02-16 19:49:58 +01:00
|
|
|
return create_grid_with_changed_resolution(static_cast<const GridType &>(grid),
|
|
|
|
|
resolution_factor);
|
2020-10-20 11:00:16 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 14:41:48 +01:00
|
|
|
#endif
|