Blender V4.3
node_fn_separate_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
5#include "BLI_math_matrix.hh"
6
9
10#include "node_function_util.hh"
11
13
15{
16 b.is_function_node();
17 b.use_custom_socket_order();
18 b.allow_any_socket_order();
19
20 PanelDeclarationBuilder &column_a = b.add_panel("Column 1").default_closed(true);
21 column_a.add_output<decl::Float>("Column 1 Row 1");
22 column_a.add_output<decl::Float>("Column 1 Row 2");
23 column_a.add_output<decl::Float>("Column 1 Row 3");
24 column_a.add_output<decl::Float>("Column 1 Row 4");
25
26 PanelDeclarationBuilder &column_b = b.add_panel("Column 2").default_closed(true);
27 column_b.add_output<decl::Float>("Column 2 Row 1");
28 column_b.add_output<decl::Float>("Column 2 Row 2");
29 column_b.add_output<decl::Float>("Column 2 Row 3");
30 column_b.add_output<decl::Float>("Column 2 Row 4");
31
32 PanelDeclarationBuilder &column_c = b.add_panel("Column 3").default_closed(true);
33 column_c.add_output<decl::Float>("Column 3 Row 1");
34 column_c.add_output<decl::Float>("Column 3 Row 2");
35 column_c.add_output<decl::Float>("Column 3 Row 3");
36 column_c.add_output<decl::Float>("Column 3 Row 4");
37
38 PanelDeclarationBuilder &column_d = b.add_panel("Column 4").default_closed(true);
39 column_d.add_output<decl::Float>("Column 4 Row 1");
40 column_d.add_output<decl::Float>("Column 4 Row 2");
41 column_d.add_output<decl::Float>("Column 4 Row 3");
42 column_d.add_output<decl::Float>("Column 4 Row 4");
43
44 b.add_input<decl::Matrix>("Matrix");
45}
46
47static void copy_with_stride(const IndexMask &mask,
48 const Span<float> src,
49 const int64_t src_step,
50 const int64_t src_begin,
51 const int64_t dst_step,
52 const int64_t dst_begin,
54{
55 if (dst.is_empty()) {
56 return;
57 }
58 BLI_assert(src_begin < src_step);
59 BLI_assert(dst_begin < dst_step);
60 mask.foreach_index_optimized<int>([&](const int64_t index) {
61 dst[dst_begin + dst_step * index] = src[src_begin + src_step * index];
62 });
63}
64
66 public:
68 {
69 static const mf::Signature signature = []() {
71 mf::SignatureBuilder builder{"Separate Matrix", signature};
72 builder.single_input<float4x4>("Matrix");
73
74 builder.single_output<float>("Column 1 Row 1", mf::ParamFlag::SupportsUnusedOutput);
75 builder.single_output<float>("Column 1 Row 2", mf::ParamFlag::SupportsUnusedOutput);
76 builder.single_output<float>("Column 1 Row 3", mf::ParamFlag::SupportsUnusedOutput);
77 builder.single_output<float>("Column 1 Row 4", mf::ParamFlag::SupportsUnusedOutput);
78
79 builder.single_output<float>("Column 2 Row 1", mf::ParamFlag::SupportsUnusedOutput);
80 builder.single_output<float>("Column 2 Row 2", mf::ParamFlag::SupportsUnusedOutput);
81 builder.single_output<float>("Column 2 Row 3", mf::ParamFlag::SupportsUnusedOutput);
82 builder.single_output<float>("Column 2 Row 4", mf::ParamFlag::SupportsUnusedOutput);
83
84 builder.single_output<float>("Column 3 Row 1", mf::ParamFlag::SupportsUnusedOutput);
85 builder.single_output<float>("Column 3 Row 2", mf::ParamFlag::SupportsUnusedOutput);
86 builder.single_output<float>("Column 3 Row 3", mf::ParamFlag::SupportsUnusedOutput);
87 builder.single_output<float>("Column 3 Row 4", mf::ParamFlag::SupportsUnusedOutput);
88
89 builder.single_output<float>("Column 4 Row 1", mf::ParamFlag::SupportsUnusedOutput);
90 builder.single_output<float>("Column 4 Row 2", mf::ParamFlag::SupportsUnusedOutput);
91 builder.single_output<float>("Column 4 Row 3", mf::ParamFlag::SupportsUnusedOutput);
92 builder.single_output<float>("Column 4 Row 4", mf::ParamFlag::SupportsUnusedOutput);
93 return signature;
94 }();
95 this->set_signature(&signature);
96 }
97
98 void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
99 {
100 const VArray<float4x4> matrices = params.readonly_single_input<float4x4>(0, "Matrix");
101
102 MutableSpan<float> column_1_row_1 = params.uninitialized_single_output_if_required<float>(
103 1, "Column 1 Row 1");
104 MutableSpan<float> column_1_row_2 = params.uninitialized_single_output_if_required<float>(
105 2, "Column 1 Row 2");
106 MutableSpan<float> column_1_row_3 = params.uninitialized_single_output_if_required<float>(
107 3, "Column 1 Row 3");
108 MutableSpan<float> column_1_row_4 = params.uninitialized_single_output_if_required<float>(
109 4, "Column 1 Row 4");
110
111 MutableSpan<float> column_2_row_1 = params.uninitialized_single_output_if_required<float>(
112 5, "Column 2 Row 1");
113 MutableSpan<float> column_2_row_2 = params.uninitialized_single_output_if_required<float>(
114 6, "Column 2 Row 2");
115 MutableSpan<float> column_2_row_3 = params.uninitialized_single_output_if_required<float>(
116 7, "Column 2 Row 3");
117 MutableSpan<float> column_2_row_4 = params.uninitialized_single_output_if_required<float>(
118 8, "Column 2 Row 4");
119
120 MutableSpan<float> column_3_row_1 = params.uninitialized_single_output_if_required<float>(
121 9, "Column 3 Row 1");
122 MutableSpan<float> column_3_row_2 = params.uninitialized_single_output_if_required<float>(
123 10, "Column 3 Row 2");
124 MutableSpan<float> column_3_row_3 = params.uninitialized_single_output_if_required<float>(
125 11, "Column 3 Row 3");
126 MutableSpan<float> column_3_row_4 = params.uninitialized_single_output_if_required<float>(
127 12, "Column 3 Row 4");
128
129 MutableSpan<float> column_4_row_1 = params.uninitialized_single_output_if_required<float>(
130 13, "Column 4 Row 1");
131 MutableSpan<float> column_4_row_2 = params.uninitialized_single_output_if_required<float>(
132 14, "Column 4 Row 2");
133 MutableSpan<float> column_4_row_3 = params.uninitialized_single_output_if_required<float>(
134 15, "Column 4 Row 3");
135 MutableSpan<float> column_4_row_4 = params.uninitialized_single_output_if_required<float>(
136 16, "Column 4 Row 4");
137
138 if (const std::optional<float4x4> single = matrices.get_if_single()) {
139 const float4x4 matrix = *single;
140 column_1_row_1.fill(matrix[0][0]);
141 column_1_row_2.fill(matrix[0][1]);
142 column_1_row_3.fill(matrix[0][2]);
143 column_1_row_4.fill(matrix[0][3]);
144
145 column_2_row_1.fill(matrix[1][0]);
146 column_2_row_2.fill(matrix[1][1]);
147 column_2_row_3.fill(matrix[1][2]);
148 column_2_row_4.fill(matrix[1][3]);
149
150 column_3_row_1.fill(matrix[2][0]);
151 column_3_row_2.fill(matrix[2][1]);
152 column_3_row_3.fill(matrix[2][2]);
153 column_3_row_4.fill(matrix[2][3]);
154
155 column_4_row_1.fill(matrix[3][0]);
156 column_4_row_2.fill(matrix[3][1]);
157 column_4_row_3.fill(matrix[3][2]);
158 column_4_row_4.fill(matrix[3][3]);
159 return;
160 }
161
162 const VArraySpan<float4x4> span_matrices(matrices);
163 const Span<float> components = span_matrices.cast<float>();
164
165 copy_with_stride(mask, components, 16, 0, 1, 0, column_1_row_1);
166 copy_with_stride(mask, components, 16, 1, 1, 0, column_1_row_2);
167 copy_with_stride(mask, components, 16, 2, 1, 0, column_1_row_3);
168 copy_with_stride(mask, components, 16, 3, 1, 0, column_1_row_4);
169
170 copy_with_stride(mask, components, 16, 4, 1, 0, column_2_row_1);
171 copy_with_stride(mask, components, 16, 5, 1, 0, column_2_row_2);
172 copy_with_stride(mask, components, 16, 6, 1, 0, column_2_row_3);
173 copy_with_stride(mask, components, 16, 7, 1, 0, column_2_row_4);
174
175 copy_with_stride(mask, components, 16, 8, 1, 0, column_3_row_1);
176 copy_with_stride(mask, components, 16, 9, 1, 0, column_3_row_2);
177 copy_with_stride(mask, components, 16, 10, 1, 0, column_3_row_3);
178 copy_with_stride(mask, components, 16, 11, 1, 0, column_3_row_4);
179
180 copy_with_stride(mask, components, 16, 12, 1, 0, column_4_row_1);
181 copy_with_stride(mask, components, 16, 13, 1, 0, column_4_row_2);
182 copy_with_stride(mask, components, 16, 14, 1, 0, column_4_row_3);
183 copy_with_stride(mask, components, 16, 15, 1, 0, column_4_row_4);
184 }
185};
186
188{
189 const static SeparateMatrixFunction fn;
190 builder.set_matching_fn(fn);
191}
192
194{
195 using namespace value_elem;
196 const MatrixElem matrix_elem = params.get_input_elem<MatrixElem>("Matrix");
197 std::array<std::array<FloatElem, 4>, 4> output_elems;
198
199 output_elems[3][0] = matrix_elem.translation.x;
200 output_elems[3][1] = matrix_elem.translation.y;
201 output_elems[3][2] = matrix_elem.translation.z;
202
203 if (matrix_elem.rotation || matrix_elem.scale) {
204 for (const int col : IndexRange(3)) {
205 for (const int row : IndexRange(3)) {
206 output_elems[col][row] = FloatElem::all();
207 }
208 }
209 }
210
211 if (matrix_elem.any_non_transform) {
212 for (const int col : IndexRange(4)) {
213 output_elems[col][3] = FloatElem::all();
214 }
215 }
216
217 for (const int col : IndexRange(4)) {
218 for (const int row : IndexRange(4)) {
219 const bNodeSocket &socket = params.node.output_socket(col * 4 + row);
220 params.set_output_elem(socket.identifier, output_elems[col][row]);
221 }
222 }
223}
224
226{
227 using namespace value_elem;
228
229 std::array<std::array<FloatElem, 4>, 4> output_elems;
230 for (const int col : IndexRange(4)) {
231 for (const int row : IndexRange(4)) {
232 const bNodeSocket &socket = params.node.output_socket(col * 4 + row);
233 output_elems[col][row] = params.get_output_elem<FloatElem>(socket.identifier);
234 }
235 }
236
237 MatrixElem matrix_elem;
238 matrix_elem.translation.x = output_elems[3][0];
239 matrix_elem.translation.y = output_elems[3][1];
240 matrix_elem.translation.z = output_elems[3][2];
241
242 bool any_inner_3x3 = false;
243 for (const int col : IndexRange(3)) {
244 for (const int row : IndexRange(3)) {
245 any_inner_3x3 |= output_elems[col][row];
246 }
247 }
248
249 if (any_inner_3x3) {
250 matrix_elem.rotation = RotationElem::all();
251 matrix_elem.scale = VectorElem::all();
252 }
253
254 const bool any_non_transform = output_elems[0][3] || output_elems[1][3] || output_elems[2][3] ||
255 output_elems[3][3];
256 if (any_non_transform) {
257 matrix_elem.any_non_transform = FloatElem::all();
258 }
259
260 params.set_input_elem("Matrix", matrix_elem);
261}
262
264{
265 float4x4 matrix;
266 for (const int col : IndexRange(4)) {
267 for (const int row : IndexRange(4)) {
268 const bNodeSocket &socket = params.node.output_socket(col * 4 + row);
269 matrix[col][row] = params.get_output<float>(socket.identifier);
270 }
271 }
272 params.set_input("Matrix", matrix);
273}
274
275static void node_register()
276{
277 static blender::bke::bNodeType ntype;
278 fn_node_type_base(&ntype, FN_NODE_SEPARATE_MATRIX, "Separate Matrix", NODE_CLASS_CONVERTER);
279 ntype.declare = node_declare;
285}
287
288} // namespace blender::nodes::node_fn_separate_matrix_cc
#define NODE_CLASS_CONVERTER
Definition BKE_node.hh:410
#define BLI_assert(a)
Definition BLI_assert.h:50
#define NOD_REGISTER_NODE(REGISTER_FUNC)
constexpr bool is_empty() const
Definition BLI_span.hh:510
Span< NewT > constexpr cast() const
Definition BLI_span.hh:419
std::optional< T > get_if_single() const
void set_signature(const Signature *signature)
void set_matching_fn(const mf::MultiFunction *fn)
DeclType::Builder & add_output(StringRef name, StringRef identifier="")
void call(const IndexMask &mask, mf::Params params, mf::Context) const override
local_group_size(16, 16) .push_constant(Type b
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
static void node_eval_inverse_elem(value_elem::InverseElemEvalParams &params)
static void node_eval_elem(value_elem::ElemEvalParams &params)
static void node_declare(NodeDeclarationBuilder &b)
static void copy_with_stride(const IndexMask &mask, const Span< 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_eval_inverse(inverse_eval::InverseEvalParams &params)
void fn_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
__int64 int64_t
Definition stdint.h:89
char identifier[64]
Defines a node type.
Definition BKE_node.hh:218
NodeInverseElemEvalFunction eval_inverse_elem
Definition BKE_node.hh:378
NodeInverseEvalFunction eval_inverse
Definition BKE_node.hh:385
NodeElemEvalFunction eval_elem
Definition BKE_node.hh:372
NodeMultiFunctionBuildFunction build_multi_function
Definition BKE_node.hh:336
NodeDeclareFunction declare
Definition BKE_node.hh:347