Blender V5.0
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 const 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 const 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(
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
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
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
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
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
ATTR_WARN_UNUSED_RESULT const void * element
size_t size() const
void reserve(const size_t newcapacity)
T * resize(const size_t newsize)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define assert(assertion)
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
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)
#define make_float2
const array< float3 > & get_float3_array(const SocketType &input) const
const array< float > & get_float_array(const SocketType &input) const
const array< int > & get_int_array(const SocketType &input) const
float get_float(const SocketType &input) const
Transform get_transform(const SocketType &input) const
void set(const SocketType &input, bool value)
float3 get_float3(const SocketType &input) const
const array< bool > & get_bool_array(const SocketType &input) const
bool get_bool(const SocketType &input) const
float2 get_float2(const SocketType &input) const
const array< ustring > & get_string_array(const SocketType &input) const
const array< float2 > & get_float2_array(const SocketType &input) const
ustring get_string(const SocketType &input) const
uint get_uint(const SocketType &input) const
int get_int(const SocketType &input) const
const array< Transform > & get_transform_array(const SocketType &input) const
@ BOOLEAN_ARRAY
Definition node_type.h:45
@ TRANSFORM_ARRAY
Definition node_type.h:54
Type type
Definition node_type.h:82
float x
float y
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
ccl_device_inline Transform transform_identity()
Definition transform.h:322
ccl_device_inline Transform make_transform(const float a, const float b, const float c, const float d, const float e, const float f, const float g, const float h, const float i, const float j, const float k, const float l)
Definition transform.h:159