Skip to content

Commit c467938

Browse files
authored
Merge pull request #1260 from johnhaddon/usdDoubleSided
USDScene : Support `doubleSided` attribute
2 parents 366b72f + 1d6bdb8 commit c467938

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ IECORE_PUSH_DEFAULT_VISIBILITY
5656
#include "pxr/usd/usd/stage.h"
5757
#include "pxr/usd/usdGeom/bboxCache.h"
5858
#include "pxr/usd/usdGeom/camera.h"
59+
#include "pxr/usd/usdGeom/gprim.h"
5960
#include "pxr/usd/usdGeom/metrics.h"
6061
#include "pxr/usd/usdGeom/pointInstancer.h"
6162
#include "pxr/usd/usdGeom/primvar.h"
@@ -803,6 +804,7 @@ namespace
803804

804805
const IECore::InternedString g_purposeAttributeName( "usd:purpose" );
805806
const IECore::InternedString g_kindAttributeName( "usd:kind" );
807+
const IECore::InternedString g_doubleSidedAttributeName( "doubleSided" );
806808

807809
} // namespace
808810

@@ -828,6 +830,10 @@ bool USDScene::hasAttribute( const SceneInterface::Name &name ) const
828830
pxr::TfToken kind;
829831
return model.GetKind( &kind );
830832
}
833+
else if( name == g_doubleSidedAttributeName )
834+
{
835+
return pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr().HasAuthoredValue();
836+
}
831837
else if( auto attribute = AttributeAlgo::findUSDAttribute( m_location->prim, name.string() ) )
832838
{
833839
return attribute.HasAuthoredValue();
@@ -876,6 +882,11 @@ void USDScene::attributeNames( SceneInterface::NameList &attrs ) const
876882
attrs.push_back( g_kindAttributeName );
877883
}
878884

885+
if( pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr().HasAuthoredValue() )
886+
{
887+
attrs.push_back( g_doubleSidedAttributeName );
888+
}
889+
879890
std::vector<pxr::UsdAttribute> attributes = m_location->prim.GetAuthoredAttributes();
880891
for( const auto &attribute : attributes )
881892
{
@@ -961,6 +972,16 @@ ConstObjectPtr USDScene::readAttribute( const SceneInterface::Name &name, double
961972
}
962973
return new StringData( kind.GetString() );
963974
}
975+
else if( name == g_doubleSidedAttributeName )
976+
{
977+
pxr::UsdAttribute attr = pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr();
978+
bool doubleSided;
979+
if( attr.HasAuthoredValue() && attr.Get( &doubleSided, m_root->getTime( time ) ) )
980+
{
981+
return new BoolData( doubleSided );
982+
}
983+
return nullptr;
984+
}
964985
else if( pxr::UsdAttribute attribute = AttributeAlgo::findUSDAttribute( m_location->prim, name.string() ) )
965986
{
966987
return DataAlgo::fromUSD( attribute, m_root->getTime( time ) );
@@ -1022,6 +1043,28 @@ void USDScene::writeAttribute( const SceneInterface::Name &name, const Object *a
10221043
}
10231044
}
10241045
}
1046+
else if( name == g_doubleSidedAttributeName )
1047+
{
1048+
if( auto *data = reportedCast<const BoolData>( attribute, "USDScene::writeAttribute", name.c_str() ) )
1049+
{
1050+
pxr::UsdGeomGprim gprim( m_location->prim );
1051+
if( gprim )
1052+
{
1053+
gprim.GetDoubleSidedAttr().Set( data->readable(), m_root->getTime( time ) );
1054+
}
1055+
else
1056+
{
1057+
// We're hamstrung by the fact that USD considers `doubleSided` to be a property
1058+
// of a Gprim and not an inheritable attribute as it was in RenderMan and is in Cortex.
1059+
// We can't author a Gprim here, because it isn't a concrete type, so we must rely on
1060+
// `writeObject()` having been called first to get a suitable concrete type in place.
1061+
IECore::msg(
1062+
IECore::Msg::Warning, "USDScene::writeAttribute",
1063+
boost::format( "Unable to write attribute \"%1%\" to \"%2%\", because it is not a Gprim" ) % name % m_location->prim.GetPath()
1064+
);
1065+
}
1066+
}
1067+
}
10251068
else if( const IECoreScene::ShaderNetwork *shaderNetwork = runTimeCast<const ShaderNetwork>( attribute ) )
10261069
{
10271070
m_shaders[name] = shaderNetwork;
@@ -1356,6 +1399,13 @@ void USDScene::attributesHash( double time, IECore::MurmurHash &h ) const
13561399
// Kind can not be animated so no need to update `mightBeTimeVarying`.
13571400
}
13581401

