diff --git a/SConstruct b/SConstruct index af8b6b4272..1dd8decf2d 100644 --- a/SConstruct +++ b/SConstruct @@ -2999,6 +2999,7 @@ else : usdLibs = [ "usd", "usdGeom", + "usdLux", "usdSkel", "usdShade", "sdf", diff --git a/contrib/IECoreUSD/include/IECoreUSD/ShaderAlgo.h b/contrib/IECoreUSD/include/IECoreUSD/ShaderAlgo.h index 15389c73d7..036a90d52f 100644 --- a/contrib/IECoreUSD/include/IECoreUSD/ShaderAlgo.h +++ b/contrib/IECoreUSD/include/IECoreUSD/ShaderAlgo.h @@ -42,6 +42,9 @@ IECORE_PUSH_DEFAULT_VISIBILITY #include "pxr/usd/usdShade/material.h" #include "pxr/usd/usdShade/output.h" +#if PXR_VERSION >= 2111 +#include "pxr/usd/usdLux/lightAPI.h" +#endif IECORE_POP_DEFAULT_VISIBILITY namespace IECoreUSD @@ -53,13 +56,13 @@ namespace ShaderAlgo /// Write ShaderNetwork to USD, placing the shaders under the Prim `shaderContainer` IECOREUSD_API pxr::UsdShadeOutput writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer ); -/// Read ShaderNetwork from a USD node ( and its connected inputs ) -/// `anchorPath` is the ancestor path that shaders will be named relative to -/// `outputHandle` specifies which output of the USD node is being used ( the ShaderNetwork must have -/// a corresponding output set ) -IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &outputShader, const pxr::TfToken &outputHandle ); - +/// Reads a ShaderNetwork from a material output, typically obtained from `UsdShadeMaterial::GetOutput()`. +IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdShadeOutput &output ); +#if PXR_VERSION >= 2111 +/// Reads a ShaderNetwork from a light. +IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdLuxLightAPI &light ); +#endif } // namespace ShaderAlgo diff --git a/contrib/IECoreUSD/src/IECoreUSD/PointInstancerAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/PointInstancerAlgo.cpp index d6513d0c12..e866662635 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/PointInstancerAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/PointInstancerAlgo.cpp @@ -95,13 +95,11 @@ IECore::ObjectPtr readPointInstancer( pxr::UsdGeomPointInstancer &pointInstancer newPoints->variables["velocity"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, velocityData ); } -#if USD_VERSION >= 1911 if( auto accelerationData = DataAlgo::fromUSD( pointInstancer.GetAccelerationsAttr(), time ) ) { Canceller::check( canceller ); newPoints->variables["acceleration"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, accelerationData ); } -#endif if( auto angularVelocityData = DataAlgo::fromUSD( pointInstancer.GetAngularVelocitiesAttr(), time ) ) { @@ -137,9 +135,7 @@ bool pointInstancerMightBeTimeVarying( pxr::UsdGeomPointInstancer &instancer ) instancer.GetOrientationsAttr().ValueMightBeTimeVarying() || instancer.GetScalesAttr().ValueMightBeTimeVarying() || instancer.GetVelocitiesAttr().ValueMightBeTimeVarying() || -#if USD_VERSION >= 1911 instancer.GetAccelerationsAttr().ValueMightBeTimeVarying() || -#endif instancer.GetAngularVelocitiesAttr().ValueMightBeTimeVarying() ; } diff --git a/contrib/IECoreUSD/src/IECoreUSD/PrimitiveAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/PrimitiveAlgo.cpp index 22ebdbd49e..63175e0a5c 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/PrimitiveAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/PrimitiveAlgo.cpp @@ -54,12 +54,6 @@ IECORE_PUSH_DEFAULT_VISIBILITY #include "pxr/usd/usdSkel/root.h" IECORE_POP_DEFAULT_VISIBILITY - -/// \todo Use the standard PXR_VERSION instead. We can't do that until -/// everyone is using USD 19.11 though, because prior to that PXR_VERSION -/// was malformed (octal, and not comparable in any way). -#define USD_VERSION ( PXR_MAJOR_VERSION * 10000 + PXR_MINOR_VERSION * 100 + PXR_PATCH_VERSION ) - using namespace std; using namespace pxr; using namespace IECore; @@ -136,12 +130,10 @@ void IECoreUSD::PrimitiveAlgo::writePrimitiveVariable( const std::string &name, { pointBased.CreateVelocitiesAttr().Set( PrimitiveAlgo::toUSDExpanded( value ), time ); } -#if USD_VERSION >= 1911 else if( name == "acceleration" ) { pointBased.CreateAccelerationsAttr().Set( PrimitiveAlgo::toUSDExpanded( value ), time ); } -#endif else { writePrimitiveVariable( name, value, static_cast( pointBased ), time ); @@ -329,7 +321,7 @@ bool readPrimitiveVariables( const pxr::UsdSkelRoot &skelRoot, const pxr::UsdGeo } Canceller::check( canceller ); -#if USD_VERSION < 2011 +#if PXR_VERSION < 2011 ::skelCache()->Populate( skelRoot ); #else ::skelCache()->Populate( skelRoot, pxr::UsdTraverseInstanceProxies() ); @@ -498,12 +490,10 @@ void IECoreUSD::PrimitiveAlgo::readPrimitiveVariables( const pxr::UsdGeomPointBa primitive->variables["velocity"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, v ); } -#if USD_VERSION >= 1911 if( auto a = boost::static_pointer_cast( DataAlgo::fromUSD( pointBased.GetAccelerationsAttr(), time ) ) ) { primitive->variables["acceleration"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Vertex, a ); } -#endif } bool IECoreUSD::PrimitiveAlgo::primitiveVariablesMightBeTimeVarying( const pxr::UsdGeomPrimvarsAPI &primvarsAPI ) @@ -524,9 +514,7 @@ bool IECoreUSD::PrimitiveAlgo::primitiveVariablesMightBeTimeVarying( const pxr:: pointBased.GetPointsAttr().ValueMightBeTimeVarying() || pointBased.GetNormalsAttr().ValueMightBeTimeVarying() || pointBased.GetVelocitiesAttr().ValueMightBeTimeVarying() || -#if USD_VERSION >= 1911 pointBased.GetAccelerationsAttr().ValueMightBeTimeVarying() || -#endif primitiveVariablesMightBeTimeVarying( pxr::UsdGeomPrimvarsAPI( pointBased.GetPrim() ) ) || skelAnimMightBeTimeVarying( pointBased.GetPrim() ) ; diff --git a/contrib/IECoreUSD/src/IECoreUSD/SceneCacheFileFormat.cpp b/contrib/IECoreUSD/src/IECoreUSD/SceneCacheFileFormat.cpp index 49feb81c60..76e10720f7 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/SceneCacheFileFormat.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/SceneCacheFileFormat.cpp @@ -237,11 +237,7 @@ void UsdSceneCacheFileFormat::writeLocation( inChild->path( currentPath ); SdfPath primPath = USDScene::toUSD(currentPath); - #if PXR_VERSION < 2007 - if( primPath.AbsoluteRootPath() != SdfPath( "/" ) ) - #else if( !primPath.IsAbsoluteRootPath() ) - #endif { if( const auto linkedOutScene = runTimeCast( outChild.get() ) ) { diff --git a/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp index 9f93f417ec..1b727cff93 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp @@ -53,7 +53,26 @@ namespace pxr::TfToken g_adapterLabelToken( IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel().string() ); -IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &usdShader, IECoreScene::ShaderNetwork &shaderNetwork ) +pxr::TfToken shaderId( const pxr::UsdShadeConnectableAPI &connectable ) +{ + pxr::TfToken result; + if( auto shader = pxr::UsdShadeShader( connectable ) ) + { + shader.GetShaderId( &result ); + } +#if PXR_VERSION >= 2111 + else if( auto light = pxr::UsdLuxLightAPI( connectable ) ) + { + light.GetShaderIdAttr().Get( &result ); + } +#endif + + return result; +} + +IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork ); + +IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeConnectableAPI &usdShader, IECoreScene::ShaderNetwork &shaderNetwork ) { IECore::InternedString handle( usdShader.GetPath().MakeRelativePath( anchorPath ).GetString() ); @@ -62,10 +81,10 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co return handle; } - pxr::TfToken id; + const pxr::TfToken id = shaderId( usdShader ); std::string shaderName = "defaultsurface"; std::string shaderType = "surface"; - if( usdShader.GetShaderId( &id ) ) + if( id.size() ) { std::string name = id.GetString(); size_t colonPos = name.find( ":" ); @@ -84,8 +103,7 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co 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(); + std::vector connections; for( pxr::UsdShadeInput &i : usdShader.GetInputs() ) { pxr::UsdShadeConnectableAPI usdSource; @@ -95,9 +113,14 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co pxr::UsdAttribute valueAttribute = i; if( i.GetConnectedSource( &usdSource, &usdSourceName, &usdSourceType ) ) { - if( !usdSource.IsContainer() ) + if( usdSourceType == pxr::UsdShadeAttributeType::Output ) { - connections.push_back( { i.GetBaseName().GetString(), usdSource, usdSourceName.GetString() } ); + const IECoreScene::ShaderNetwork::Parameter sourceHandle = readShaderNetworkWalk( + anchorPath, usdSource.GetOutput( usdSourceName ), shaderNetwork + ); + connections.push_back( { + sourceHandle, { handle, IECore::InternedString( i.GetBaseName().GetString() ) } + } ); } else { @@ -124,33 +147,28 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co } shaderNetwork.addShader( handle, std::move( newShader ) ); + // Can only add connections after we've added the shader. 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 } - ) ); - } + shaderNetwork.addConnection( c ); } return handle; } +IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath &anchorPath, const pxr::UsdShadeOutput &output, IECoreScene::ShaderNetwork &shaderNetwork ) +{ + IECore::InternedString shaderHandle = readShaderNetworkWalk( anchorPath, pxr::UsdShadeConnectableAPI( output.GetPrim() ), shaderNetwork ); + if( output.GetBaseName() != "DEFAULT_OUTPUT" ) + { + return IECoreScene::ShaderNetwork::Parameter( shaderHandle, output.GetBaseName().GetString() ); + } + else + { + return IECoreScene::ShaderNetwork::Parameter( shaderHandle ); + } +} + } // namespace pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer ) @@ -249,10 +267,21 @@ pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene return networkOutUsd; } -IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::SdfPath &anchorPath, const pxr::UsdShadeShader &outputShader, const pxr::TfToken &outputParameter ) +IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::UsdShadeOutput &output ) { + pxr::UsdShadeConnectableAPI usdSource; + pxr::TfToken usdSourceName; + pxr::UsdShadeAttributeType usdSourceType; + if( + !output.GetConnectedSource( &usdSource, &usdSourceName, &usdSourceType ) || + usdSourceType != pxr::UsdShadeAttributeType::Output + ) + { + return new IECoreScene::ShaderNetwork(); + } + IECoreScene::ShaderNetworkPtr result = new IECoreScene::ShaderNetwork(); - IECore::InternedString outputHandle = readShaderNetworkWalk( anchorPath, outputShader, *result ); + IECoreScene::ShaderNetwork::Parameter outputHandle = readShaderNetworkWalk( usdSource.GetPrim().GetParent().GetPath(), usdSource.GetOutput( usdSourceName ), *result ); // For the output shader, set the type to "ai:surface" if it is "ai:shader". // This is complete nonsense - there is nothing to suggest that this shader is @@ -265,24 +294,30 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px // don't use the suffix of the shader type for anything, and we should just set // everything to prefix:shader ( aside from lights, which are a bit of a // different question ) - if( result->getShader( outputHandle )->getType() == "ai:shader" ) + const IECoreScene::Shader *outputShader = result->getShader( outputHandle.shader ); + if( outputShader->getType() == "ai:shader" ) { - IECoreScene::ShaderPtr o = result->getShader( outputHandle )->copy(); + IECoreScene::ShaderPtr o = outputShader->copy(); o->setType( "ai:surface" ); - result->setShader( outputHandle, std::move( o ) ); + result->setShader( outputHandle.shader, std::move( o ) ); } - // handles[0] is the handle of the first shader added, which is always the output shader - if( outputParameter.GetString() != "DEFAULT_OUTPUT" ) - { - result->setOutput( IECoreScene::ShaderNetwork::Parameter( outputHandle, outputParameter.GetString() ) ); - } - else - { - result->setOutput( IECoreScene::ShaderNetwork::Parameter( outputHandle ) ); - } + result->setOutput( outputHandle ); IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters( result.get() ); return result; } + +#if PXR_VERSION >= 2111 + +IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::UsdLuxLightAPI &light ) +{ + IECoreScene::ShaderNetworkPtr result = new IECoreScene::ShaderNetwork(); + IECoreScene::ShaderNetwork::Parameter lightHandle = readShaderNetworkWalk( light.GetPath().GetParentPath(), pxr::UsdShadeConnectableAPI( light ), *result ); + result->setOutput( lightHandle ); + IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters( result.get() ); + return result; +} + +#endif diff --git a/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp b/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp index e1c2d9ebd6..5e902821dc 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp @@ -63,6 +63,9 @@ IECORE_PUSH_DEFAULT_VISIBILITY #include "pxr/usd/usdGeom/scope.h" #include "pxr/usd/usdGeom/tokens.h" #include "pxr/usd/usdGeom/xform.h" +#if PXR_VERSION >= 2111 +#include "pxr/usd/usdLux/lightAPI.h" +#endif #include "pxr/usd/usdShade/material.h" #include "pxr/usd/usdShade/materialBindingAPI.h" #include "pxr/usd/usdShade/connectableAPI.h" @@ -84,16 +87,7 @@ using namespace IECore; using namespace IECoreScene; using namespace IECoreUSD; -/// \todo Use the standard PXR_VERSION instead. We can't do that until -/// everyone is using USD 19.11 though, because prior to that PXR_VERSION -/// was malformed (octal, and not comparable in any way). -#define USD_VERSION ( PXR_MAJOR_VERSION * 10000 + PXR_MINOR_VERSION * 100 + PXR_PATCH_VERSION ) - -#if USD_VERSION < 1903 -#define HasAuthoredValue HasAuthoredValueOpinion -#endif - -#if USD_VERSION < 2011 +#if PXR_VERSION < 2011 #define GetPrimInPrototype GetPrimInMaster #endif @@ -204,7 +198,7 @@ void writeSetInternal( const pxr::UsdPrim &prim, const pxr::TfToken &name, const targets.push_back( USDScene::toUSD( *it, /* relative = */ true ) ); } -#if USD_VERSION < 2009 +#if PXR_VERSION < 2009 pxr::UsdCollectionAPI collection = pxr::UsdCollectionAPI::ApplyCollection( prim, validName( name ), pxr::UsdTokens->explicitOnly ); @@ -219,7 +213,7 @@ void writeSetInternal( const pxr::UsdPrim &prim, const pxr::TfToken &name, const } template -IECore::PathMatcher readSchemaTypeSet( const pxr::UsdPrim &prim ) +IECore::PathMatcher descendantsWithType( const pxr::UsdPrim &prim ) { IECore::PathMatcher result; for( const auto &descendant : prim.GetDescendants() ) @@ -232,9 +226,26 @@ IECore::PathMatcher readSchemaTypeSet( const pxr::UsdPrim &prim ) return result; } +template +IECore::PathMatcher descendantsWithAPI( const pxr::UsdPrim &prim ) +{ + IECore::PathMatcher result; + for( const auto &descendant : prim.GetDescendants() ) + { + if( descendant.HasAPI() ) + { + result.addPath( USDScene::fromUSD( descendant.GetPath() ) ); + } + } + return result; +} + boost::container::flat_map g_schemaTypeSetReaders = { - { "__cameras", readSchemaTypeSet }, - { "usd:pointInstancers", readSchemaTypeSet } + { "__cameras", descendantsWithType }, +#if PXR_VERSION >= 2111 + { "__lights", descendantsWithAPI }, +#endif + { "usd:pointInstancers", descendantsWithType } }; IECore::PathMatcher readSetInternal( const pxr::UsdPrim &prim, const pxr::TfToken &name, bool includeDescendantSets, const Canceller *canceller ) @@ -424,26 +435,7 @@ class ShaderNetworkCache : public LRUCacheObject::memoryUsage(); return result; } @@ -803,6 +795,7 @@ namespace const IECore::InternedString g_purposeAttributeName( "usd:purpose" ); const IECore::InternedString g_kindAttributeName( "usd:kind" ); +const IECore::InternedString g_lightAttributeName( "light" ); } // namespace @@ -828,6 +821,12 @@ bool USDScene::hasAttribute( const SceneInterface::Name &name ) const pxr::TfToken kind; return model.GetKind( &kind ); } +#if PXR_VERSION >= 2111 + else if( name == g_lightAttributeName ) + { + return m_location->prim.HasAPI(); + } +#endif else if( auto attribute = AttributeAlgo::findUSDAttribute( m_location->prim, name.string() ) ) { return attribute.HasAuthoredValue(); @@ -876,6 +875,13 @@ void USDScene::attributeNames( SceneInterface::NameList &attrs ) const attrs.push_back( g_kindAttributeName ); } +#if PXR_VERSION >= 2111 + if( m_location->prim.HasAPI() ) + { + attrs.push_back( g_lightAttributeName ); + } +#endif + std::vector attributes = m_location->prim.GetAuthoredAttributes(); for( const auto &attribute : attributes ) { @@ -952,6 +958,12 @@ ConstObjectPtr USDScene::readAttribute( const SceneInterface::Name &name, double pxr::TfToken value; attr.Get( &value ); return new StringData( value.GetString() ); } +#if PXR_VERSION >= 2111 + else if( name == g_lightAttributeName ) + { + return ShaderAlgo::readShaderNetwork( pxr::UsdLuxLightAPI( m_location->prim ) ); + } +#endif else if( name == g_kindAttributeName ) { pxr::TfToken kind; diff --git a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py index dfb2448f99..6d5d3de58d 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -1890,6 +1890,13 @@ def testCanReferenceTags( self ) : grandChild = child.child( "grandChild" ) self.assertSetNamesEqual( grandChild.readTags(), [ "tagB", "tagC" ] ) + def __expectedLightSets( self ) : + + if pxr.Usd.GetVersion() >= ( 0, 21, 11 ) : + return [ "__lights" ] + else : + return [] + def testTagSetEquivalence( self ) : # Location Tags Sets @@ -1955,7 +1962,7 @@ def checkHasTag( scene ) : self.assertSetNamesEqual( root.readTags( root.AncestorTag ), [] ) self.assertSetNamesEqual( root.readTags( root.LocalTag ), [] ) - self.assertSetNamesEqual( root.readTags( root.DescendantTag ), allTags + [ "__cameras", "usd:pointInstancers" ] ) + self.assertSetNamesEqual( root.readTags( root.DescendantTag ), allTags + [ "__cameras", "usd:pointInstancers" ] + self.__expectedLightSets() ) checkHasTag( root ) a = root.child( "a" ) @@ -2003,7 +2010,7 @@ def testSchemaTypeSetsAndTags( self ) : instancerGroup = group.child( "instancerGroup" ) instancer = instancerGroup.child( "instancer" ) - self.assertSetNamesEqual( root.setNames(), [ "__cameras", "usd:pointInstancers" ] ) + self.assertSetNamesEqual( root.setNames(), [ "__cameras", "usd:pointInstancers" ] + self.__expectedLightSets() ) self.assertSetNamesEqual( group.setNames(), [] ) self.assertSetNamesEqual( camera.setNames(), [] ) self.assertSetNamesEqual( instancerGroup.setNames(), [] ) @@ -2025,7 +2032,7 @@ def testSchemaTypeSetsAndTags( self ) : self.assertSetNamesEqual( root.readTags( root.AncestorTag ), [] ) self.assertSetNamesEqual( root.readTags( root.LocalTag ), [] ) - self.assertSetNamesEqual( root.readTags( root.DescendantTag ), [ "__cameras", "usd:pointInstancers" ] ) + self.assertSetNamesEqual( root.readTags( root.DescendantTag ), [ "__cameras", "usd:pointInstancers" ] + self.__expectedLightSets() ) self.assertSetNamesEqual( group.readTags( root.AncestorTag ), [] ) self.assertSetNamesEqual( group.readTags( root.LocalTag ), [] ) @@ -2967,5 +2974,46 @@ def testExposedShaderInput( self ) : self.assertEqual( network.getOutput(), "surface" ) self.assertEqual( network.getShader( "surface" ).parameters["diffuse_roughness"].value, 0.75 ) + @unittest.skipIf( pxr.Usd.GetVersion() < ( 0, 21, 11 ), "UsdLuxLightAPI not available" ) + def testLightsSet( self ) : + + scene = IECoreScene.SceneInterface.create( + os.path.join( os.path.dirname( __file__ ), "data", "sphereLight.usda" ), + IECore.IndexedIO.OpenMode.Read + ) + + self.assertIn( "__lights", scene.setNames() ) + self.assertEqual( scene.readSet( "__lights" ), IECore.PathMatcher( [ "/SpotLight23" ] ) ) + + @unittest.skipIf( pxr.Usd.GetVersion() < ( 0, 21, 11 ), "UsdLuxLightAPI not available" ) + def testLightAttribute( self ) : + + scene = IECoreScene.SceneInterface.create( + os.path.join( os.path.dirname( __file__ ), "data", "sphereLight.usda" ), + IECore.IndexedIO.OpenMode.Read + ) + light = scene.child( "SpotLight23" ) + self.assertIn( "light", light.attributeNames() ) + self.assertTrue( light.hasAttribute( "light" ) ) + + shader = light.readAttribute( "light", 0 ) + self.assertIsInstance( shader, IECoreScene.ShaderNetwork ) + self.assertEqual( shader.size(), 1 ) + self.assertEqual( shader.getOutput(), "SpotLight23" ) + + self.assertEqual( + shader.getShader( "SpotLight23" ).parameters, + IECore.CompoundData( { + "color" : imath.Color3f( 1, 1, 1 ), + "colorTemperature" : 6500.0, + "enableColorTemperature" : False, + "exposure" : 0.0, + "intensity" : 30000.0, + "radius" : 0.0, + "shaping:cone:angle" : 66.0, + "shaping:cone:softness" : 1.0 + } ) + ) + if __name__ == "__main__": unittest.main() diff --git a/contrib/IECoreUSD/test/IECoreUSD/data/sphereLight.usda b/contrib/IECoreUSD/test/IECoreUSD/data/sphereLight.usda new file mode 100644 index 0000000000..c31f421ee1 --- /dev/null +++ b/contrib/IECoreUSD/test/IECoreUSD/data/sphereLight.usda @@ -0,0 +1,19 @@ +#usda 1.0 + +def SphereLight "SpotLight23" ( + apiSchemas = ["ShapingAPI"] +) +{ + color3f inputs:color = (1, 1, 1) + float inputs:colorTemperature = 6500 + bool inputs:enableColorTemperature = 0 + float inputs:exposure = 0 + float inputs:intensity = 30000 + float inputs:radius = 0 + float inputs:shaping:cone:angle = 66 + float inputs:shaping:cone:softness = 1 + bool treatAsPoint = 1 + token visibility = "inherited" + matrix4d xformOp:transform = ( (0.9672808051109314, -0.21715188026428223, 0.1311977356672287, 0), (-0.05085674673318863, 0.3406679034233093, 0.9388070106506348, 0), (-0.24855859577655792, -0.9147622585296631, 0.3184778690338135, 0), (20949.08203125, 2227.8759765625, 528.5748901367188, 1) ) + uniform token[] xformOpOrder = ["xformOp:transform"] +}