Skip to content

Commit 3d273a2

Browse files
IECoreUSD : Load prototype paths inside a PointInstancer as relative
By default, if an instancer named "/inst" contains an internal prototype path like "/inst/Prototypes/proto", that prototype path will now be loaded as "./Prototypes/proto". You can set the env var GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES=0 to get the old behaviour, where prototype paths were always absolute. Or can set the env var GAFFERSCENE_INSTANCER_EXPLICITABSOLUTEPATHS=1 to get the newest behaviour, where prototype paths are assumed to be relative unless they start with a slash, so the prototype path would be loaded as "Prototypes/proto".
1 parent d4569e5 commit 3d273a2

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

contrib/IECoreUSD/src/IECoreUSD/PointInstancerAlgo.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ using namespace IECoreUSD;
5353
namespace
5454
{
5555

56+
bool checkEnvFlag( const char *envVar, bool def )
57+
{
58+
const char *value = getenv( envVar );
59+
if( value )
60+
{
61+
return std::string( value ) != "0";
62+
}
63+
else
64+
{
65+
return def;
66+
}
67+
68+
}
69+
5670
IECore::ObjectPtr readPointInstancer( pxr::UsdGeomPointInstancer &pointInstancer, pxr::UsdTimeCode time, const Canceller *canceller )
5771
{
5872
pxr::VtVec3fArray pointsData;
@@ -108,16 +122,42 @@ IECore::ObjectPtr readPointInstancer( pxr::UsdGeomPointInstancer &pointInstancer
108122

109123
// Prototype paths
110124

125+
const static bool gafferUSDPointInstancersRelativeProtoypes = checkEnvFlag( "GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES", true );
126+
const static bool gafferSceneInstancerExplicitAbsolutePaths = checkEnvFlag( "GAFFERSCENE_INSTANCER_EXPLICITABSOLUTEPATHS", false );
127+
111128
pxr::SdfPathVector targets;
112129
Canceller::check( canceller );
113130
pointInstancer.GetPrototypesRel().GetForwardedTargets( &targets );
114131

132+
const pxr::SdfPath &primPath = pointInstancer.GetPath();
133+
115134
IECore::StringVectorDataPtr prototypeRootsData = new IECore::StringVectorData();
116135
auto &prototypeRoots = prototypeRootsData->writable();
117136
prototypeRoots.reserve( targets.size() );
118137
for( const auto &t : targets )
119138
{
120-
prototypeRoots.push_back( t.GetString() );
139+
if( !gafferUSDPointInstancersRelativeProtoypes )
140+
{
141+
prototypeRoots.push_back( t.GetString() );
142+
}
143+
else
144+
{
145+
if( t.HasPrefix( primPath ) )
146+
{
147+
if( gafferSceneInstancerExplicitAbsolutePaths )
148+
{
149+
prototypeRoots.push_back( t.MakeRelativePath( primPath ).GetString() );
150+
}
151+
else
152+
{
153+
prototypeRoots.push_back( "./" + t.MakeRelativePath( primPath ).GetString() );
154+
}
155+
}
156+
else
157+
{
158+
prototypeRoots.push_back( t.GetString() );
159+
}
160+
}
121161
}
122162

123163
newPoints->variables["prototypeRoots"] = IECoreScene::PrimitiveVariable( IECoreScene::PrimitiveVariable::Constant, prototypeRootsData );

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4451,6 +4451,37 @@ def testAssetPathSlashes ( self ) :
44514451
self.assertNotIn( "\\", xform.readAttribute( "render:testAsset", 0 ).value )
44524452
self.assertTrue( pathlib.Path( xform.readAttribute( "render:testAsset", 0 ).value ).is_file() )
44534453

4454+
4455+
@unittest.skipIf( os.environ.get("GAFFERSCENE_INSTANCER_EXPLICITABSOLUTEPATHS") == "1" or os.environ.get("GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES") == "0", "GAFFERSCENE_INSTANCER_EXPLICITABSOLUTEPATHS or GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES is set, running alternate test" )
4456+
def testPointInstancerRelative( self ) :
4457+
root = IECoreScene.SceneInterface.create(
4458+
os.path.join( os.path.dirname( __file__ ), "data", "pointInstancerWeirdPrototypes.usda" ),
4459+
IECore.IndexedIO.OpenMode.Read
4460+
)
4461+
pointInstancer = root.child( "inst" )
4462+
obj = pointInstancer.readObject(0.0)
4463+
self.assertEqual( obj["prototypeRoots"].data, IECore.StringVectorData( [ './Prototypes/sphere', '/cube' ] ) )
4464+
4465+
@unittest.skipIf( not os.environ.get("GAFFERSCENE_INSTANCER_EXPLICITABSOLUTEPATHS") == "1" or os.environ.get("GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES") == "0", "Set GAFFERSCENE_INSTANCER_EXPLICITABSOLUTEPATHS and don't disable GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES to test this" )
4466+
def testPointInstancerRelativeNewStyle( self ) :
4467+
root = IECoreScene.SceneInterface.create(
4468+
os.path.join( os.path.dirname( __file__ ), "data", "pointInstancerWeirdPrototypes.usda" ),
4469+
IECore.IndexedIO.OpenMode.Read
4470+
)
4471+
pointInstancer = root.child( "inst" )
4472+
obj = pointInstancer.readObject(0.0)
4473+
self.assertEqual( obj["prototypeRoots"].data, IECore.StringVectorData( [ 'Prototypes/sphere', '/cube' ] ) )
4474+
4475+
@unittest.skipIf( not os.environ.get("GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES") == "0", "Set GAFFERUSD_POINTINSTANCER_RELATIVEPROTOTYPES=0 to test" )
4476+
def testPointInstancerAbsolute( self ) :
4477+
root = IECoreScene.SceneInterface.create(
4478+
os.path.join( os.path.dirname( __file__ ), "data", "pointInstancerWeirdPrototypes.usda" ),
4479+
IECore.IndexedIO.OpenMode.Read
4480+
)
4481+
pointInstancer = root.child( "inst" )
4482+
obj = pointInstancer.readObject(0.0)
4483+
self.assertEqual( obj["prototypeRoots"].data, IECore.StringVectorData( [ '/inst/Prototypes/sphere', '/cube' ] ) )
4484+
44544485
@unittest.skipIf( not haveVDB, "No IECoreVDB" )
44554486
def testUsdVolVolumeSlashes( self ) :
44564487

0 commit comments

Comments
 (0)