diff options
Diffstat (limited to 'intern/cycles/hydra/node_util.cpp')
-rw-r--r-- | intern/cycles/hydra/node_util.cpp | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/intern/cycles/hydra/node_util.cpp b/intern/cycles/hydra/node_util.cpp new file mode 100644 index 00000000000..c7e49688f5c --- /dev/null +++ b/intern/cycles/hydra/node_util.cpp @@ -0,0 +1,561 @@ +/* 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<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 |