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
This commit is contained in:
Brady Johnston
2025-10-02 19:12:39 +02:00
committed by Hans Goudey
parent a68d39e9d9
commit 4a56973fe7
5 changed files with 122 additions and 0 deletions

View File

@@ -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)

View File

@@ -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");

View File

@@ -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

View File

@@ -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<decl::Bool>("Is Valid")
.description("The new transform is valid and was successfully applied to the grid.");
b.add_input<decl::Matrix>("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<bke::GVolumeGrid>("Grid");
if (!grid) {
params.set_default_remaining_outputs();
return;
}
const float4x4 transform = params.extract_input<float4x4>("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

Binary file not shown.