Blender V4.3
node_util.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 NVIDIA Corporation
2 * SPDX-FileCopyrightText: 2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: Apache-2.0 */
5
6#include "hydra/node_util.h"
7#include "util/transform.h"
8
9#include <pxr/base/gf/matrix3d.h>
10#include <pxr/base/gf/matrix3f.h>
11#include <pxr/base/gf/matrix4d.h>
12#include <pxr/base/gf/matrix4f.h>
13#include <pxr/base/gf/vec2f.h>
14#include <pxr/base/gf/vec3f.h>
15#include <pxr/base/vt/array.h>
16#include <pxr/usd/sdf/assetPath.h>
17
19
20namespace {
21
22template<typename DstType> DstType convertToCycles(const VtValue &value)
23{
24 if (value.IsHolding<DstType>()) {
25 return value.UncheckedGet<DstType>();
26 }
27
28 VtValue castedValue = VtValue::Cast<DstType>(value);
29 if (castedValue.IsHolding<DstType>()) {
30 return castedValue.UncheckedGet<DstType>();
31 }
32
33 TF_WARN("Could not convert VtValue to Cycles type");
34 return DstType(0);
35}
36
37template<> float2 convertToCycles<float2>(const VtValue &value)
38{
39 const GfVec2f convertedValue = convertToCycles<GfVec2f>(value);
40 return make_float2(convertedValue[0], convertedValue[1]);
41}
42
43template<> float3 convertToCycles<float3>(const VtValue &value)
44{
45 if (value.IsHolding<GfVec3f>()) {
46 const GfVec3f convertedValue = value.UncheckedGet<GfVec3f>();
47 return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
48 }
49 if (value.IsHolding<GfVec4f>()) {
50 const GfVec4f convertedValue = value.UncheckedGet<GfVec4f>();
51 return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
52 }
53
54 if (value.CanCast<GfVec3f>()) {
55 const GfVec3f convertedValue = VtValue::Cast<GfVec3f>(value).UncheckedGet<GfVec3f>();
56 return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
57 }
58 if (value.CanCast<GfVec4f>()) {
59 const GfVec4f convertedValue = VtValue::Cast<GfVec4f>(value).UncheckedGet<GfVec4f>();
60 return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
61 }
62
63 TF_WARN("Could not convert VtValue to float3");
64 return zero_float3();
65}
66
67template<> ustring convertToCycles<ustring>(const VtValue &value)
68{
69 if (value.IsHolding<TfToken>()) {
70 return ustring(value.UncheckedGet<TfToken>().GetString());
71 }
72 if (value.IsHolding<std::string>()) {
73 return ustring(value.UncheckedGet<std::string>());
74 }
75 if (value.IsHolding<SdfAssetPath>()) {
76 const SdfAssetPath &path = value.UncheckedGet<SdfAssetPath>();
77 return ustring(path.GetResolvedPath());
78 }
79
80 if (value.CanCast<TfToken>()) {
81 return convertToCycles<ustring>(VtValue::Cast<TfToken>(value));
82 }
83 if (value.CanCast<std::string>()) {
84 return convertToCycles<ustring>(VtValue::Cast<std::string>(value));
85 }
86 if (value.CanCast<SdfAssetPath>()) {
87 return convertToCycles<ustring>(VtValue::Cast<SdfAssetPath>(value));
88 }
89
90 TF_WARN("Could not convert VtValue to ustring");
91 return ustring();
92}
93
94template<typename Matrix>
96 const typename std::enable_if<Matrix::numRows == 3 && Matrix::numColumns == 3, Matrix>::type
97 &matrix)
98{
99 return make_transform(matrix[0][0],
100 matrix[1][0],
101 matrix[2][0],
102 0,
103 matrix[0][1],
104 matrix[1][1],
105 matrix[2][1],
106 0,
107 matrix[0][2],
108 matrix[1][2],
109 matrix[2][2],
110 0);
111}
112
113template<typename Matrix>
115 const typename std::enable_if<Matrix::numRows == 4 && Matrix::numColumns == 4, Matrix>::type
116 &matrix)
117{
118 return make_transform(matrix[0][0],
119 matrix[1][0],
120 matrix[2][0],
121 matrix[3][0],
122 matrix[0][1],
123 matrix[1][1],
124 matrix[2][1],
125 matrix[3][1],
126 matrix[0][2],
127 matrix[1][2],
128 matrix[2][2],
129 matrix[3][2]);
130}
131
132template<> Transform convertToCycles<Transform>(const VtValue &value)
133{
134 if (value.IsHolding<GfMatrix4f>()) {
135 return convertMatrixToCycles<GfMatrix4f>(value.UncheckedGet<GfMatrix4f>());
136 }
137 if (value.IsHolding<GfMatrix3f>()) {
138 return convertMatrixToCycles<GfMatrix3f>(value.UncheckedGet<GfMatrix3f>());
139 }
140 if (value.IsHolding<GfMatrix4d>()) {
141 return convertMatrixToCycles<GfMatrix4d>(value.UncheckedGet<GfMatrix4d>());
142 }
143 if (value.IsHolding<GfMatrix3d>()) {
144 return convertMatrixToCycles<GfMatrix3d>(value.UncheckedGet<GfMatrix3d>());
145 }
146
147 if (value.CanCast<GfMatrix4f>()) {
148 return convertToCycles<Transform>(VtValue::Cast<GfMatrix4f>(value));
149 }
150 if (value.CanCast<GfMatrix3f>()) {
151 return convertToCycles<Transform>(VtValue::Cast<GfMatrix3f>(value));
152 }
153 if (value.CanCast<GfMatrix4d>()) {
154 return convertToCycles<Transform>(VtValue::Cast<GfMatrix4d>(value));
155 }
156 if (value.CanCast<GfMatrix3d>()) {
157 return convertToCycles<Transform>(VtValue::Cast<GfMatrix3d>(value));
158 }
159
160 TF_WARN("Could not convert VtValue to Transform");
161 return transform_identity();
162}
163
164template<typename DstType, typename SrcType = DstType>
166{
167 static_assert(sizeof(DstType) == sizeof(SrcType),
168 "Size mismatch between VtArray and array base type");
169
170 using SrcArray = VtArray<SrcType>;
171
172 if (value.IsHolding<SrcArray>()) {
173 const auto &valueData = value.UncheckedGet<SrcArray>();
174 array<DstType> cyclesArray;
175 cyclesArray.resize(valueData.size());
176 std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
177 return cyclesArray;
178 }
179
180 if (value.CanCast<SrcArray>()) {
181 VtValue castedValue = VtValue::Cast<SrcArray>(value);
182 const auto &valueData = castedValue.UncheckedGet<SrcArray>();
183 array<DstType> cyclesArray;
184 cyclesArray.resize(valueData.size());
185 std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
186 return cyclesArray;
187 }
188
189 return array<DstType>();
190}
191
192template<> array<float3> convertToCyclesArray<float3, GfVec3f>(const VtValue &value)
193{
194 if (value.IsHolding<VtVec3fArray>()) {
195 const auto &valueData = value.UncheckedGet<VtVec3fArray>();
196 array<float3> cyclesArray;
197 cyclesArray.reserve(valueData.size());
198 for (const GfVec3f &vec : valueData) {
199 cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
200 }
201 return cyclesArray;
202 }
203 if (value.IsHolding<VtVec4fArray>()) {
204 const auto &valueData = value.UncheckedGet<VtVec4fArray>();
205 array<float3> cyclesArray;
206 cyclesArray.reserve(valueData.size());
207 for (const GfVec4f &vec : valueData) {
208 cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
209 }
210 return cyclesArray;
211 }
212
213 if (value.CanCast<VtVec3fArray>()) {
214 return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec3fArray>(value));
215 }
216 if (value.CanCast<VtVec4fArray>()) {
217 return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec4fArray>(value));
218 }
219
220 return array<float3>();
221}
222
223template<> array<ustring> convertToCyclesArray<ustring, void>(const VtValue &value)
224{
225 using SdfPathArray = VtArray<SdfAssetPath>;
226
227 if (value.IsHolding<VtStringArray>()) {
228 const auto &valueData = value.UncheckedGet<VtStringArray>();
229 array<ustring> cyclesArray;
230 cyclesArray.reserve(valueData.size());
231 for (const auto &element : valueData) {
232 cyclesArray.push_back_reserved(ustring(element));
233 }
234 return cyclesArray;
235 }
236 if (value.IsHolding<VtTokenArray>()) {
237 const auto &valueData = value.UncheckedGet<VtTokenArray>();
238 array<ustring> cyclesArray;
239 cyclesArray.reserve(valueData.size());
240 for (const auto &element : valueData) {
241 cyclesArray.push_back_reserved(ustring(element.GetString()));
242 }
243 return cyclesArray;
244 }
245 if (value.IsHolding<SdfPathArray>()) {
246 const auto &valueData = value.UncheckedGet<SdfPathArray>();
247 array<ustring> cyclesArray;
248 cyclesArray.reserve(valueData.size());
249 for (const auto &element : valueData) {
250 cyclesArray.push_back_reserved(ustring(element.GetResolvedPath()));
251 }
252 return cyclesArray;
253 }
254
255 if (value.CanCast<VtStringArray>()) {
256 return convertToCyclesArray<ustring, void>(VtValue::Cast<VtStringArray>(value));
257 }
258 if (value.CanCast<VtTokenArray>()) {
259 return convertToCyclesArray<ustring, void>(VtValue::Cast<VtTokenArray>(value));
260 }
261 if (value.CanCast<SdfPathArray>()) {
262 return convertToCyclesArray<ustring, void>(VtValue::Cast<SdfPathArray>(value));
263 }
264
265 TF_WARN("Could not convert VtValue to array<ustring>");
266 return array<ustring>();
267}
268
269template<typename MatrixArray> array<Transform> convertToCyclesTransformArray(const VtValue &value)
270{
271 assert(value.IsHolding<MatrixArray>());
272
273 const auto &valueData = value.UncheckedGet<MatrixArray>();
274 array<Transform> cyclesArray;
275 cyclesArray.reserve(valueData.size());
276 for (const auto &element : valueData) {
277 cyclesArray.push_back_reserved(
278 convertMatrixToCycles<typename MatrixArray::value_type>(element));
279 }
280 return cyclesArray;
281}
282
283template<> array<Transform> convertToCyclesArray<Transform, void>(const VtValue &value)
284{
285 if (value.IsHolding<VtMatrix4fArray>()) {
286 return convertToCyclesTransformArray<VtMatrix4fArray>(value);
287 }
288 if (value.IsHolding<VtMatrix3fArray>()) {
289 return convertToCyclesTransformArray<VtMatrix3fArray>(value);
290 }
291 if (value.IsHolding<VtMatrix4dArray>()) {
292 return convertToCyclesTransformArray<VtMatrix4dArray>(value);
293 }
294 if (value.IsHolding<VtMatrix3dArray>()) {
295 return convertToCyclesTransformArray<VtMatrix3dArray>(value);
296 }
297
298 if (value.CanCast<VtMatrix4fArray>()) {
299 return convertToCyclesTransformArray<VtMatrix4fArray>(VtValue::Cast<VtMatrix4fArray>(value));
300 }
301 if (value.CanCast<VtMatrix3fArray>()) {
302 return convertToCyclesTransformArray<VtMatrix3fArray>(VtValue::Cast<VtMatrix3fArray>(value));
303 }
304 if (value.CanCast<VtMatrix4dArray>()) {
305 return convertToCyclesTransformArray<VtMatrix4dArray>(VtValue::Cast<VtMatrix4dArray>(value));
306 }
307 if (value.CanCast<VtMatrix3dArray>()) {
308 return convertToCyclesTransformArray<VtMatrix3dArray>(VtValue::Cast<VtMatrix3dArray>(value));
309 }
310
311 TF_WARN("Could not convert VtValue to array<Transform>");
312 return array<Transform>();
313}
314
315template<typename SrcType> VtValue convertFromCycles(const SrcType &value)
316{
317 return VtValue(value);
318}
319
320template<> VtValue convertFromCycles<float2>(const float2 &value)
321{
322 const GfVec2f convertedValue(value.x, value.y);
323 return VtValue(convertedValue);
324}
325
326template<> VtValue convertFromCycles<float3>(const float3 &value)
327{
328 const GfVec3f convertedValue(value.x, value.y, value.z);
329 return VtValue(convertedValue);
330}
331
332template<> VtValue convertFromCycles<ustring>(const ustring &value)
333{
334 return VtValue(value.string());
335}
336
337GfMatrix4f convertMatrixFromCycles(const Transform &matrix)
338{
339 return GfMatrix4f(matrix[0][0],
340 matrix[1][0],
341 matrix[2][0],
342 0.0f,
343 matrix[0][1],
344 matrix[1][1],
345 matrix[2][1],
346 0.0f,
347 matrix[0][2],
348 matrix[1][2],
349 matrix[2][2],
350 0.0f,
351 0.0f,
352 0.0f,
353 0.0f,
354 1.0f);
355}
356
357template<> VtValue convertFromCycles<Transform>(const Transform &value)
358{
359 return VtValue(convertMatrixFromCycles(value));
360}
361
362template<typename SrcType, typename DstType = SrcType>
364{
365 static_assert(sizeof(DstType) == sizeof(SrcType),
366 "Size mismatch between VtArray and array base type");
367
368 VtArray<DstType> convertedValue;
369 convertedValue.resize(value.size());
370 std::memcpy(convertedValue.data(), value.data(), value.size() * sizeof(SrcType));
371 return VtValue(convertedValue);
372}
373
374template<> VtValue convertFromCyclesArray<float2, GfVec2f>(const array<float2> &value)
375{
376 VtVec2fArray convertedValue;
377 convertedValue.reserve(value.size());
378 for (const auto &element : value) {
379 convertedValue.push_back(GfVec2f(element.x, element.y));
380 }
381 return VtValue(convertedValue);
382}
383
384template<> VtValue convertFromCyclesArray<float3, GfVec3f>(const array<float3> &value)
385{
386 VtVec3fArray convertedValue;
387 convertedValue.reserve(value.size());
388 for (const auto &element : value) {
389 convertedValue.push_back(GfVec3f(element.x, element.y, element.z));
390 }
391 return VtValue(convertedValue);
392}
393
394template<> VtValue convertFromCyclesArray<ustring, void>(const array<ustring> &value)
395{
396 VtStringArray convertedValue;
397 convertedValue.reserve(value.size());
398 for (const auto &element : value) {
399 convertedValue.push_back(element.string());
400 }
401 return VtValue(convertedValue);
402}
403
404template<> VtValue convertFromCyclesArray<Transform, void>(const array<Transform> &value)
405{
406 VtMatrix4fArray convertedValue;
407 convertedValue.reserve(value.size());
408 for (const auto &element : value) {
409 convertedValue.push_back(convertMatrixFromCycles(element));
410 }
411 return VtValue(convertedValue);
412}
413
414} // namespace
415
416void SetNodeValue(Node *node, const SocketType &socket, const VtValue &value)
417{
418 switch (socket.type) {
419 default:
421 TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
422 break;
423
425 node->set(socket, convertToCycles<bool>(value));
426 break;
428 node->set(socket, convertToCycles<float>(value));
429 break;
430 case SocketType::INT:
431 node->set(socket, convertToCycles<int>(value));
432 break;
433 case SocketType::UINT:
434 node->set(socket, convertToCycles<unsigned int>(value));
435 break;
440 node->set(socket, convertToCycles<float3>(value));
441 break;
443 node->set(socket, convertToCycles<float2>(value));
444 break;
446 // Handled by node connections
447 break;
449 node->set(socket, convertToCycles<ustring>(value));
450 break;
451 case SocketType::ENUM:
452 // Enum's can accept a string or an int
453 if (value.IsHolding<TfToken>() || value.IsHolding<std::string>()) {
454 node->set(socket, convertToCycles<ustring>(value));
455 }
456 else {
457 node->set(socket, convertToCycles<int>(value));
458 }
459 break;
461 node->set(socket, convertToCycles<Transform>(value));
462 break;
463 case SocketType::NODE:
464 // TODO: renderIndex->GetRprim()->cycles_node ?
465 TF_WARN("Unimplemented conversion: SocketType::NODE");
466 break;
467
469 auto cyclesArray = convertToCyclesArray<bool>(value);
470 node->set(socket, cyclesArray);
471 break;
472 }
474 auto cyclesArray = convertToCyclesArray<float>(value);
475 node->set(socket, cyclesArray);
476 break;
477 }
479 auto cyclesArray = convertToCyclesArray<int>(value);
480 node->set(socket, cyclesArray);
481 break;
482 }
487 auto cyclesArray = convertToCyclesArray<float3, GfVec3f>(value);
488 node->set(socket, cyclesArray);
489 break;
490 }
492 auto cyclesArray = convertToCyclesArray<float2, GfVec2f>(value);
493 node->set(socket, cyclesArray);
494 break;
495 }
497 auto cyclesArray = convertToCyclesArray<ustring, void>(value);
498 node->set(socket, cyclesArray);
499 break;
500 }
502 auto cyclesArray = convertToCyclesArray<Transform, void>(value);
503 node->set(socket, cyclesArray);
504 break;
505 }
507 // TODO: renderIndex->GetRprim()->cycles_node ?
508 TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
509 break;
510 }
511 }
512}
513
514VtValue GetNodeValue(const Node *node, const SocketType &socket)
515{
516 switch (socket.type) {
517 default:
519 TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
520 return VtValue();
521
523 return convertFromCycles(node->get_bool(socket));
525 return convertFromCycles(node->get_float(socket));
526 case SocketType::INT:
527 return convertFromCycles(node->get_int(socket));
528 case SocketType::UINT:
529 return convertFromCycles(node->get_uint(socket));
534 return convertFromCycles(node->get_float3(socket));
536 return convertFromCycles(node->get_float2(socket));
538 return VtValue();
540 return convertFromCycles(node->get_string(socket));
541 case SocketType::ENUM:
542 return convertFromCycles(node->get_int(socket));
544 return convertFromCycles(node->get_transform(socket));
545 case SocketType::NODE:
546 TF_WARN("Unimplemented conversion: SocketType::NODE");
547 return VtValue();
548
550 return convertFromCyclesArray(node->get_bool_array(socket));
552 return convertFromCyclesArray(node->get_float_array(socket));
554 return convertFromCyclesArray(node->get_int_array(socket));
559 return convertFromCyclesArray<float3, GfVec3f>(node->get_float3_array(socket));
561 return convertFromCyclesArray<float2, GfVec2f>(node->get_float2_array(socket));
563 return convertFromCyclesArray<ustring, void>(node->get_string_array(socket));
565 return convertFromCyclesArray<Transform, void>(node->get_transform_array(socket));
567 TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
568 return VtValue();
569 }
570 }
571}
572
T * resize(size_t newsize)
void reserve(size_t newcapacity)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:15
array< DstType > convertToCyclesArray(const VtValue &value)
array< Transform > convertToCyclesTransformArray(const VtValue &value)
GfMatrix4f convertMatrixFromCycles(const Transform &matrix)
VtValue convertFromCycles(const SrcType &value)
VtValue convertFromCyclesArray(const array< SrcType > &value)
Transform convertMatrixToCycles(const typename std::enable_if< Matrix::numRows==3 &&Matrix::numColumns==3, Matrix >::type &matrix)
Definition node_util.cpp:95
DstType convertToCycles(const VtValue &value)
Definition node_util.cpp:22
void SetNodeValue(Node *node, const SocketType &socket, const VtValue &value)
VtValue GetNodeValue(const Node *node, const SocketType &socket)
@ BOOLEAN_ARRAY
Definition node_type.h:43
@ TRANSFORM_ARRAY
Definition node_type.h:52
Type type
Definition node_type.h:80
ccl_device_inline Transform transform_identity()
Definition transform.h:296
ccl_device_inline Transform make_transform(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l)
Definition transform.h:133