1402+
auto doubleSidedAttr = pxr::UsdGeomGprim( m_location->prim ).GetDoubleSidedAttr();
1403+
if( doubleSidedAttr && doubleSidedAttr.HasAuthoredValue() )
1404+
{
1405+
haveAttributes = true;
1406+
mightBeTimeVarying |= doubleSidedAttr.ValueMightBeTimeVarying();
1407+
}
1408+
13591409
std::vector<pxr::UsdAttribute> attributes = m_location->prim.GetAuthoredAttributes();
13601410
for( const auto &attribute : attributes )
13611411
{

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2967,5 +2967,85 @@ def testExposedShaderInput( self ) :
29672967
self.assertEqual( network.getOutput(), "surface" )
29682968
self.assertEqual( network.getShader( "surface" ).parameters["diffuse_roughness"].value, 0.75 )
29692969

2970+
def testReadDoubleSidedAttribute( self ) :
2971+
2972+
root = IECoreScene.SceneInterface.create(
2973+
os.path.join( os.path.dirname( __file__ ), "data", "doubleSidedAttribute.usda" ),
2974+
IECore.IndexedIO.OpenMode.Read
2975+
)
2976+
2977+
for name, doubleSided in {
2978+
"sphere" : None,
2979+
"singleSidedSphere" : False,
2980+
"doubleSidedSphere" : True
2981+
}.items() :
2982+
object = root.child( name )
2983+
if doubleSided is None :
2984+
self.assertFalse( object.hasAttribute( "doubleSided" ) )
2985+
self.assertNotIn( "doubleSided", object.attributeNames() )
2986+
else :
2987+
self.assertTrue( object.hasAttribute( "doubleSided" ) )
2988+
self.assertIn( "doubleSided", object.attributeNames() )
2989+
self.assertEqual( object.readAttribute( "doubleSided", 1 ), IECore.BoolData( doubleSided ) )
2990+
2991+
def testWriteDoubleSidedAttribute( self ) :
2992+
2993+
# Write via SceneInterface
2994+
2995+
fileName = os.path.join( self.temporaryDirectory(), "doubleSidedAttribute.usda" )
2996+
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write )
2997+
2998+
toWrite = (
2999+
( "singleSidedSphere", "before", False ),
3000+
( "doubleSidedSphere", "before", True ),
3001+
( "doubleSidedSphereWrittenAfter", "after", True ),
3002+
( "doubleSidedNoObject", "never", True ),
3003+
( "sphere", "before", None ),
3004+
)
3005+
3006+
for name, writeObject, doubleSided in toWrite :
3007+
3008+
child = root.createChild( name )
3009+
if writeObject == "before" :
3010+
child.writeObject( IECoreScene.SpherePrimitive(), 1 )
3011+
3012+
if doubleSided is not None :
3013+
3014+
with IECore.CapturingMessageHandler() as mh :
3015+
child.writeAttribute( "doubleSided", IECore.BoolData( doubleSided ), 1 )
3016+
3017+
if writeObject != "before" :
3018+
self.assertEqual( len( mh.messages ), 1 )
3019+
self.assertEqual(
3020+
mh.messages[0].message,
3021+
'Unable to write attribute "doubleSided" to "/{}", because it is not a Gprim'.format(
3022+
name
3023+
)
3024+
)
3025+
3026+
if writeObject == "after" :
3027+
child.writeObject( IECoreScene.SpherePrimitive(), 1 )
3028+
3029+
del root, child
3030+
3031+
# Verify via USD API
3032+
3033+
stage = pxr.Usd.Stage.Open( fileName )
3034+
3035+
for name, writeObject, doubleSided in toWrite :
3036+
3037+
if writeObject != "before" :
3038+
doubleSided = None
3039+
3040+
if doubleSided is None :
3041+
self.assertFalse(
3042+
pxr.UsdGeom.Gprim( stage.GetPrimAtPath( "/" + name ) ).GetDoubleSidedAttr().HasAuthoredValue(),
3043+
)
3044+
else :
3045+
self.assertEqual(
3046+
pxr.UsdGeom.Gprim( stage.GetPrimAtPath( "/" + name ) ).GetDoubleSidedAttr().Get( 1 ),
3047+
doubleSided
3048+
)
3049+
29703050
if __name__ == "__main__":
29713051
unittest.main()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#usda 1.0
2+
3+
def Sphere "doubleSidedSphere"
4+
{
5+
uniform bool doubleSided = 1
6+
}
7+
8+
def Sphere "singleSidedSphere"
9+
{
10+
uniform bool doubleSided = 0
11+
}
12+
13+
def Sphere "sphere"
14+
{
15+
}
16+

0 commit comments

Comments
 (0)