New Grid Info node for reading grid transforms and background value

These are generic properties of grids (not stored in voxels) which are
useful to know in geometry nodes. The transform in particular defines
the voxel size. Background value is used outside of active voxels.

Pull Request: https://projects.blender.org/blender/blender/pulls/138592
This commit is contained in:
Lukas Tönne
2025-05-12 13:46:40 +02:00
parent 800e2cdde1
commit 11ceddb9df
7 changed files with 151 additions and 22 deletions

View File

@@ -796,6 +796,7 @@ class NODE_MT_geometry_node_GEO_VOLUME_READ(Menu):
def draw(self, context):
layout = self.layout
node_add_menu.add_node_type(layout, "GeometryNodeGetNamedGrid")
node_add_menu.add_node_type(layout, "GeometryNodeGridInfo")
node_add_menu.draw_assets_for_catalog(layout, "Volume/Read")

View File

@@ -41,6 +41,9 @@ std::optional<blender::Bounds<blender::float3>> BKE_volume_grid_bounds(
openvdb::GridBase::ConstPtr BKE_volume_grid_shallow_transform(openvdb::GridBase::ConstPtr grid,
const blender::float4x4 &transform);
blender::float4x4 BKE_volume_transform_to_blender(const openvdb::math::Transform &transform);
openvdb::math::Transform BKE_volume_transform_to_openvdb(const blender::float4x4 &transform);
template<typename OpType>
auto BKE_volume_grid_type_operation(const VolumeGridType grid_type, OpType &&op)
{

View File

@@ -1092,6 +1092,32 @@ openvdb::GridBase::ConstPtr BKE_volume_grid_shallow_transform(openvdb::GridBase:
return grid->copyGridReplacingTransform(grid_transform);
}
blender::float4x4 BKE_volume_transform_to_blender(const openvdb::math::Transform &transform)
{
/* Perspective not supported for now, getAffineMap() will leave out the
* perspective part of the transform. */
const openvdb::math::Mat4f matrix = transform.baseMap()->getAffineMap()->getMat4();
/* Blender column-major and OpenVDB right-multiplication conventions match. */
float4x4 result;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 4; row++) {
result[col][row] = matrix(col, row);
}
}
return result;
}
openvdb::math::Transform BKE_volume_transform_to_openvdb(const blender::float4x4 &transform)
{
openvdb::math::Mat4f matrix_openvdb;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 4; row++) {
matrix_openvdb(col, row) = transform[col][row];
}
}
return openvdb::math::Transform(std::make_shared<openvdb::math::AffineMap>(matrix_openvdb));
}
/* Changing the resolution of a grid. */
/**

View File

@@ -436,19 +436,7 @@ int get_channels_num(const VolumeGridType type)
float4x4 get_transform_matrix(const VolumeGridData &grid)
{
#ifdef WITH_OPENVDB
const openvdb::math::Transform &transform = grid.transform();
/* Perspective not supported for now, getAffineMap() will leave out the
* perspective part of the transform. */
openvdb::math::Mat4f matrix = transform.baseMap()->getAffineMap()->getMat4();
/* Blender column-major and OpenVDB right-multiplication conventions match. */
float4x4 result;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 4; row++) {
result[col][row] = matrix(col, row);
}
}
return result;
return BKE_volume_transform_to_blender(grid.transform());
#else
UNUSED_VARS(grid);
return float4x4::identity();
@@ -458,15 +446,7 @@ float4x4 get_transform_matrix(const VolumeGridData &grid)
void set_transform_matrix(VolumeGridData &grid, const float4x4 &matrix)
{
#ifdef WITH_OPENVDB
openvdb::math::Mat4f matrix_openvdb;
for (int col = 0; col < 4; col++) {
for (int row = 0; row < 4; row++) {
matrix_openvdb(col, row) = matrix[col][row];
}
}
grid.transform_for_write() = openvdb::math::Transform(
std::make_shared<openvdb::math::AffineMap>(matrix_openvdb));
grid.transform_for_write() = BKE_volume_transform_to_openvdb(matrix);
#else
UNUSED_VARS(grid, matrix);
#endif

View File

@@ -13883,6 +13883,7 @@ static void rna_def_nodes(BlenderRNA *brna)
define("GeometryNode", "GeometryNodeGizmoLinear");
define("GeometryNode", "GeometryNodeGizmoTransform", rna_def_geo_gizmo_transform);
define("GeometryNode", "GeometryNodeGreasePencilToCurves");
define("GeometryNode", "GeometryNodeGridInfo");
define("GeometryNode", "GeometryNodeGridToMesh");
define("GeometryNode", "GeometryNodeImageInfo");
define("GeometryNode", "GeometryNodeImageTexture", def_geo_image_texture);

View File

@@ -89,6 +89,7 @@ set(SRC
nodes/node_geo_gizmo_linear.cc
nodes/node_geo_gizmo_transform.cc
nodes/node_geo_grease_pencil_to_curves.cc
nodes/node_geo_grid_info.cc
nodes/node_geo_grid_to_mesh.cc
nodes/node_geo_image.cc
nodes/node_geo_image_info.cc

View File

@@ -0,0 +1,117 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "node_geometry_util.hh"
#include "BLI_math_matrix.hh"
#include "BKE_attribute_math.hh"
#include "BKE_volume_grid.hh"
#include "BKE_volume_openvdb.hh"
#include "NOD_rna_define.hh"
#include "NOD_socket.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"
#include "RNA_enum_types.hh"
namespace blender::nodes::node_geo_grid_info_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
const bNode *node = b.node_or_null();
if (!node) {
return;
}
const eNodeSocketDatatype data_type = eNodeSocketDatatype(node->custom1);
b.add_input(data_type, "Grid").hide_value();
b.add_output<decl::Matrix>("Transform")
.description("Transform from grid index space to object space");
b.add_output(data_type, "Background Value").description("Default value outside of grid voxels");
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
uiLayoutSetPropSep(layout, true);
uiLayoutSetPropDecorate(layout, false);
layout->prop(ptr, "data_type", UI_ITEM_NONE, "", ICON_NONE);
}
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_OPENVDB
const eNodeSocketDatatype data_type = eNodeSocketDatatype(params.node().custom1);
const auto grid = params.extract_input<bke::GVolumeGrid>("Grid");
if (!grid) {
params.set_default_remaining_outputs();
return;
}
bke::VolumeTreeAccessToken tree_token;
const std::shared_ptr<const openvdb::GridBase> vdb_grid = grid->grid_ptr(tree_token);
params.set_output("Transform", BKE_volume_transform_to_blender(vdb_grid->transform()));
bke::attribute_math::convert_to_static_type(
*bke::socket_type_to_geo_nodes_base_cpp_type(data_type), [&](auto type_tag) {
using ValueT = decltype(type_tag);
using type_traits = typename bke::VolumeGridTraits<ValueT>;
using TreeType = typename type_traits::TreeType;
using GridType = openvdb::Grid<TreeType>;
if constexpr (!std::is_same_v<typename type_traits::BlenderType, void>) {
const std::shared_ptr<const GridType> vdb_typed_grid = openvdb::GridBase::grid<GridType>(
vdb_grid);
params.set_output("Background Value",
type_traits::to_blender(vdb_typed_grid->background()));
}
});
#else
params.set_default_remaining_outputs();
params.error_message_add(NodeWarningType::Error,
TIP_("Disabled, Blender was compiled without OpenVDB"));
#endif
}
static void node_init(bNodeTree * /*tree*/, bNode *node)
{
node->custom1 = SOCK_FLOAT;
}
static void node_rna(StructRNA *srna)
{
RNA_def_node_enum(srna,
"data_type",
"Data Type",
"Type of grid data",
rna_enum_node_socket_data_type_items,
NOD_inline_enum_accessors(custom1),
SOCK_FLOAT,
grid_socket_type_items_filter_fn);
}
static void node_register()
{
static blender::bke::bNodeType ntype;
geo_node_type_base(&ntype, "GeometryNodeGridInfo");
ntype.ui_name = "Grid Info";
ntype.ui_description = "Retrieve information about a volume grid";
ntype.nclass = NODE_CLASS_INPUT;
ntype.initfunc = node_init;
ntype.geometry_node_execute = node_geo_exec;
ntype.draw_buttons = node_layout;
ntype.declare = node_declare;
blender::bke::node_register_type(ntype);
node_rna(ntype.rna_ext.srna);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_geo_grid_info_cc