Geometry Nodes: support volume grid sockets in bake node #120981
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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_) {
|
||||
|
|
Loading…
Reference in New Issue