Skip to content

Commit 0968d9a

Browse files
authored
Merge pull request #1543 from johnhaddon/renderManAttributesFix
IECoreUSD : Conform writing of `ri:` attributes to match `usdRiPxr`
2 parents 0225ead + 5e2f322 commit 0968d9a

3 files changed

Lines changed: 70 additions & 3 deletions

File tree

‎Changes‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
10.6.x.x (relative to 10.6.6.0)
22
========
33

4+
Improvements
5+
------------
46

7+
- USDScene : Added `IECOREUSD_WRITE_CONFORMANT_RENDERMAN_ATTRIBUTES` environment variable. If set to a value of `1`, this causes "ri:" prefixed attributes to be written as expected by `usdRiPxr`.
58

69
10.6.6.0 (relative to 10.6.5.0)
710
========

‎contrib/IECoreUSD/src/IECoreUSD/AttributeAlgo.cpp‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,19 @@ static const pxr::TfToken g_cortexPrimitiveVariableMetadataTokenDeprecated( "IEC
5555
static const std::string g_primVarPrefix = "primvars:";
5656
static const std::string g_primVarUserPrefix = "primvars:user:";
5757
static const std::string g_renderPrefix = "render:";
58+
static const std::string g_riPrefix = "ri:";
59+
static const std::string g_riAttributesPrefix = "ri:attributes:";
5860
static const std::string g_userPrefix = "user:";
5961

62+
bool writeConformantRenderManAttributes()
63+
{
64+
if( const char *e = getenv( "IECOREUSD_WRITE_CONFORMANT_RENDERMAN_ATTRIBUTES" ) )
65+
{
66+
return strcmp( e, "0" );
67+
}
68+
return false;
69+
}
70+
6071
}
6172

6273
bool IECoreUSD::AttributeAlgo::isCortexAttribute( const pxr::UsdGeomPrimvar &primVar )
@@ -122,12 +133,19 @@ pxr::TfToken IECoreUSD::AttributeAlgo::cortexPrimitiveVariableMetadataTokenDepre
122133

123134
IECoreUSD::AttributeAlgo::Name IECoreUSD::AttributeAlgo::nameToUSD( std::string name )
124135
{
136+
if( boost::starts_with( name, g_riPrefix ) && writeConformantRenderManAttributes() )
137+
{
138+
return { pxr::TfToken( g_riAttributesPrefix + name.substr( g_riPrefix.size() ) ), true };
139+
}
140+
125141
bool isPrimvar = false;
126142

127143
// The long term plan is to convert only "render:" prefixed attributes to primvars, and it will
128144
// be the client's responsibility to ensure everything important gets prefixed with "render:".
129145
// But for the moment, Gaffer doesn't do this yet, so we support the two most important prefixes
130-
// for Gaffer currently: "user:" and "ai:"
146+
// for Gaffer currently: "user:" and "ai:".
147+
/// \todo I don't think the `render:` plan is working out - it may well be better to just map
148+
/// all Cortex attributes to primvars.
131149
if( boost::starts_with( name, "render:" ) || boost::starts_with( name, "user:" ) || boost::starts_with( name, "ai:" ) )
132150
{
133151
isPrimvar = true;
@@ -170,7 +188,12 @@ IECoreUSD::AttributeAlgo::Name IECoreUSD::AttributeAlgo::nameToUSD( std::string
170188
IECore::InternedString IECoreUSD::AttributeAlgo::nameFromUSD( IECoreUSD::AttributeAlgo::Name name )
171189
{
172190
std::string nameStr = name.name;
173-
if( nameStr == "arnold:displacement" )
191+
192+
if( boost::starts_with( nameStr, g_riAttributesPrefix ) )
193+
{
194+
return g_riPrefix + nameStr.substr( g_riAttributesPrefix.size() );
195+
}
196+
else if( nameStr == "arnold:displacement" )
174197
{
175198
// Special case where the whole name is different, not just prefix
176199
nameStr = "ai:disp_map";
@@ -198,7 +221,9 @@ IECore::InternedString IECoreUSD::AttributeAlgo::nameFromUSD( IECoreUSD::Attribu
198221

199222
// The long term plan is to always prefix primitive variables converted to attributes with "render:".
200223
// But for the moment, Gaffer doesn't support this, so we skip the prefix for the two most important prefixes
201-
// for Gaffer currently: "user:" and "ai:"
224+
// for Gaffer currently: "user:" and "ai:".
225+
/// \todo I don't think the `render:` plan is working out - it may well be better to just map
226+
/// all Cortex attributes to primvars.
202227
if ( !boost::starts_with( nameStr, g_userPrefix ) && !boost::starts_with( nameStr, "ai:" ) && name.isPrimvar )
203228
{
204229
nameStr = "render:" + nameStr;

‎contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4868,5 +4868,44 @@ def testOSLShaderForHDPrman( self ) :
48684868
self.assertEqual( loadedShaderNetwork.getShader( "scale" ).name, "floatAttribute" )
48694869
self.assertEqual( loadedShaderNetwork.getShader( "scale" ).type, "osl:shader" )
48704870

4871+
def testRenderManAttributeRoundTrip( self ) :
4872+
4873+
self.addCleanup( os.environ.__delitem__, "IECOREUSD_WRITE_CONFORMANT_RENDERMAN_ATTRIBUTES" )
4874+
4875+
for conformant in True, False :
4876+
4877+
with self.subTest( conformant = conformant ) :
4878+
4879+
os.environ["IECOREUSD_WRITE_CONFORMANT_RENDERMAN_ATTRIBUTES"] = str( int( conformant ) )
4880+
4881+
fileName = os.path.join( self.temporaryDirectory(), f"renderManAttributes{conformant}.usda" )
4882+
4883+
# Test writing to USD.
4884+
4885+
scene = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write )
4886+
child = scene.createChild( "test" )
4887+
child.writeAttribute( "ri:trace:maxdiffusedepth", IECore.IntData( 2 ), 0 )
4888+
del scene, child
4889+
4890+
stage = pxr.Usd.Stage.Open( fileName )
4891+
4892+
if conformant :
4893+
primVars = pxr.UsdGeom.PrimvarsAPI( stage.GetPrimAtPath( "/test" ) )
4894+
diffuseDepth = primVars.GetPrimvar( "ri:attributes:trace:maxdiffusedepth" )
4895+
self.assertTrue( diffuseDepth.IsDefined() )
4896+
self.assertEqual( diffuseDepth.GetInterpolation(), "constant" )
4897+
self.assertTrue( diffuseDepth.HasAuthoredValue() )
4898+
self.assertTrue( diffuseDepth.Get( 0 ), 2 )
4899+
else :
4900+
diffuseDepth = stage.GetPrimAtPath( "/test" ).GetAttribute( "ri:trace:maxdiffusedepth" )
4901+
self.assertEqual( diffuseDepth.Get( 0 ), 2 )
4902+
4903+
# Test loading back to Cortex.
4904+
4905+
scene = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )
4906+
child = scene.child( "test" )
4907+
self.assertEqual( child.attributeNames(), [ "ri:trace:maxdiffusedepth" ] )
4908+
self.assertEqual( child.readAttribute( "ri:trace:maxdiffusedepth", 0 ), IECore.IntData( 2 ) )
4909+
48714910
if __name__ == "__main__":
48724911
unittest.main()

0 commit comments

Comments
 (0)