Skip to content

Commit

Permalink
Merge pull request ImageEngine#1260 from johnhaddon/usdDoubleSided
Browse files Browse the repository at this point in the history
USDScene : Support `doubleSided` attribute
  • Loading branch information
johnhaddon authored Apr 26, 2022
2 parents 366b72f + 1d6bdb8 commit c467938
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 0 deletions.
50 changes: 50 additions & 0 deletions contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ IECORE_PUSH_DEFAULT_VISIBILITY
#include "pxr/usd/usd/stage.h"
#include "pxr/usd/usdGeom/bboxCache.h"
#include "pxr/usd/usdGeom/camera.h"
#include "pxr/usd/usdGeom/gprim.h"
#include "pxr/usd/usdGeom/metrics.h"
#include "pxr/usd/usdGeom/pointInstancer.h"
#include "pxr/usd/usdGeom/primvar.h"
Expand Down Expand Up @@ -803,6 +804,7 @@ namespace

const IECore::InternedString g_purposeAttributeName( "usd:purpose" );
const IECore::InternedString g_kindAttributeName( "usd:kind" );
const IECore::InternedString g_doubleSidedAttributeName( "doubleSided" );

} // namespace

Expand All @@ -828,6 +830,10 @@ bool USDScene::hasAttribute( const SceneInterface::Name &name ) const
pxr::TfToken kind;
return model.GetKind( &kind );
}
else if( name == g_doubleSidedAttributeName )
{
return pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr().HasAuthoredValue();
}
else if( auto attribute = AttributeAlgo::findUSDAttribute( m_location->prim, name.string() ) )
{
return attribute.HasAuthoredValue();
Expand Down Expand Up @@ -876,6 +882,11 @@ void USDScene::attributeNames( SceneInterface::NameList &attrs ) const
attrs.push_back( g_kindAttributeName );
}

if( pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr().HasAuthoredValue() )
{
attrs.push_back( g_doubleSidedAttributeName );
}

std::vector<pxr::UsdAttribute> attributes = m_location->prim.GetAuthoredAttributes();
for( const auto &attribute : attributes )
{
Expand Down Expand Up @@ -961,6 +972,16 @@ ConstObjectPtr USDScene::readAttribute( const SceneInterface::Name &name, double
}
return new StringData( kind.GetString() );
}
else if( name == g_doubleSidedAttributeName )
{
pxr::UsdAttribute attr = pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr();
bool doubleSided;
if( attr.HasAuthoredValue() && attr.Get( &doubleSided, m_root->getTime( time ) ) )
{
return new BoolData( doubleSided );
}
return nullptr;
}
else if( pxr::UsdAttribute attribute = AttributeAlgo::findUSDAttribute( m_location->prim, name.string() ) )
{
return DataAlgo::fromUSD( attribute, m_root->getTime( time ) );
Expand Down Expand Up @@ -1022,6 +1043,28 @@ void USDScene::writeAttribute( const SceneInterface::Name &name, const Object *a
}
}
}
else if( name == g_doubleSidedAttributeName )
{
if( auto *data = reportedCast<const BoolData>( attribute, "USDScene::writeAttribute", name.c_str() ) )
{
pxr::UsdGeomGprim gprim( m_location->prim );
if( gprim )
{
gprim.GetDoubleSidedAttr().Set( data->readable(), m_root->getTime( time ) );
}
else
{
// We're hamstrung by the fact that USD considers `doubleSided` to be a property
// of a Gprim and not an inheritable attribute as it was in RenderMan and is in Cortex.
// We can't author a Gprim here, because it isn't a concrete type, so we must rely on
// `writeObject()` having been called first to get a suitable concrete type in place.
IECore::msg(
IECore::Msg::Warning, "USDScene::writeAttribute",
boost::format( "Unable to write attribute \"%1%\" to \"%2%\", because it is not a Gprim" ) % name % m_location->prim.GetPath()
);
}
}
}
else if( const IECoreScene::ShaderNetwork *shaderNetwork = runTimeCast<const ShaderNetwork>( attribute ) )
{
m_shaders[name] = shaderNetwork;
Expand Down Expand Up @@ -1356,6 +1399,13 @@ void USDScene::attributesHash( double time, IECore::MurmurHash &h ) const
// Kind can not be animated so no need to update `mightBeTimeVarying`.
}

