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