From 4a56973fe71e00ba62dec99ca29449aaa0a0105d Mon Sep 17 00:00:00 2001 From: Brady Johnston Date: Thu, 2 Oct 2025 19:12:39 +0200 Subject: [PATCH] Geometry Nodes: Set Grid Transform Explicitly set the transform of a grid. The new transform can fail to be applied if the input transform isn't invertible or for some extremes of scaling (0 or combinations of negative and positive) and numerical errors with `openvdb`. If a transform is not applied an error is raised and the `Is Valid` returns false. Pull Request: https://projects.blender.org/blender/blender/pulls/146824 --- .../startup/bl_ui/node_add_menu_geometry.py | 1 + .../blender/makesrna/intern/rna_nodetree.cc | 1 + source/blender/nodes/geometry/CMakeLists.txt | 1 + .../nodes/node_geo_set_grid_transform.cc | 116 ++++++++++++++++++ .../geometry/set_grid_transform.blend | 3 + 5 files changed, 122 insertions(+) create mode 100644 source/blender/nodes/geometry/nodes/node_geo_set_grid_transform.cc create mode 100644 tests/files/modeling/geometry_nodes/geometry/set_grid_transform.blend diff --git a/scripts/startup/bl_ui/node_add_menu_geometry.py b/scripts/startup/bl_ui/node_add_menu_geometry.py index 4f675b16591..7e0d618ec8c 100644 --- a/scripts/startup/bl_ui/node_add_menu_geometry.py +++ b/scripts/startup/bl_ui/node_add_menu_geometry.py @@ -911,6 +911,7 @@ class NODE_MT_gn_volume_read_base(node_add_menu.NodeMenu): layout = self.layout self.node_operator(layout, "GeometryNodeGetNamedGrid") self.node_operator(layout, "GeometryNodeGridInfo") + self.node_operator(layout, "GeometryNodeSetGridTransform") self.draw_assets_for_catalog(layout, self.menu_path) diff --git a/source/blender/makesrna/intern/rna_nodetree.cc b/source/blender/makesrna/intern/rna_nodetree.cc index 057875222cd..d94cb85112d 100644 --- a/source/blender/makesrna/intern/rna_nodetree.cc +++ b/source/blender/makesrna/intern/rna_nodetree.cc @@ -10282,6 +10282,7 @@ static void rna_def_nodes(BlenderRNA *brna) define("GeometryNode", "GeometryNodeSetGreasePencilColor"); define("GeometryNode", "GeometryNodeSetGreasePencilDepth"); define("GeometryNode", "GeometryNodeSetGreasePencilSoftness"); + define("GeometryNode", "GeometryNodeSetGridTransform"); define("GeometryNode", "GeometryNodeSetID"); define("GeometryNode", "GeometryNodeSetInstanceTransform"); define("GeometryNode", "GeometryNodeSetMaterial"); diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt index 40c1652adac..026294cd523 100644 --- a/source/blender/nodes/geometry/CMakeLists.txt +++ b/source/blender/nodes/geometry/CMakeLists.txt @@ -219,6 +219,7 @@ set(SRC nodes/node_geo_set_grease_pencil_color.cc nodes/node_geo_set_grease_pencil_depth_mode.cc nodes/node_geo_set_grease_pencil_softness.cc + nodes/node_geo_set_grid_transform.cc nodes/node_geo_set_id.cc nodes/node_geo_set_instance_transform.cc nodes/node_geo_set_material.cc diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_grid_transform.cc b/source/blender/nodes/geometry/nodes/node_geo_set_grid_transform.cc new file mode 100644 index 00000000000..6547d4f0118 --- /dev/null +++ b/source/blender/nodes/geometry/nodes/node_geo_set_grid_transform.cc @@ -0,0 +1,116 @@ +/* SPDX-FileCopyrightText: 2025 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_layout.hh" +#include "UI_resources.hh" + +#include "RNA_enum_types.hh" + +namespace blender::nodes::node_geo_set_grid_transform { + +static void node_declare(NodeDeclarationBuilder &b) +{ + const bNode *node = b.node_or_null(); + if (!node) { + return; + } + + const eNodeSocketDatatype data_type = eNodeSocketDatatype(node->custom1); + + b.use_custom_socket_order(); + b.allow_any_socket_order(); + b.add_default_layout(); + b.add_input(data_type, "Grid") + .hide_value() + .structure_type(StructureType::Grid) + .is_default_link_socket(); + b.add_output(data_type, "Grid").structure_type(StructureType::Grid).align_with_previous(); + b.add_output("Is Valid") + .description("The new transform is valid and was successfully applied to the grid."); + b.add_input("Transform") + .description("The new transform from grid index space to object space."); +} + +static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr) +{ + layout->use_property_split_set(true); + layout->use_property_decorate_set(false); + layout->prop(ptr, "data_type", UI_ITEM_NONE, "", ICON_NONE); +} + +static void node_geo_exec(GeoNodeExecParams params) +{ +#ifdef WITH_OPENVDB + bke::GVolumeGrid grid = params.extract_input("Grid"); + if (!grid) { + params.set_default_remaining_outputs(); + return; + } + + const float4x4 transform = params.extract_input("Transform"); + + try { + bke::VolumeGridData &grid_data = grid.get_for_write(); + bke::volume_grid::set_transform_matrix(grid_data, transform); + params.set_output("Is Valid", true); + } + catch (const openvdb::ArithmeticError & /*error*/) { + params.error_message_add(NodeWarningType::Error, + TIP_("Failed to set the new grid transform.")); + params.set_output("Is Valid", false); + } + + params.set_output("Grid", std::move(grid)); +#else + node_geo_exec_with_missing_openvdb(params); +#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", + "Node socket data type", + 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, "GeometryNodeSetGridTransform"); + ntype.ui_name = "Set Grid Transform"; + ntype.ui_description = "Set the transform for the grid from index space into object space."; + ntype.nclass = NODE_CLASS_GEOMETRY; + 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_set_grid_transform diff --git a/tests/files/modeling/geometry_nodes/geometry/set_grid_transform.blend b/tests/files/modeling/geometry_nodes/geometry/set_grid_transform.blend new file mode 100644 index 00000000000..4fa60efd49f --- /dev/null +++ b/tests/files/modeling/geometry_nodes/geometry/set_grid_transform.blend @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f148116ab28409a16cb8ec4224996bfd6ab8ff49998679f99be0fbd6780aee2e +size 1663183