@@ -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"
@@ -796,6 +797,7 @@ namespace
796797const IECore::InternedString g_purposeAttributeName ( " usd:purpose" );
797798const IECore::InternedString g_kindAttributeName ( " usd:kind" );
798799const IECore::InternedString g_lightAttributeName ( " light" );
800+ const IECore::InternedString g_doubleSidedAttributeName ( " doubleSided" );
799801
800802} // namespace
801803
@@ -827,6 +829,10 @@ bool USDScene::hasAttribute( const SceneInterface::Name &name ) const
827829 return m_location->prim .HasAPI <pxr::UsdLuxLightAPI>();
828830 }
829831#endif
832+ else if ( name == g_doubleSidedAttributeName )
833+ {
834+ return pxr::UsdGeomGprim ( m_location->prim ).GetDoubleSidedAttr ().HasAuthoredValue ();
835+ }
830836 else if ( auto attribute = AttributeAlgo::findUSDAttribute ( m_location->prim , name.string () ) )
831837 {
832838 return attribute.HasAuthoredValue ();
@@ -882,6 +888,11 @@ void USDScene::attributeNames( SceneInterface::NameList &attrs ) const
882888 }
883889#endif
884890
891+ if ( pxr::UsdGeomGprim ( m_location->prim ).GetDoubleSidedAttr ().HasAuthoredValue () )
892+ {
893+ attrs.push_back ( g_doubleSidedAttributeName );
894+ }
895+
885896 std::vector<pxr::UsdAttribute> attributes = m_location->prim .GetAuthoredAttributes ();
886897 for ( const auto &attribute : attributes )
887898 {
@@ -973,6 +984,16 @@ ConstObjectPtr USDScene::readAttribute( const SceneInterface::Name &name, double
973984 }
974985 return new StringData ( kind.GetString () );
975986 }
987+ else if ( name == g_doubleSidedAttributeName )
988+ {
989+ pxr::UsdAttribute attr = pxr::UsdGeomGprim ( m_location->prim ).GetDoubleSidedAttr ();
990+ bool doubleSided;
991+ if ( attr.HasAuthoredValue () && attr.Get ( &doubleSided, m_root->getTime ( time ) ) )
992+ {
993+ return new BoolData ( doubleSided );
994+ }
995+ return nullptr ;
996+ }
976997 else if ( pxr::UsdAttribute attribute = AttributeAlgo::findUSDAttribute ( m_location->prim , name.string () ) )
977998 {
978999 return DataAlgo::fromUSD ( attribute, m_root->getTime ( time ) );
@@ -1034,6 +1055,28 @@ void USDScene::writeAttribute( const SceneInterface::Name &name, const Object *a
10341055 }
10351056 }
10361057 }
1058+ else if ( name == g_doubleSidedAttributeName )
1059+ {
1060+ if ( auto *data = reportedCast<const BoolData>( attribute, " USDScene::writeAttribute" , name.c_str () ) )
1061+ {
1062+ pxr::UsdGeomGprim gprim ( m_location->prim );
1063+ if ( gprim )
1064+ {
1065+ gprim.GetDoubleSidedAttr ().Set ( data->readable (), m_root->getTime ( time ) );
1066+ }
1067+ else
1068+ {
1069+ // We're hamstrung by the fact that USD considers `doubleSided` to be a property
1070+ // of a Gprim and not an inheritable attribute as it was in RenderMan and is in Cortex.
1071+ // We can't author a Gprim here, because it isn't a concrete type, so we must rely on
1072+ // `writeObject()` having been called first to get a suitable concrete type in place.
1073+ IECore::msg (
1074+ IECore::Msg::Warning, " USDScene::writeAttribute" ,
1075+ boost::format ( " Unable to write attribute \" %1%\" to \" %2%\" , because it is not a Gprim" ) % name % m_location->prim .GetPath ()
1076+ );
1077+ }
1078+ }
1079+ }
10371080 else if ( const IECoreScene::ShaderNetwork *shaderNetwork = runTimeCast<const ShaderNetwork>( attribute ) )
10381081 {
10391082 m_shaders[name] = shaderNetwork;
@@ -1368,6 +1411,13 @@ void USDScene::attributesHash( double time, IECore::MurmurHash &h ) const
13681411 // Kind can not be animated so no need to update `mightBeTimeVarying`.
13691412 }
13701413
1414+ auto doubleSidedAttr = pxr::UsdGeomGprim ( m_location->prim ).GetDoubleSidedAttr ();
1415+ if ( doubleSidedAttr && doubleSidedAttr.HasAuthoredValue () )
1416+ {
1417+ haveAttributes = true ;
1418+ mightBeTimeVarying |= doubleSidedAttr.ValueMightBeTimeVarying ();
1419+ }
1420+
13711421 std::vector<pxr::UsdAttribute> attributes = m_location->prim .GetAuthoredAttributes ();
13721422 for ( const auto &attribute : attributes )
13731423 {
@@ -1456,5 +1506,6 @@ namespace
14561506SceneInterface::FileFormatDescription<USDScene> g_descriptionUSD ( " .usd" , IndexedIO::Read | IndexedIO::Write );
14571507SceneInterface::FileFormatDescription<USDScene> g_descriptionUSDA ( " .usda" , IndexedIO::Read | IndexedIO::Write );
14581508SceneInterface::FileFormatDescription<USDScene> g_descriptionUSDC ( " .usdc" , IndexedIO::Read | IndexedIO::Write );
1509+ SceneInterface::FileFormatDescription<USDScene> g_descriptionUSDZ ( " .usdz" , IndexedIO::Read | IndexedIO::Write );
14591510
14601511} // namespace
0 commit comments