Geometry Nodes: support volume grid sockets in bake node #120981

Merged
Jacques Lucke merged 4 commits from JacquesLucke/blender:bake-volume-grid-sockets into main 2024-04-23 18:56:51 +02:00
6 changed files with 106 additions and 0 deletions

View File

@ -6,6 +6,7 @@
#include "BKE_bake_data_block_map.hh"
#include "BKE_geometry_set.hh"
#include "BKE_volume_grid_fwd.hh"
namespace blender::bke::bake {
@ -81,6 +82,17 @@ class AttributeBakeItem : public BakeItem {
}
};
#ifdef WITH_OPENVDB
class VolumeGridBakeItem : public BakeItem {
public:
/** Using #unique_ptr so that `BKE_volume_grid_fwd.hh` can be used. */
std::unique_ptr<GVolumeGrid> grid;
VolumeGridBakeItem(std::unique_ptr<GVolumeGrid> grid);
~VolumeGridBakeItem();
};
#endif
/** Storage for a single value of a trivial type like `float`, `int`, etc. */
class PrimitiveBakeItem : public BakeItem {
private:

View File

@ -121,6 +121,11 @@ class SocketValueVariant {
*/
bool is_context_dependent_field() const;
/**
* The stored value is a volume grid.
*/
bool is_volume_grid() const;
/**
* Convert the stored value into a single value. For simple value access, this is not necessary,
* because #get` does the conversion implicitly. However, it is necessary if one wants to use

View File

@ -9,6 +9,7 @@
#include "BKE_mesh.hh"
#include "BKE_pointcloud.hh"
#include "BKE_volume.hh"
#include "BKE_volume_grid.hh"
#include "BLI_math_matrix_types.hh"
@ -134,6 +135,14 @@ void GeometryBakeItem::try_restore_data_blocks(GeometrySet &main_geometry,
});
}
#ifdef WITH_OPENVDB
VolumeGridBakeItem::VolumeGridBakeItem(std::unique_ptr<GVolumeGrid> grid) : grid(std::move(grid))
{
}
VolumeGridBakeItem::~VolumeGridBakeItem() = default;
#endif
PrimitiveBakeItem::PrimitiveBakeItem(const CPPType &type, const void *value) : type_(type)
{
value_ = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);

View File

@ -1197,6 +1197,23 @@ static void serialize_bake_item(const BakeItem &item,
r_io_item.append_str("type", "ATTRIBUTE");
r_io_item.append_str("name", attribute_state_item->name());
}
#ifdef WITH_OPENVDB
else if (const auto *grid_state_item = dynamic_cast<const VolumeGridBakeItem *>(&item)) {
r_io_item.append_str("type", "GRID");
const GVolumeGrid &grid = *grid_state_item->grid;
auto io_vdb = blob_writer
.write_as_stream(".vdb",
[&](std::ostream &stream) {
openvdb::GridCPtrVec vdb_grids;
bke::VolumeTreeAccessToken tree_token;
vdb_grids.push_back(grid->grid_ptr(tree_token));
openvdb::io::Stream vdb_stream(stream);
vdb_stream.write(vdb_grids);
})
.serialize();
r_io_item.append("vdb", std::move(io_vdb));
}
#endif
else if (const auto *string_state_item = dynamic_cast<const StringBakeItem *>(&item)) {
r_io_item.append_str("type", "STRING");
const StringRefNull str = string_state_item->value();
@ -1246,6 +1263,39 @@ static std::unique_ptr<BakeItem> deserialize_bake_item(const DictionaryValue &io
}
return std::make_unique<AttributeBakeItem>(std::move(*name));
}
#ifdef WITH_OPENVDB
if (*state_item_type == StringRef("GRID")) {
const DictionaryValue &io_grid = io_item;
const auto *io_vdb = io_grid.lookup_dict("vdb");
if (!io_vdb) {
return {};
}
std::optional<BlobSlice> vdb_slice = BlobSlice::deserialize(*io_vdb);
if (!vdb_slice) {
return {};
}
openvdb::GridPtrVecPtr vdb_grids;
if (!blob_reader.read_as_stream(*vdb_slice, [&](std::istream &stream) {
try {
openvdb::io::Stream vdb_stream{stream};
vdb_grids = vdb_stream.getGrids();
return true;
}
catch (...) {
return false;
}
}))
{
return {};
}
if (vdb_grids->size() != 1) {
return {};
}
std::shared_ptr<openvdb::GridBase> vdb_grid = std::move((*vdb_grids)[0]);
GVolumeGrid grid{std::move(vdb_grid)};
return std::make_unique<VolumeGridBakeItem>(std::make_unique<GVolumeGrid>(grid));
}
#endif
if (*state_item_type == StringRef("STRING")) {
const std::shared_ptr<io::serialize::Value> *io_data = io_item.lookup("data");
if (!io_data) {

View File

@ -6,6 +6,7 @@
#include "BKE_geometry_fields.hh"
#include "BKE_node.hh"
#include "BKE_node_socket_value.hh"
#include "BKE_volume_grid.hh"
namespace blender::bke::bake {
@ -80,6 +81,14 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
}
bake_items[i] = std::make_unique<AttributeBakeItem>(attribute_name);
}
#ifdef WITH_OPENVDB
else if (value_variant.is_volume_grid()) {
bke::GVolumeGrid grid = value_variant.get<bke::GVolumeGrid>();
grid.get_for_write().set_name(config.names[i]);
bake_items[i] = std::make_unique<VolumeGridBakeItem>(
std::make_unique<bke::GVolumeGrid>(std::move(grid)));
}
#endif
else {
value_variant.convert_to_single();
GPointer value = value_variant.get_single_ptr();
@ -152,6 +161,22 @@ Array<std::unique_ptr<BakeItem>> move_socket_values_to_bake_items(const Span<voi
r_attribute_map.add(item->name(), attribute_id);
return true;
}
#ifdef WITH_OPENVDB
if (const auto *item = dynamic_cast<const VolumeGridBakeItem *>(&bake_item)) {
const GVolumeGrid &grid = *item->grid;
const VolumeGridType grid_type = grid->grid_type();
const std::optional<eNodeSocketDatatype> grid_socket_type = grid_type_to_socket_type(
grid_type);
if (!grid_socket_type) {
return false;
}
if (grid_socket_type == socket_type) {
new (r_value) SocketValueVariant(*item->grid);
return true;
}
return false;
}
#endif
return false;
}
case SOCK_STRING: {

View File

@ -229,6 +229,11 @@ bool SocketValueVariant::is_context_dependent_field() const
return field.node().depends_on_input();
}
bool SocketValueVariant::is_volume_grid() const
{
return kind_ == Kind::Grid;
}
void SocketValueVariant::convert_to_single()
{
switch (kind_) {