Blender V5.0
node_fn_combine_matrix.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
7
9
11
13{
14 b.is_function_node();
15 b.use_custom_socket_order();
16
17 b.add_output<decl::Matrix>("Matrix");
18
19 PanelDeclarationBuilder &column_a = b.add_panel("Column 1").default_closed(true);
20 column_a.add_input<decl::Float>("Column 1 Row 1").default_value(1.0f);
21 column_a.add_input<decl::Float>("Column 1 Row 2");
22 column_a.add_input<decl::Float>("Column 1 Row 3");
23 column_a.add_input<decl::Float>("Column 1 Row 4");
24
25 PanelDeclarationBuilder &column_b = b.add_panel("Column 2").default_closed(true);
26 column_b.add_input<decl::Float>("Column 2 Row 1");
27 column_b.add_input<decl::Float>("Column 2 Row 2").default_value(1.0f);
28 column_b.add_input<decl::Float>("Column 2 Row 3");
29 column_b.add_input<decl::Float>("Column 2 Row 4");
30
31 PanelDeclarationBuilder &column_c = b.add_panel("Column 3").default_closed(true);
32 column_c.add_input<decl::Float>("Column 3 Row 1");
33 column_c.add_input<decl::Float>("Column 3 Row 2");
34 column_c.add_input<decl::Float>("Column 3 Row 3").default_value(1.0f);
35 column_c.add_input<decl::Float>("Column 3 Row 4");
36
37 PanelDeclarationBuilder &column_d = b.add_panel("Column 4").default_closed(true);
38 column_d.add_input<decl::Float>("Column 4 Row 1");
39 column_d.add_input<decl::Float>("Column 4 Row 2");
40 column_d.add_input<decl::Float>("Column 4 Row 3");
41 column_d.add_input<decl::Float>("Column 4 Row 4").default_value(1.0f);
42}
43
44static void copy_with_stride(const IndexMask &mask,
45 const VArray<float> &src,
46 const int64_t src_step,
47 const int64_t src_begin,
48 const int64_t dst_step,
49 const int64_t dst_begin,
51{
52 BLI_assert(src_begin < src_step);
53 BLI_assert(dst_begin < dst_step);
54 devirtualize_varray(src, [&](const auto src) {
55 mask.foreach_index_optimized<int>([&](const int64_t index) {
56 dst[dst_begin + dst_step * index] = src[src_begin + src_step * index];
57 });
58 });
59}
60
61class CombineMatrixFunction : public mf::MultiFunction {
62 public:
64 {
65 static const mf::Signature signature = []() {
66 mf::Signature signature;
67 mf::SignatureBuilder builder{"Combine Matrix", signature};
68 builder.single_input<float>("Column 1 Row 1");
69 builder.single_input<float>("Column 1 Row 2");
70 builder.single_input<float>("Column 1 Row 3");
71 builder.single_input<float>("Column 1 Row 4");
72
73 builder.single_input<float>("Column 2 Row 1");
74 builder.single_input<float>("Column 2 Row 2");
75 builder.single_input<float>("Column 2 Row 3");
76 builder.single_input<float>("Column 2 Row 4");
77
78 builder.single_input<float>("Column 3 Row 1");
79 builder.single_input<float>("Column 3 Row 2");
80 builder.single_input<float>("Column 3 Row 3");
81 builder.single_input<float>("Column 3 Row 4");
82
83 builder.single_input<float>("Column 4 Row 1");
84 builder.single_input<float>("Column 4 Row 2");
85 builder.single_input<float>("Column 4 Row 3");
86 builder.single_input<float>("Column 4 Row 4");
87
88 builder.single_output<float4x4>("Matrix");
89 return signature;
90 }();
91 this->set_signature(&signature);
92 }
93
94 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
95 {
96 const VArray<float> &column_1_row_1 = params.readonly_single_input<float>(0, "Column 1 Row 1");
97 const VArray<float> &column_1_row_2 = params.readonly_single_input<float>(1, "Column 1 Row 2");
98 const VArray<float> &column_1_row_3 = params.readonly_single_input<float>(2, "Column 1 Row 3");
99 const VArray<float> &column_1_row_4 = params.readonly_single_input<float>(3, "Column 1 Row 4");
100
101 const VArray<float> &column_2_row_1 = params.readonly_single_input<float>(4, "Column 2 Row 1");
102 const VArray<float> &column_2_row_2 = params.readonly_single_input<float>(5, "Column 2 Row 2");
103 const VArray<float> &column_2_row_3 = params.readonly_single_input<float>(6, "Column 2 Row 3");
104 const VArray<float> &column_2_row_4 = params.readonly_single_input<float>(7, "Column 2 Row 4");
105
106 const VArray<float> &column_3_row_1 = params.readonly_single_input<float>(8, "Column 3 Row 1");
107 const VArray<float> &column_3_row_2 = params.readonly_single_input<float>(9, "Column 3 Row 2");
108 const VArray<float> &column_3_row_3 = params.readonly_single_input<float>(10,
109 "Column 3 Row 3");
110 const VArray<float> &column_3_row_4 = params.readonly_single_input<float>(11,
111 "Column 3 Row 4");
112
113 const VArray<float> &column_4_row_1 = params.readonly_single_input<float>(12,
114 "Column 4 Row 1");
115 const VArray<float> &column_4_row_2 = params.readonly_single_input<float>(13,
116 "Column 4 Row 2");
117 const VArray<float> &column_4_row_3 = params.readonly_single_input<float>(14,
118 "Column 4 Row 3");
119 const VArray<float> &column_4_row_4 = params.readonly_single_input<float>(15,
120 "Column 4 Row 4");
121
122 MutableSpan<float4x4> matrices = params.uninitialized_single_output<float4x4>(16, "Matrix");
123 MutableSpan<float> components = matrices.cast<float>();
124
125 copy_with_stride(mask, column_1_row_1, 1, 0, 16, 0, components);
126 copy_with_stride(mask, column_1_row_2, 1, 0, 16, 1, components);
127 copy_with_stride(mask, column_1_row_3, 1, 0, 16, 2, components);
128 copy_with_stride(mask, column_1_row_4, 1, 0, 16, 3, components);
129
130 copy_with_stride(mask, column_2_row_1, 1, 0, 16, 4, components);
131 copy_with_stride(mask, column_2_row_2, 1, 0, 16, 5, components);
132 copy_with_stride(mask, column_2_row_3, 1, 0, 16, 6, components);
133 copy_with_stride(mask, column_2_row_4, 1, 0, 16, 7, components);
134
135 copy_with_stride(mask, column_3_row_1, 1, 0, 16, 8, components);
136 copy_with_stride(mask, column_3_row_2, 1, 0, 16, 9, components);
137 copy_with_stride(mask, column_3_row_3, 1, 0, 16, 10, components);
138 copy_with_stride(mask, column_3_row_4, 1, 0, 16, 11, components);
139
140 copy_with_stride(mask, column_4_row_1, 1, 0, 16, 12, components);
141 copy_with_stride(mask, column_4_row_2, 1, 0, 16, 13, components);
142 copy_with_stride(mask, column_4_row_3, 1, 0, 16, 14, components);
143 copy_with_stride(mask, column_4_row_4, 1, 0, 16, 15, components);
144 }
145};
146
148{
149 const static CombineMatrixFunction fn;
150 builder.set_matching_fn(fn);
151}
152
154{
155 using namespace value_elem;
156
157 std::array<std::array<FloatElem, 4>, 4> input_elems;
158 for (const int col : IndexRange(4)) {
159 for (const int row : IndexRange(4)) {
160 const bNodeSocket &socket = params.node.input_socket(col * 4 + row);
161 input_elems[col][row] = params.get_input_elem<FloatElem>(socket.identifier);
162 }
163 }
164
165 MatrixElem matrix_elem;
166 matrix_elem.translation.x = input_elems[3][0];
167 matrix_elem.translation.y = input_elems[3][1];
168 matrix_elem.translation.z = input_elems[3][2];
169
170 bool any_inner_3x3 = false;
171 for (const int col : IndexRange(3)) {
172 for (const int row : IndexRange(3)) {
173 any_inner_3x3 |= input_elems[col][row];
174 }
175 }
176 if (any_inner_3x3) {
177 matrix_elem.rotation = RotationElem::all();
178 matrix_elem.scale = VectorElem::all();
179 }
180
181 const bool any_non_transform = input_elems[0][3] || input_elems[1][3] || input_elems[2][3] ||
182 input_elems[3][3];
183 if (any_non_transform) {
184 matrix_elem.any_non_transform = FloatElem::all();
185 }
186
187 params.set_output_elem("Matrix", matrix_elem);
188}
189
191{
192 using namespace value_elem;
193
194 const MatrixElem matrix_elem = params.get_output_elem<MatrixElem>("Matrix");
195 std::array<std::array<FloatElem, 4>, 4> input_elems;
196
197 input_elems[3][0] = matrix_elem.translation.x;
198 input_elems[3][1] = matrix_elem.translation.y;
199 input_elems[3][2] = matrix_elem.translation.z;
200
201 if (matrix_elem.rotation || matrix_elem.scale) {
202 for (const int col : IndexRange(3)) {
203 for (const int row : IndexRange(3)) {
204 input_elems[col][row] = FloatElem::all();
205 }
206 }
207 }
208
209 if (matrix_elem.any_non_transform) {
210 for (const int col : IndexRange(4)) {
211 input_elems[col][3] = FloatElem::all();
212 }
213 }
214
215 for (const int col : IndexRange(4)) {
216 for (const int row : IndexRange(4)) {
217 const bNodeSocket &socket = params.node.input_socket(col * 4 + row);
218 params.set_input_elem(socket.identifier, input_elems[col][row]);
219 }
220 }
221}
222
224{
225 const float4x4 matrix = params.get_output<float4x4>("Matrix");
226 for (const int col : IndexRange(4)) {
227 for (const int row : IndexRange(4)) {
228 const bNodeSocket &socket = params.node.input_socket(col * 4 + row);
229 params.set_input(socket.identifier, matrix[col][row]);
230 }
231 }
232}
233
234static void node_register()
235{
236 static blender::bke::bNodeType ntype;
237 fn_node_type_base(&ntype, "FunctionNodeCombineMatrix", FN_NODE_COMBINE_MATRIX);
238 ntype.ui_name = "Combine Matrix";
239 ntype.ui_description = "Construct a 4x4 matrix from its individual values";
240 ntype.enum_name_legacy = "COMBINE_MATRIX";
242 ntype.declare = node_declare;
248}
250
251} // namespace blender::nodes::node_fn_combine_matrix_cc
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:453
#define FN_NODE_COMBINE_MATRIX
#define BLI_assert(a)
Definition BLI_assert.h:46
#define NOD_REGISTER_NODE(REGISTER_FUNC)
long long int int64_t
constexpr MutableSpan< NewT > cast() const
Definition BLI_span.hh:749
void set_signature(const Signature *signature)
void set_matching_fn(const mf::MultiFunction *fn)
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
static void copy_with_stride(const IndexMask &mask, const VArray< float > &src, const int64_t src_step, const int64_t src_begin, const int64_t dst_step, const int64_t dst_begin, MutableSpan< float > dst)
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
static void node_eval_inverse_elem(value_elem::InverseElemEvalParams &params)
static void node_declare(NodeDeclarationBuilder &b)
static void node_eval_elem(value_elem::ElemEvalParams &params)
static void node_eval_inverse(inverse_eval::InverseEvalParams &params)
void devirtualize_varray(const VArray< T > &varray, const Func &func, bool enable=true)
MatBase< float, 4, 4 > float4x4
void fn_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
char identifier[64]
Defines a node type.
Definition BKE_node.hh:238
NodeInverseElemEvalFunction eval_inverse_elem
Definition BKE_node.hh:403
NodeInverseEvalFunction eval_inverse
Definition BKE_node.hh:410
std::string ui_description
Definition BKE_node.hh:244
NodeElemEvalFunction eval_elem
Definition BKE_node.hh:397
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:351
const char * enum_name_legacy
Definition BKE_node.hh:247
NodeDeclareFunction declare
Definition BKE_node.hh:362