
Adds support for linking with some of the dependencies of a USD build instead of the precompiled libraries from Blender, specifically OpenSubdiv, OpenVDB and TBB. Other dependencies keep using the precompiled libraries from Blender, since they are linked statically anyway so it does't matter as much. Plus they have interdependencies that are difficult to resolve when only using selected libraries from the USD build and can't simply assume that USD was built with all of them. This patch also makes building the Hydra render delegate via the standalone repository work and fixes various small issues I ran into in general on Windows (e.g. the use of both fixed paths and `find_package` did not seem to work correctly). Building both the standalone Cycles application and the Hydra render delegate at the same time is supported now as well (the paths in the USD plugin JSON file are updated accordingly). All that needs to be done now to build is to specify a `PXR_ROOT` or `USD_ROOT` CMake variable pointing to the USD installation, everything else is taken care of automatically (CMake targets are loaded from the `pxrTargets.cmake` of USD and linked into the render delegate and OpenSubdiv, OpenVDB and TBB are replaced with those from USD when they exist). Differential Revision: https://developer.blender.org/D14523
562 lines
18 KiB
C++
562 lines
18 KiB
C++
/* SPDX-License-Identifier: Apache-2.0
|
|
* Copyright 2022 NVIDIA Corporation
|
|
* Copyright 2022 Blender Foundation */
|
|
|
|
#include "hydra/node_util.h"
|
|
#include "util/transform.h"
|
|
|
|
#include <pxr/base/gf/matrix3d.h>
|
|
#include <pxr/base/gf/matrix3f.h>
|
|
#include <pxr/base/gf/matrix4d.h>
|
|
#include <pxr/base/gf/matrix4f.h>
|
|
#include <pxr/base/gf/vec2f.h>
|
|
#include <pxr/base/gf/vec3f.h>
|
|
#include <pxr/base/vt/array.h>
|
|
#include <pxr/usd/sdf/assetPath.h>
|
|
|
|
HDCYCLES_NAMESPACE_OPEN_SCOPE
|
|
|
|
namespace {
|
|
|
|
template<typename DstType> DstType convertToCycles(const VtValue &value)
|
|
{
|
|
if (value.IsHolding<DstType>()) {
|
|
return value.UncheckedGet<DstType>();
|
|
}
|
|
|
|
VtValue castedValue = VtValue::Cast<DstType>(value);
|
|
if (castedValue.IsHolding<DstType>()) {
|
|
return castedValue.UncheckedGet<DstType>();
|
|
}
|
|
|
|
TF_WARN("Could not convert VtValue to Cycles type");
|
|
return DstType(0);
|
|
}
|
|
|
|
template<> float2 convertToCycles<float2>(const VtValue &value)
|
|
{
|
|
const GfVec2f convertedValue = convertToCycles<GfVec2f>(value);
|
|
return make_float2(convertedValue[0], convertedValue[1]);
|
|
}
|
|
|
|
template<> float3 convertToCycles<float3>(const VtValue &value)
|
|
{
|
|
if (value.IsHolding<GfVec3f>()) {
|
|
const GfVec3f convertedValue = value.UncheckedGet<GfVec3f>();
|
|
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
|
}
|
|
if (value.IsHolding<GfVec4f>()) {
|
|
const GfVec4f convertedValue = value.UncheckedGet<GfVec4f>();
|
|
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
|
}
|
|
|
|
if (value.CanCast<GfVec3f>()) {
|
|
const GfVec3f convertedValue = VtValue::Cast<GfVec3f>(value).UncheckedGet<GfVec3f>();
|
|
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
|
}
|
|
if (value.CanCast<GfVec4f>()) {
|
|
const GfVec4f convertedValue = VtValue::Cast<GfVec4f>(value).UncheckedGet<GfVec4f>();
|
|
return make_float3(convertedValue[0], convertedValue[1], convertedValue[2]);
|
|
}
|
|
|
|
TF_WARN("Could not convert VtValue to float3");
|
|
return zero_float3();
|
|
}
|
|
|
|
template<> ustring convertToCycles<ustring>(const VtValue &value)
|
|
{
|
|
if (value.IsHolding<TfToken>()) {
|
|
return ustring(value.UncheckedGet<TfToken>().GetString());
|
|
}
|
|
if (value.IsHolding<std::string>()) {
|
|
return ustring(value.UncheckedGet<std::string>());
|
|
}
|
|
if (value.IsHolding<SdfAssetPath>()) {
|
|
const SdfAssetPath &path = value.UncheckedGet<SdfAssetPath>();
|
|
return ustring(path.GetResolvedPath());
|
|
}
|
|
|
|
if (value.CanCast<TfToken>()) {
|
|
return convertToCycles<ustring>(VtValue::Cast<TfToken>(value));
|
|
}
|
|
if (value.CanCast<std::string>()) {
|
|
return convertToCycles<ustring>(VtValue::Cast<std::string>(value));
|
|
}
|
|
if (value.CanCast<SdfAssetPath>()) {
|
|
return convertToCycles<ustring>(VtValue::Cast<SdfAssetPath>(value));
|
|
}
|
|
|
|
TF_WARN("Could not convert VtValue to ustring");
|
|
return ustring();
|
|
}
|
|
|
|
template<typename Matrix>
|
|
Transform convertMatrixToCycles(
|
|
const typename std::enable_if<Matrix::numRows == 3 && Matrix::numColumns == 3, Matrix>::type
|
|
&matrix)
|
|
{
|
|
return make_transform(matrix[0][0],
|
|
matrix[1][0],
|
|
matrix[2][0],
|
|
0,
|
|
matrix[0][1],
|
|
matrix[1][1],
|
|
matrix[2][1],
|
|
0,
|
|
matrix[0][2],
|
|
matrix[1][2],
|
|
matrix[2][2],
|
|
0);
|
|
}
|
|
|
|
template<typename Matrix>
|
|
Transform convertMatrixToCycles(
|
|
const typename std::enable_if<Matrix::numRows == 4 && Matrix::numColumns == 4, Matrix>::type
|
|
&matrix)
|
|
{
|
|
return make_transform(matrix[0][0],
|
|
matrix[1][0],
|
|
matrix[2][0],
|
|
matrix[3][0],
|
|
matrix[0][1],
|
|
matrix[1][1],
|
|
matrix[2][1],
|
|
matrix[3][1],
|
|
matrix[0][2],
|
|
matrix[1][2],
|
|
matrix[2][2],
|
|
matrix[3][2]);
|
|
}
|
|
|
|
template<> Transform convertToCycles<Transform>(const VtValue &value)
|
|
{
|
|
if (value.IsHolding<GfMatrix4f>()) {
|
|
return convertMatrixToCycles<GfMatrix4f>(value.UncheckedGet<GfMatrix4f>());
|
|
}
|
|
if (value.IsHolding<GfMatrix3f>()) {
|
|
return convertMatrixToCycles<GfMatrix3f>(value.UncheckedGet<GfMatrix3f>());
|
|
}
|
|
if (value.IsHolding<GfMatrix4d>()) {
|
|
return convertMatrixToCycles<GfMatrix4d>(value.UncheckedGet<GfMatrix4d>());
|
|
}
|
|
if (value.IsHolding<GfMatrix3d>()) {
|
|
return convertMatrixToCycles<GfMatrix3d>(value.UncheckedGet<GfMatrix3d>());
|
|
}
|
|
|
|
if (value.CanCast<GfMatrix4f>()) {
|
|
return convertToCycles<Transform>(VtValue::Cast<GfMatrix4f>(value));
|
|
}
|
|
if (value.CanCast<GfMatrix3f>()) {
|
|
return convertToCycles<Transform>(VtValue::Cast<GfMatrix3f>(value));
|
|
}
|
|
if (value.CanCast<GfMatrix4d>()) {
|
|
return convertToCycles<Transform>(VtValue::Cast<GfMatrix4d>(value));
|
|
}
|
|
if (value.CanCast<GfMatrix3d>()) {
|
|
return convertToCycles<Transform>(VtValue::Cast<GfMatrix3d>(value));
|
|
}
|
|
|
|
TF_WARN("Could not convert VtValue to Transform");
|
|
return transform_identity();
|
|
}
|
|
|
|
template<typename DstType, typename SrcType = DstType>
|
|
array<DstType> convertToCyclesArray(const VtValue &value)
|
|
{
|
|
static_assert(sizeof(DstType) == sizeof(SrcType),
|
|
"Size mismatch between VtArray and array base type");
|
|
|
|
using SrcArray = VtArray<SrcType>;
|
|
|
|
if (value.IsHolding<SrcArray>()) {
|
|
const auto &valueData = value.UncheckedGet<SrcArray>();
|
|
array<DstType> cyclesArray;
|
|
cyclesArray.resize(valueData.size());
|
|
std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
|
|
return cyclesArray;
|
|
}
|
|
|
|
if (value.CanCast<SrcArray>()) {
|
|
VtValue castedValue = VtValue::Cast<SrcArray>(value);
|
|
const auto &valueData = castedValue.UncheckedGet<SrcArray>();
|
|
array<DstType> cyclesArray;
|
|
cyclesArray.resize(valueData.size());
|
|
std::memcpy(cyclesArray.data(), valueData.data(), valueData.size() * sizeof(DstType));
|
|
return cyclesArray;
|
|
}
|
|
|
|
return array<DstType>();
|
|
}
|
|
|
|
template<> array<float3> convertToCyclesArray<float3, GfVec3f>(const VtValue &value)
|
|
{
|
|
if (value.IsHolding<VtVec3fArray>()) {
|
|
const auto &valueData = value.UncheckedGet<VtVec3fArray>();
|
|
array<float3> cyclesArray;
|
|
cyclesArray.reserve(valueData.size());
|
|
for (const GfVec3f &vec : valueData) {
|
|
cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
|
|
}
|
|
return cyclesArray;
|
|
}
|
|
if (value.IsHolding<VtVec4fArray>()) {
|
|
const auto &valueData = value.UncheckedGet<VtVec4fArray>();
|
|
array<float3> cyclesArray;
|
|
cyclesArray.reserve(valueData.size());
|
|
for (const GfVec4f &vec : valueData) {
|
|
cyclesArray.push_back_reserved(make_float3(vec[0], vec[1], vec[2]));
|
|
}
|
|
return cyclesArray;
|
|
}
|
|
|
|
if (value.CanCast<VtVec3fArray>()) {
|
|
return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec3fArray>(value));
|
|
}
|
|
if (value.CanCast<VtVec4fArray>()) {
|
|
return convertToCyclesArray<float3, GfVec3f>(VtValue::Cast<VtVec4fArray>(value));
|
|
}
|
|
|
|
return array<float3>();
|
|
}
|
|
|
|
template<> array<ustring> convertToCyclesArray<ustring, void>(const VtValue &value)
|
|
{
|
|
using SdfPathArray = VtArray<SdfAssetPath>;
|
|
|
|
if (value.IsHolding<VtStringArray>()) {
|
|
const auto &valueData = value.UncheckedGet<VtStringArray>();
|
|
array<ustring> cyclesArray;
|
|
cyclesArray.reserve(valueData.size());
|
|
for (const auto &element : valueData) {
|
|
cyclesArray.push_back_reserved(ustring(element));
|
|
}
|
|
return cyclesArray;
|
|
}
|
|
if (value.IsHolding<VtTokenArray>()) {
|
|
const auto &valueData = value.UncheckedGet<VtTokenArray>();
|
|
array<ustring> cyclesArray;
|
|
cyclesArray.reserve(valueData.size());
|
|
for (const auto &element : valueData) {
|
|
cyclesArray.push_back_reserved(ustring(element.GetString()));
|
|
}
|
|
return cyclesArray;
|
|
}
|
|
if (value.IsHolding<SdfPathArray>()) {
|
|
const auto &valueData = value.UncheckedGet<SdfPathArray>();
|
|
array<ustring> cyclesArray;
|
|
cyclesArray.reserve(valueData.size());
|
|
for (const auto &element : valueData) {
|
|
cyclesArray.push_back_reserved(ustring(element.GetResolvedPath()));
|
|
}
|
|
return cyclesArray;
|
|
}
|
|
|
|
if (value.CanCast<VtStringArray>()) {
|
|
return convertToCyclesArray<ustring, void>(VtValue::Cast<VtStringArray>(value));
|
|
}
|
|
if (value.CanCast<VtTokenArray>()) {
|
|
return convertToCyclesArray<ustring, void>(VtValue::Cast<VtTokenArray>(value));
|
|
}
|
|
if (value.CanCast<SdfPathArray>()) {
|
|
return convertToCyclesArray<ustring, void>(VtValue::Cast<SdfPathArray>(value));
|
|
}
|
|
|
|
TF_WARN("Could not convert VtValue to array<ustring>");
|
|
return array<ustring>();
|
|
}
|
|
|
|
template<typename MatrixArray> array<Transform> convertToCyclesTransformArray(const VtValue &value)
|
|
{
|
|
assert(value.IsHolding<MatrixArray>());
|
|
|
|
const auto &valueData = value.UncheckedGet<MatrixArray>();
|
|
array<Transform> cyclesArray;
|
|
cyclesArray.reserve(valueData.size());
|
|
for (const auto &element : valueData) {
|
|
cyclesArray.push_back_reserved(convertMatrixToCycles<typename MatrixArray::value_type>(element));
|
|
}
|
|
return cyclesArray;
|
|
}
|
|
|
|
template<> array<Transform> convertToCyclesArray<Transform, void>(const VtValue &value)
|
|
{
|
|
if (value.IsHolding<VtMatrix4fArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix4fArray>(value);
|
|
}
|
|
if (value.IsHolding<VtMatrix3fArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix3fArray>(value);
|
|
}
|
|
if (value.IsHolding<VtMatrix4dArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix4dArray>(value);
|
|
}
|
|
if (value.IsHolding<VtMatrix3dArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix3dArray>(value);
|
|
}
|
|
|
|
if (value.CanCast<VtMatrix4fArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix4fArray>(VtValue::Cast<VtMatrix4fArray>(value));
|
|
}
|
|
if (value.CanCast<VtMatrix3fArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix3fArray>(VtValue::Cast<VtMatrix3fArray>(value));
|
|
}
|
|
if (value.CanCast<VtMatrix4dArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix4dArray>(VtValue::Cast<VtMatrix4dArray>(value));
|
|
}
|
|
if (value.CanCast<VtMatrix3dArray>()) {
|
|
return convertToCyclesTransformArray<VtMatrix3dArray>(VtValue::Cast<VtMatrix3dArray>(value));
|
|
}
|
|
|
|
TF_WARN("Could not convert VtValue to array<Transform>");
|
|
return array<Transform>();
|
|
}
|
|
|
|
template<typename SrcType> VtValue convertFromCycles(const SrcType &value)
|
|
{
|
|
return VtValue(value);
|
|
}
|
|
|
|
template<> VtValue convertFromCycles<float2>(const float2 &value)
|
|
{
|
|
const GfVec2f convertedValue(value.x, value.y);
|
|
return VtValue(convertedValue);
|
|
}
|
|
|
|
template<> VtValue convertFromCycles<float3>(const float3 &value)
|
|
{
|
|
const GfVec3f convertedValue(value.x, value.y, value.z);
|
|
return VtValue(convertedValue);
|
|
}
|
|
|
|
template<> VtValue convertFromCycles<ustring>(const ustring &value)
|
|
{
|
|
return VtValue(value.string());
|
|
}
|
|
|
|
GfMatrix4f convertMatrixFromCycles(const Transform &matrix)
|
|
{
|
|
return GfMatrix4f(matrix[0][0],
|
|
matrix[1][0],
|
|
matrix[2][0],
|
|
0.0f,
|
|
matrix[0][1],
|
|
matrix[1][1],
|
|
matrix[2][1],
|
|
0.0f,
|
|
matrix[0][2],
|
|
matrix[1][2],
|
|
matrix[2][2],
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
1.0f);
|
|
}
|
|
|
|
template<> VtValue convertFromCycles<Transform>(const Transform &value)
|
|
{
|
|
return VtValue(convertMatrixFromCycles(value));
|
|
}
|
|
|
|
template<typename SrcType, typename DstType = SrcType>
|
|
VtValue convertFromCyclesArray(const array<SrcType> &value)
|
|
{
|
|
static_assert(sizeof(DstType) == sizeof(SrcType),
|
|
"Size mismatch between VtArray and array base type");
|
|
|
|
VtArray<DstType> convertedValue;
|
|
convertedValue.resize(value.size());
|
|
std::memcpy(convertedValue.data(), value.data(), value.size() * sizeof(SrcType));
|
|
return VtValue(convertedValue);
|
|
}
|
|
|
|
template<> VtValue convertFromCyclesArray<float3, GfVec3f>(const array<float3> &value)
|
|
{
|
|
VtVec3fArray convertedValue;
|
|
convertedValue.reserve(value.size());
|
|
for (const auto &element : value) {
|
|
convertedValue.push_back(GfVec3f(element.x, element.y, element.z));
|
|
}
|
|
return VtValue(convertedValue);
|
|
}
|
|
|
|
template<> VtValue convertFromCyclesArray<ustring, void>(const array<ustring> &value)
|
|
{
|
|
VtStringArray convertedValue;
|
|
convertedValue.reserve(value.size());
|
|
for (const auto &element : value) {
|
|
convertedValue.push_back(element.string());
|
|
}
|
|
return VtValue(convertedValue);
|
|
}
|
|
|
|
template<> VtValue convertFromCyclesArray<Transform, void>(const array<Transform> &value)
|
|
{
|
|
VtMatrix4fArray convertedValue;
|
|
convertedValue.reserve(value.size());
|
|
for (const auto &element : value) {
|
|
convertedValue.push_back(convertMatrixFromCycles(element));
|
|
}
|
|
return VtValue(convertedValue);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void SetNodeValue(Node *node, const SocketType &socket, const VtValue &value)
|
|
{
|
|
switch (socket.type) {
|
|
default:
|
|
case SocketType::UNDEFINED:
|
|
TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
|
|
break;
|
|
|
|
case SocketType::BOOLEAN:
|
|
node->set(socket, convertToCycles<bool>(value));
|
|
break;
|
|
case SocketType::FLOAT:
|
|
node->set(socket, convertToCycles<float>(value));
|
|
break;
|
|
case SocketType::INT:
|
|
node->set(socket, convertToCycles<int>(value));
|
|
break;
|
|
case SocketType::UINT:
|
|
node->set(socket, convertToCycles<unsigned int>(value));
|
|
break;
|
|
case SocketType::COLOR:
|
|
case SocketType::VECTOR:
|
|
case SocketType::POINT:
|
|
case SocketType::NORMAL:
|
|
node->set(socket, convertToCycles<float3>(value));
|
|
break;
|
|
case SocketType::POINT2:
|
|
node->set(socket, convertToCycles<float2>(value));
|
|
break;
|
|
case SocketType::CLOSURE:
|
|
// Handled by node connections
|
|
break;
|
|
case SocketType::STRING:
|
|
node->set(socket, convertToCycles<ustring>(value));
|
|
break;
|
|
case SocketType::ENUM:
|
|
// Enum's can accept a string or an int
|
|
if (value.IsHolding<TfToken>() || value.IsHolding<std::string>()) {
|
|
node->set(socket, convertToCycles<ustring>(value));
|
|
}
|
|
else {
|
|
node->set(socket, convertToCycles<int>(value));
|
|
}
|
|
break;
|
|
case SocketType::TRANSFORM:
|
|
node->set(socket, convertToCycles<Transform>(value));
|
|
break;
|
|
case SocketType::NODE:
|
|
// TODO: renderIndex->GetRprim()->cycles_node ?
|
|
TF_WARN("Unimplemented conversion: SocketType::NODE");
|
|
break;
|
|
|
|
case SocketType::BOOLEAN_ARRAY: {
|
|
auto cyclesArray = convertToCyclesArray<bool>(value);
|
|
node->set(socket, cyclesArray);
|
|
break;
|
|
}
|
|
case SocketType::FLOAT_ARRAY: {
|
|
auto cyclesArray = convertToCyclesArray<float>(value);
|
|
node->set(socket, cyclesArray);
|
|
break;
|
|
}
|
|
case SocketType::INT_ARRAY: {
|
|
auto cyclesArray = convertToCyclesArray<int>(value);
|
|
node->set(socket, cyclesArray);
|
|
break;
|
|
}
|
|
case SocketType::COLOR_ARRAY:
|
|
case SocketType::VECTOR_ARRAY:
|
|
case SocketType::POINT_ARRAY:
|
|
case SocketType::NORMAL_ARRAY: {
|
|
auto cyclesArray = convertToCyclesArray<float3, GfVec3f>(value);
|
|
node->set(socket, cyclesArray);
|
|
break;
|
|
}
|
|
case SocketType::POINT2_ARRAY: {
|
|
auto cyclesArray = convertToCyclesArray<float2, GfVec2f>(value);
|
|
node->set(socket, cyclesArray);
|
|
break;
|
|
}
|
|
case SocketType::STRING_ARRAY: {
|
|
auto cyclesArray = convertToCyclesArray<ustring, void>(value);
|
|
node->set(socket, cyclesArray);
|
|
break;
|
|
}
|
|
case SocketType::TRANSFORM_ARRAY: {
|
|
auto cyclesArray = convertToCyclesArray<Transform, void>(value);
|
|
node->set(socket, cyclesArray);
|
|
break;
|
|
}
|
|
case SocketType::NODE_ARRAY: {
|
|
// TODO: renderIndex->GetRprim()->cycles_node ?
|
|
TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
VtValue GetNodeValue(const Node *node, const SocketType &socket)
|
|
{
|
|
switch (socket.type) {
|
|
default:
|
|
case SocketType::UNDEFINED:
|
|
TF_RUNTIME_ERROR("Unexpected conversion: SocketType::UNDEFINED");
|
|
return VtValue();
|
|
|
|
case SocketType::BOOLEAN:
|
|
return convertFromCycles(node->get_bool(socket));
|
|
case SocketType::FLOAT:
|
|
return convertFromCycles(node->get_float(socket));
|
|
case SocketType::INT:
|
|
return convertFromCycles(node->get_int(socket));
|
|
case SocketType::UINT:
|
|
return convertFromCycles(node->get_uint(socket));
|
|
case SocketType::COLOR:
|
|
case SocketType::VECTOR:
|
|
case SocketType::POINT:
|
|
case SocketType::NORMAL:
|
|
return convertFromCycles(node->get_float3(socket));
|
|
case SocketType::POINT2:
|
|
return convertFromCycles(node->get_float2(socket));
|
|
case SocketType::CLOSURE:
|
|
return VtValue();
|
|
case SocketType::STRING:
|
|
return convertFromCycles(node->get_string(socket));
|
|
case SocketType::ENUM:
|
|
return convertFromCycles(node->get_int(socket));
|
|
case SocketType::TRANSFORM:
|
|
return convertFromCycles(node->get_transform(socket));
|
|
case SocketType::NODE:
|
|
TF_WARN("Unimplemented conversion: SocketType::NODE");
|
|
return VtValue();
|
|
|
|
case SocketType::BOOLEAN_ARRAY:
|
|
return convertFromCyclesArray(node->get_bool_array(socket));
|
|
case SocketType::FLOAT_ARRAY:
|
|
return convertFromCyclesArray(node->get_float_array(socket));
|
|
case SocketType::INT_ARRAY:
|
|
return convertFromCyclesArray(node->get_int_array(socket));
|
|
case SocketType::COLOR_ARRAY:
|
|
case SocketType::VECTOR_ARRAY:
|
|
case SocketType::POINT_ARRAY:
|
|
case SocketType::NORMAL_ARRAY:
|
|
return convertFromCyclesArray<float3, GfVec3f>(node->get_float3_array(socket));
|
|
case SocketType::POINT2_ARRAY:
|
|
return convertFromCyclesArray<float2, GfVec2f>(node->get_float2_array(socket));
|
|
case SocketType::STRING_ARRAY:
|
|
return convertFromCyclesArray<ustring, void>(node->get_string_array(socket));
|
|
case SocketType::TRANSFORM_ARRAY:
|
|
return convertFromCyclesArray<Transform, void>(node->get_transform_array(socket));
|
|
case SocketType::NODE_ARRAY: {
|
|
TF_WARN("Unimplemented conversion: SocketType::NODE_ARRAY");
|
|
return VtValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
HDCYCLES_NAMESPACE_CLOSE_SCOPE
|