diff --git a/contrib/IECoreUSD/src/IECoreUSD/DataAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/DataAlgo.cpp index b34981db6c..e5de4b5755 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/DataAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/DataAlgo.cpp @@ -139,6 +139,11 @@ IECore::DataPtr dataFromArray( const pxr::VtValue &value, GeometricData::Interpr return d; } +IECore::DataPtr dataFromSdfAssetPath( const pxr::VtValue &value, GeometricData::Interpretation interpretation, bool arrayAccepted ) +{ + return new StringData( value.Get().GetResolvedPath() ); +} + static const std::map g_fromVtValueConverters = { // Numeric types @@ -202,7 +207,8 @@ static const std::map(), &dataFromValue }, { TfType::Find>(), &dataFromArray }, { TfType::Find(), &dataFromValue }, - { TfType::Find>(), &dataFromArray } + { TfType::Find>(), &dataFromArray }, + { TfType::Find(), &dataFromSdfAssetPath } }; diff --git a/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp index baadb00781..be1dbe5a82 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp @@ -46,95 +46,107 @@ namespace { - pxr::TfToken g_adapterLabelToken( IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel().string() ); - IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &usdShader, IECoreScene::ShaderNetwork &shaderNetwork ) - { - IECore::InternedString handle( usdShader.GetPath().MakeRelativePath( anchorPath ).GetString() ); +pxr::TfToken g_adapterLabelToken( IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel().string() ); - if( shaderNetwork.getShader( handle ) ) - { - return handle; - } +IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &usdShader, IECoreScene::ShaderNetwork &shaderNetwork ) +{ + IECore::InternedString handle( usdShader.GetPath().MakeRelativePath( anchorPath ).GetString() ); + + if( shaderNetwork.getShader( handle ) ) + { + return handle; + } - pxr::TfToken id; - std::string shaderName = "defaultsurface"; - std::string shaderType = "surface"; - if( usdShader.GetShaderId( &id ) ) + pxr::TfToken id; + std::string shaderName = "defaultsurface"; + std::string shaderType = "surface"; + if( usdShader.GetShaderId( &id ) ) + { + std::string name = id.GetString(); + size_t colonPos = name.find( ":" ); + if( colonPos != std::string::npos ) { - std::string name = id.GetString(); - size_t colonPos = name.find( ":" ); - if( colonPos != std::string::npos ) + std::string prefix = name.substr( 0, colonPos ); + name = name.substr( colonPos + 1 ); + if( prefix == "arnold" ) { - std::string prefix = name.substr( 0, colonPos ); - name = name.substr( colonPos + 1 ); - if( prefix == "arnold" ) - { - prefix = "ai"; - } - shaderType = prefix + ":shader"; + prefix = "ai"; } - shaderName = name; + shaderType = prefix + ":shader"; } + shaderName = name; + } - IECore::CompoundDataPtr parametersData = new IECore::CompoundData(); - IECore::CompoundDataMap ¶meters = parametersData->writable(); - std::vector< std::tuple< IECore::InternedString, pxr::UsdShadeConnectableAPI, IECore::InternedString > > connections; - std::vector< pxr::UsdShadeInput > inputs = usdShader.GetInputs(); - for( pxr::UsdShadeInput &i : usdShader.GetInputs() ) - { - pxr::UsdShadeConnectableAPI usdSource; - pxr::TfToken usdSourceName; - pxr::UsdShadeAttributeType usdSourceType; + IECore::CompoundDataPtr parametersData = new IECore::CompoundData(); + IECore::CompoundDataMap ¶meters = parametersData->writable(); + std::vector< std::tuple< IECore::InternedString, pxr::UsdShadeConnectableAPI, IECore::InternedString > > connections; + std::vector< pxr::UsdShadeInput > inputs = usdShader.GetInputs(); + for( pxr::UsdShadeInput &i : usdShader.GetInputs() ) + { + pxr::UsdShadeConnectableAPI usdSource; + pxr::TfToken usdSourceName; + pxr::UsdShadeAttributeType usdSourceType; - if( IECore::DataPtr d = IECoreUSD::DataAlgo::fromUSD( pxr::UsdAttribute( i ) ) ) + pxr::UsdAttribute valueAttribute = i; + if( i.GetConnectedSource( &usdSource, &usdSourceName, &usdSourceType ) ) + { + if( !usdSource.IsContainer() ) { - parameters[ i.GetBaseName().GetString() ] = d; + connections.push_back( { i.GetBaseName().GetString(), usdSource, usdSourceName.GetString() } ); } - - if( i.GetConnectedSource( &usdSource, &usdSourceName, &usdSourceType ) ) + else { - connections.push_back( { i.GetBaseName().GetString(), usdSource, usdSourceName.GetString() } ); + // Connected to an exposed input on the material container. We don't + // have an equivalent in IECoreScene::ShaderNetwork yet, so just take + // the parameter value from the exposed input. + valueAttribute = usdSource.GetInput( usdSourceName ); } } - parametersData = boost::const_pointer_cast< IECore::CompoundData >( IECoreScene::ShaderNetworkAlgo::collapseSplineParameters( parametersData ) ); - - IECoreScene::ShaderPtr newShader = new IECoreScene::Shader( shaderName, shaderType, parametersData ); - pxr::VtValue metadataValue; - if( usdShader.GetPrim().GetMetadata( g_adapterLabelToken, &metadataValue ) && metadataValue.Get() ) + if( IECore::DataPtr d = IECoreUSD::DataAlgo::fromUSD( pxr::UsdAttribute( valueAttribute ) ) ) { - newShader->blindData()->writable()[ IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel() ] = new IECore::BoolData( true ); + parameters[ i.GetBaseName().GetString() ] = d; } - shaderNetwork.addShader( handle, std::move( newShader ) ); + } - for( const auto &c : connections ) - { - IECore::InternedString attributeName; - pxr::UsdShadeConnectableAPI usdSource; - IECore::InternedString sourceAttributeName; - std::tie( attributeName, usdSource, sourceAttributeName ) = c; - IECore::InternedString sourceHandle = readShaderNetworkWalk( anchorPath, pxr::UsdShadeShader( usdSource.GetPrim() ), shaderNetwork ); + parametersData = boost::const_pointer_cast< IECore::CompoundData >( IECoreScene::ShaderNetworkAlgo::collapseSplineParameters( parametersData ) ); - if( sourceAttributeName == "DEFAULT_OUTPUT" ) - { - shaderNetwork.addConnection( IECoreScene::ShaderNetwork::Connection( - { sourceHandle, "" }, - { handle, attributeName } - ) ); - } - else - { - shaderNetwork.addConnection( IECoreScene::ShaderNetwork::Connection( - { sourceHandle, sourceAttributeName }, - { handle, attributeName } - ) ); - } - } + IECoreScene::ShaderPtr newShader = new IECoreScene::Shader( shaderName, shaderType, parametersData ); + pxr::VtValue metadataValue; + if( usdShader.GetPrim().GetMetadata( g_adapterLabelToken, &metadataValue ) && metadataValue.Get() ) + { + newShader->blindData()->writable()[ IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel() ] = new IECore::BoolData( true ); + } + shaderNetwork.addShader( handle, std::move( newShader ) ); - return handle; + for( const auto &c : connections ) + { + IECore::InternedString attributeName; + pxr::UsdShadeConnectableAPI usdSource; + IECore::InternedString sourceAttributeName; + std::tie( attributeName, usdSource, sourceAttributeName ) = c; + IECore::InternedString sourceHandle = readShaderNetworkWalk( anchorPath, pxr::UsdShadeShader( usdSource.GetPrim() ), shaderNetwork ); + + if( sourceAttributeName == "DEFAULT_OUTPUT" ) + { + shaderNetwork.addConnection( IECoreScene::ShaderNetwork::Connection( + { sourceHandle, "" }, + { handle, attributeName } + ) ); + } + else + { + shaderNetwork.addConnection( IECoreScene::ShaderNetwork::Connection( + { sourceHandle, sourceAttributeName }, + { handle, attributeName } + ) ); + } } + return handle; +} + } // namespace pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer ) diff --git a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py index 8e705f2ad9..dfb2448f99 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -2938,5 +2938,34 @@ def testHoudiniVaryingLengthArrayPrimVar( self ) : ) ) + def testAssetAttributes( self ) : + + root = IECoreScene.SceneInterface.create( + os.path.join( os.path.dirname( __file__ ), "data", "assetPathAttribute.usda" ), + IECore.IndexedIO.OpenMode.Read + ) + xform = root.child( "xform" ) + + self.assertEqual( xform.attributeNames(), [ "render:testAsset" ] ) + self.assertEqual( + os.path.normcase( os.path.normpath( xform.readAttribute( "render:testAsset", 0 ).value ) ), + os.path.normcase( os.path.join( os.path.dirname( __file__ ), "data", "cube.usda" ) ) + ) + + def testExposedShaderInput( self ) : + + root = IECoreScene.SceneInterface.create( + os.path.join( os.path.dirname( __file__ ), "data", "exposedShaderInput.usda" ), + IECore.IndexedIO.OpenMode.Read + ) + sphere = root.child( "model" ).child( "sphere" ) + + self.assertEqual( sphere.attributeNames(), [ "surface" ] ) + network = sphere.readAttribute( "surface", 0 ) + + self.assertEqual( network.size(), 1 ) + self.assertEqual( network.getOutput(), "surface" ) + self.assertEqual( network.getShader( "surface" ).parameters["diffuse_roughness"].value, 0.75 ) + if __name__ == "__main__": unittest.main() diff --git a/contrib/IECoreUSD/test/IECoreUSD/data/assetPathAttribute.usda b/contrib/IECoreUSD/test/IECoreUSD/data/assetPathAttribute.usda new file mode 100644 index 0000000000..d9d495e534 --- /dev/null +++ b/contrib/IECoreUSD/test/IECoreUSD/data/assetPathAttribute.usda @@ -0,0 +1,9 @@ +#usda 1.0 + +def Xform "xform" +{ + + asset primvars:testAsset = @./cube.usda@ + +} + diff --git a/contrib/IECoreUSD/test/IECoreUSD/data/exposedShaderInput.usda b/contrib/IECoreUSD/test/IECoreUSD/data/exposedShaderInput.usda new file mode 100644 index 0000000000..d4d66f7d1f --- /dev/null +++ b/contrib/IECoreUSD/test/IECoreUSD/data/exposedShaderInput.usda @@ -0,0 +1,30 @@ +#usda 1.0 + +def "model" +{ + + def Sphere "sphere" + { + rel material:binding = + } + + def Scope "materials" + { + + def Material "material1" + { + + float inputs:exposedRoughness = 0.75 + token outputs:surface.connect = + + def Shader "surface" + { + uniform token info:id = "arnold:standard_surface" + float inputs:diffuse_roughness.connect = + token outputs:DEFAULT_OUTPUT + } + } + + } + +} diff --git a/src/IECoreScene/CurvesAlgo.cpp b/src/IECoreScene/CurvesAlgo.cpp index 6dbc820f6e..a04f0aab43 100644 --- a/src/IECoreScene/CurvesAlgo.cpp +++ b/src/IECoreScene/CurvesAlgo.cpp @@ -52,14 +52,16 @@ namespace // PrimitiveEvaluator only supports certain types -template< typename T > struct IsPrimitiveEvaluatableTypedData : boost::mpl::and_< +template< typename T > +struct IsPrimitiveEvaluatableTypedData : boost::mpl::and_< TypeTraits::IsNumericBasedVectorTypedData, boost::mpl::or_< - TypeTraits::IsVec3::type >, - boost::is_same< typename TypeTraits::VectorValueType::type, float >, - boost::is_same< typename TypeTraits::VectorValueType::type, int >, - TypeTraits::IsColor3::type > -> + TypeTraits::IsVec2::type>, + TypeTraits::IsVec3::type>, + boost::is_same::type, float>, + boost::is_same::type, int>, + TypeTraits::IsColor3::type> + > > {}; @@ -69,6 +71,11 @@ static T evalPrimVar( PrimitiveEvaluator::Result *result, const PrimitiveVariabl throw Exception( "PrimvarResamplerCache : This should never be called because of IsPrimitiveEvaluatableTypedData" ); } +template<> +Imath::V2f evalPrimVar( PrimitiveEvaluator::Result *result, const PrimitiveVariable &primVar ) +{ + return result->vec2PrimVar( primVar ); +} template<> Imath::V3f evalPrimVar( PrimitiveEvaluator::Result *result, const PrimitiveVariable &primVar ) diff --git a/test/IECoreScene/CurvesAlgoTest.py b/test/IECoreScene/CurvesAlgoTest.py index ff2cc89089..d9ce5f3c11 100644 --- a/test/IECoreScene/CurvesAlgoTest.py +++ b/test/IECoreScene/CurvesAlgoTest.py @@ -1195,6 +1195,24 @@ def testBezierCurvesFaceVaryingToVarying( self ) : # endregion + def testV2fVaryingToVertex( self ) : + + curves = IECoreScene.CurvesPrimitive( + IECore.IntVectorData( [ 4 ] ), IECore.CubicBasisf.catmullRom(), False, + IECore.V3fVectorData( [ imath.V3f( i ) for i in range( 0, 4 ) ] ) + ) + + uv = IECoreScene.PrimitiveVariable( + IECoreScene.PrimitiveVariable.Interpolation.Varying, + IECore.V2fVectorData( [ imath.V2f( 0 ), imath.V2f( 1 ) ] ) + ) + curves["uv"] = uv + + IECoreScene.CurvesAlgo.resamplePrimitiveVariable( curves, uv, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) + self.assertTrue( curves.arePrimitiveVariablesValid() ) + self.assertEqual( uv.interpolation, IECoreScene.PrimitiveVariable.Interpolation.Vertex ) + self.assertEqual( len( uv.data ), 4 ) + class CurvesAlgoDeleteCurvesTest ( unittest.TestCase ): def createLinearCurves(self):