diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index b7374cd4af6..b5f17777f82 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -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") diff --git a/source/blender/blenkernel/BKE_volume_openvdb.hh b/source/blender/blenkernel/BKE_volume_openvdb.hh index 490b546da72..369bb80597f 100644 --- a/source/blender/blenkernel/BKE_volume_openvdb.hh +++ b/source/blender/blenkernel/BKE_volume_openvdb.hh @@ -41,6 +41,9 @@ std::optional> 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 auto BKE_volume_grid_type_operation(const VolumeGridType grid_type, OpType &&op) { diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index 0617ddfe3b3..41aeb34a837 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -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(matrix_openvdb)); +} + /* Changing the resolution of a grid. */ /** diff --git a/source/blender/blenkernel/intern/volume_grid.cc b/source/blender/blenkernel/intern/volume_grid.cc index 5325dcb9444..7e1d8a08f7a 100644 --- a/source/blender/blenkernel/intern/volume_grid.cc +++ b/source/blender/blenkernel/intern/volume_grid.cc @@ -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(matrix_openvdb)); + grid.transform_for_write() = BKE_volume_transform_to_openvdb(matrix); #else UNUSED_VARS(grid, matrix); #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index bbd21b3eb8c..5d6f805f76f 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -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); diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 45140c6fb47..c8ed3b0b8be 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -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 diff --git a/source/blender/nodes/geometry/nodes/node_geo_grid_info.cc b/source/blender/nodes/geometry/nodes/node_geo_grid_info.cc new file mode 100644 index 00000000000..89301ed5ccc --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_grid_info.cc @@ -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("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("Grid"); + if (!grid) { + params.set_default_remaining_outputs(); + return; + } + + bke::VolumeTreeAccessToken tree_token; + const std::shared_ptr 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; + using TreeType = typename type_traits::TreeType; + using GridType = openvdb::Grid; + + if constexpr (!std::is_same_v) { + const std::shared_ptr vdb_typed_grid = openvdb::GridBase::grid( + 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