auto doubleSidedAttr = pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr();
if( doubleSidedAttr && doubleSidedAttr.HasAuthoredValue() )
{
haveAttributes = true;
mightBeTimeVarying |= doubleSidedAttr.ValueMightBeTimeVarying();
}

std::vector<pxr::UsdAttribute> attributes = m_location->prim.GetAuthoredAttributes();
for( const auto &attribute : attributes )
{
Expand Down
80 changes: 80 additions & 0 deletions contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2967,5 +2967,85 @@ def testExposedShaderInput( self ) :
self.assertEqual( network.getOutput(), "surface" )
self.assertEqual( network.getShader( "surface" ).parameters["diffuse_roughness"].value, 0.75 )

def testReadDoubleSidedAttribute( self ) :

root = IECoreScene.SceneInterface.create(
os.path.join( os.path.dirname( __file__ ), "data", "doubleSidedAttribute.usda" ),
IECore.IndexedIO.OpenMode.Read
)

for name, doubleSided in {
"sphere" : None,
"singleSidedSphere" : False,
"doubleSidedSphere" : True
}.items() :
object = root.child( name )
if doubleSided is None :
self.assertFalse( object.hasAttribute( "doubleSided" ) )
self.assertNotIn( "doubleSided", object.attributeNames() )
else :
self.assertTrue( object.hasAttribute( "doubleSided" ) )
self.assertIn( "doubleSided", object.attributeNames() )
self.assertEqual( object.readAttribute( "doubleSided", 1 ), IECore.BoolData( doubleSided ) )

def testWriteDoubleSidedAttribute( self ) :

# Write via SceneInterface

fileName = os.path.join( self.temporaryDirectory(), "doubleSidedAttribute.usda" )
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write )

toWrite = (
( "singleSidedSphere", "before", False ),
( "doubleSidedSphere", "before", True ),
( "doubleSidedSphereWrittenAfter", "after", True ),
( "doubleSidedNoObject", "never", True ),
( "sphere", "before", None ),
)

for name, writeObject, doubleSided in toWrite :

child = root.createChild( name )
if writeObject == "before" :
child.writeObject( IECoreScene.SpherePrimitive(), 1 )

if doubleSided is not None :

with IECore.CapturingMessageHandler() as mh :
child.writeAttribute( "doubleSided", IECore.BoolData( doubleSided ), 1 )

if writeObject != "before" :
self.assertEqual( len( mh.messages ), 1 )
self.assertEqual(
mh.messages[0].message,
'Unable to write attribute "doubleSided" to "/{}", because it is not a Gprim'.format(
name
)
)

if writeObject == "after" :
child.writeObject( IECoreScene.SpherePrimitive(), 1 )

del root, child

# Verify via USD API

stage = pxr.Usd.Stage.Open( fileName )

for name, writeObject, doubleSided in toWrite :

if writeObject != "before" :
doubleSided = None

if doubleSided is None :
self.assertFalse(
pxr.UsdGeom.Gprim( stage.GetPrimAtPath( "/" + name ) ).GetDoubleSidedAttr().HasAuthoredValue(),
)
else :
self.assertEqual(
pxr.UsdGeom.Gprim( stage.GetPrimAtPath( "/" + name ) ).GetDoubleSidedAttr().Get( 1 ),
doubleSided
)

if __name__ == "__main__":
unittest.main()
16 changes: 16 additions & 0 deletions contrib/IECoreUSD/test/IECoreUSD/data/doubleSidedAttribute.usda
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#usda 1.0

def Sphere "doubleSidedSphere"
{
uniform bool doubleSided = 1
}

def Sphere "singleSidedSphere"
{
uniform bool doubleSided = 0
}

def Sphere "sphere"
{
}

0 comments on commit c467938

Please sign in to comment.