Blender V4.5
node_geo_transform_geometry.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_math_matrix.hh"
7
8#include "NOD_rna_define.hh"
9
10#include "GEO_transform.hh"
11
12#include "UI_interface.hh"
13#include "UI_resources.hh"
14
15#include "node_geometry_util.hh"
16
18
20{
21 b.use_custom_socket_order();
22 b.allow_any_socket_order();
23 b.add_default_layout();
24 auto enable_components = [](bNode &node) { node.custom1 = GEO_NODE_TRANSFORM_MODE_COMPONENTS; };
25 auto enable_matrix = [](bNode &node) { node.custom1 = GEO_NODE_TRANSFORM_MODE_MATRIX; };
26
27 b.add_input<decl::Geometry>("Geometry");
28 b.add_output<decl::Geometry>("Geometry").propagate_all().align_with_previous();
29 auto &translation = b.add_input<decl::Vector>("Translation")
30 .subtype(PROP_TRANSLATION)
31 .make_available(enable_components);
32 auto &rotation = b.add_input<decl::Rotation>("Rotation").make_available(enable_components);
33 auto &scale =
34 b.add_input<decl::Vector>("Scale").default_value({1, 1, 1}).subtype(PROP_XYZ).make_available(
35 enable_components);
36 auto &transform = b.add_input<decl::Matrix>("Transform").make_available(enable_matrix);
37
38 const bNode *node = b.node_or_null();
39 if (node != nullptr) {
40 const bool use_matrix = node->custom1 == GEO_NODE_TRANSFORM_MODE_MATRIX;
41
42 translation.available(!use_matrix);
43 rotation.available(!use_matrix);
44 scale.available(!use_matrix);
45 transform.available(use_matrix);
46 }
47}
48
49static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
50{
51 uiLayoutSetPropSep(layout, true);
52 uiLayoutSetPropDecorate(layout, false);
53 layout->prop(ptr, "mode", UI_ITEM_NONE, "", ICON_NONE);
54}
55
56static bool use_translate(const math::Quaternion &rotation, const float3 scale)
57{
58 if (math::angle_of(rotation).radian() > 1e-7f) {
59 return false;
60 }
61 if (compare_ff(scale.x, 1.0f, 1e-9f) != 1 || compare_ff(scale.y, 1.0f, 1e-9f) != 1 ||
62 compare_ff(scale.z, 1.0f, 1e-9f) != 1)
63 {
64 return false;
65 }
66 return true;
67}
68
71{
72 if (errors.bad_volume_transform) {
73 params.error_message_add(NodeWarningType::Warning,
74 TIP_("Invalid transformation for volume grids"));
75 }
76 else if (errors.volume_too_small) {
77 params.error_message_add(NodeWarningType::Warning,
78 TIP_("Volume scale is lower than permitted by OpenVDB"));
79 }
80}
81
83{
84 const bool use_matrix = params.node().custom1 == GEO_NODE_TRANSFORM_MODE_MATRIX;
85 GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
86
87 if (use_matrix) {
88 const float4x4 transform = params.extract_input<float4x4>("Transform");
89 if (auto errors = geometry::transform_geometry(geometry_set, transform)) {
90 report_errors(params, *errors);
91 }
92 }
93 else {
94 const float3 translation = params.extract_input<float3>("Translation");
95 const math::Quaternion rotation = params.extract_input<math::Quaternion>("Rotation");
96 const float3 scale = params.extract_input<float3>("Scale");
97
98 /* Use only translation if rotation and scale don't apply. */
99 if (use_translate(rotation, scale)) {
100 geometry::translate_geometry(geometry_set, translation);
101 }
102 else {
103 if (auto errors = geometry::transform_geometry(
104 geometry_set, math::from_loc_rot_scale<float4x4>(translation, rotation, scale)))
105 {
106 report_errors(params, *errors);
107 }
108 }
109 }
110
111 params.set_output("Geometry", std::move(geometry_set));
112}
113
114static void node_rna(StructRNA *srna)
115{
116 static EnumPropertyItem mode_items[] = {
118 "COMPONENTS",
119 0,
120 "Components",
121 "Provide separate location, rotation and scale"},
122 {GEO_NODE_TRANSFORM_MODE_MATRIX, "MATRIX", 0, "Matrix", "Use a transformation matrix"},
123 {0, nullptr, 0, nullptr, nullptr},
124 };
125
127 "mode",
128 "Mode",
129 "How the transformation is specified",
130 mode_items,
132}
133
134static void register_node()
135{
136 static blender::bke::bNodeType ntype;
137 geo_node_type_base(&ntype, "GeometryNodeTransform", GEO_NODE_TRANSFORM_GEOMETRY);
138 ntype.ui_name = "Transform Geometry";
139 ntype.ui_description = "Translate, rotate or scale the geometry";
140 ntype.enum_name_legacy = "TRANSFORM_GEOMETRY";
142 ntype.declare = node_declare;
146
147 node_rna(ntype.rna_ext.srna);
148}
150
151} // namespace blender::nodes::node_geo_transform_geometry_cc
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:447
#define GEO_NODE_TRANSFORM_GEOMETRY
MINLINE int compare_ff(float a, float b, float max_diff)
#define TIP_(msgid)
@ GEO_NODE_TRANSFORM_MODE_MATRIX
@ GEO_NODE_TRANSFORM_MODE_COMPONENTS
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
@ PROP_XYZ
Definition RNA_types.hh:257
@ PROP_TRANSLATION
Definition RNA_types.hh:249
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void make_available(bNode &node) const
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
void translate_geometry(bke::GeometrySet &geometry, const float3 translation)
std::optional< TransformGeometryErrors > transform_geometry(bke::GeometrySet &geometry, const float4x4 &transform)
QuaternionBase< float > Quaternion
AngleRadianBase< T > angle_of(const QuaternionBase< T > &q)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
static bool use_translate(const math::Quaternion &rotation, const float3 scale)
static void node_declare(NodeDeclarationBuilder &b)
static void report_errors(GeoNodeExecParams &params, const geometry::TransformGeometryErrors &errors)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
StructRNA * srna
Definition RNA_types.hh:909
int16_t custom1
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:347
const char * enum_name_legacy
Definition BKE_node.hh:235
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:355
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
PointerRNA * ptr
Definition wm_files.cc:4227