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:
committed by
Hans Goudey
parent
a68d39e9d9
commit
4a56973fe7
@@ -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)
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
BIN
tests/files/modeling/geometry_nodes/geometry/set_grid_transform.blend
(Stored with Git LFS)
Normal file
BIN
tests/files/modeling/geometry_nodes/geometry/set_grid_transform.blend
(Stored with Git LFS)
Normal file
Binary file not shown.
Reference in New Issue
Block a user