Skip to content

Commit 69df141

Browse files
committed
USDScene : Fix loading of asset paths containing <UDIM> tokens
1 parent 0844525 commit 69df141

File tree

3 files changed

+127
-4
lines changed

3 files changed

+127
-4
lines changed

contrib/IECoreUSD/src/IECoreUSD/DataAlgo.cpp

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@
3838
#include "IECore/MessageHandler.h"
3939

4040
IECORE_PUSH_DEFAULT_VISIBILITY
41-
#include "pxr/usd/sdf/schema.h"
42-
4341
#include "pxr/base/gf/matrix3f.h"
4442
#include "pxr/base/gf/matrix3d.h"
4543
#include "pxr/base/gf/matrix4f.h"
4644
#include "pxr/base/gf/matrix4d.h"
45+
46+
#include "pxr/usd/sdf/layerUtils.h"
47+
#include "pxr/usd/sdf/schema.h"
4748
IECORE_POP_DEFAULT_VISIBILITY
4849

4950
#include "boost/unordered_map.hpp"
@@ -139,9 +140,46 @@ IECore::DataPtr dataFromArray( const pxr::VtValue &value, GeometricData::Interpr
139140
return d;
140141
}
141142

143+
IECore::DataPtr dataFromSdfAssetPath( const SdfAssetPath &assetPath, const pxr::UsdAttribute *attribute = nullptr )
144+
{
145+
if( assetPath.GetResolvedPath().size() || !assetPath.GetAssetPath().size() || !attribute )
146+
{
147+
return new StringData( assetPath.GetResolvedPath() );
148+
}
149+
150+
// Path resolution failed, for a couple of possible reasons :
151+
//
152+
// - The asset may not exist. In this case we still want to load the source
153+
// asset path so that users can debug the problem.
154+
// - The source path may have contained a `<UDIM>` token, which is not
155+
// understood by ArResolvers. USD defers all UDIM handling to UsdImaging,
156+
// which is of no use to us. We still want to load the source path
157+
// because the `<UDIM>` token will be resolved by the Cortex Renderer.
158+
//
159+
// In both cases, the source path may be relative to the layer in which
160+
// it was authored, which may be buried deep in a complex composition, so
161+
// we need to find that layer and make the path absolute.
162+
163+
SdfLayerHandle layer;
164+
for( const auto &spec : attribute->GetPropertyStack() )
165+
{
166+
if(
167+
spec->HasDefaultValue() ||
168+
spec->GetLayer()->GetNumTimeSamplesForPath( spec->GetPath() )
169+
)
170+
{
171+
return new StringData(
172+
SdfComputeAssetPathRelativeToLayer( spec->GetLayer(), assetPath.GetAssetPath() )
173+
);
174+
}
175+
}
176+
177+
return new StringData();
178+
}
179+
142180
IECore::DataPtr dataFromSdfAssetPath( const pxr::VtValue &value, GeometricData::Interpretation interpretation, bool arrayAccepted )
143181
{
144-
return new StringData( value.Get<SdfAssetPath>().GetResolvedPath() );
182+
return dataFromSdfAssetPath( value.UncheckedGet<SdfAssetPath>() );
145183
}
146184

147185
static const std::map<pxr::TfType, IECore::DataPtr (*)( const pxr::VtValue &, GeometricData::Interpretation, bool )> g_fromVtValueConverters = {
@@ -281,7 +319,15 @@ IECore::DataPtr IECoreUSD::DataAlgo::fromUSD( const pxr::UsdAttribute &attribute
281319
return nullptr;
282320
}
283321

284-
return DataAlgo::fromUSD( value, attribute.GetTypeName(), arrayAccepted );
322+
if( value.IsHolding<SdfAssetPath>() )
323+
{
324+
// Special case to deal with resolution of UDIM textures.
325+
return dataFromSdfAssetPath( value.UncheckedGet<SdfAssetPath>(), &attribute );
326+
}
327+
else
328+
{
329+
return DataAlgo::fromUSD( value, attribute.GetTypeName(), arrayAccepted );
330+
}
285331
}
286332

287333
//////////////////////////////////////////////////////////////////////////

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2955,6 +2955,31 @@ def testAssetAttributes( self ) :
29552955
os.path.normcase( os.path.join( os.path.dirname( __file__ ), "data", "cube.usda" ) )
29562956
)
29572957

2958+
def testTextureParameters( self ) :
2959+
2960+
root = IECoreScene.SceneInterface.create(
2961+
os.path.join( os.path.dirname( __file__ ), "data", "textureParameters.usda" ),
2962+
IECore.IndexedIO.OpenMode.Read
2963+
)
2964+
sphere = root.child( "model" ).child( "sphere" )
2965+
2966+
self.assertEqual( sphere.attributeNames(), [ "surface" ] )
2967+
network = sphere.readAttribute( "surface", 0 )
2968+
2969+
self.assertEqual( network.size(), 4 )
2970+
self.assertEqual(
2971+
os.path.normpath( network.getShader( "relativeTexture" ).parameters["file"].value ),
2972+
os.path.join( os.path.dirname( __file__ ), "myTexture.tx" ),
2973+
)
2974+
self.assertEqual(
2975+
os.path.normpath( network.getShader( "relativeUDIMTexture" ).parameters["file"].value ),
2976+
os.path.join( os.path.dirname( __file__ ), "myTexture.<UDIM>.tx" ),
2977+
)
2978+
self.assertEqual(
2979+
os.path.normpath( network.getShader( "udimTexture" ).parameters["file"].value ),
2980+
os.path.normpath( "/full/path/to/myTexture.<UDIM>.tx" )
2981+
)
2982+
29582983
def testExposedShaderInput( self ) :
29592984

29602985
root = IECoreScene.SceneInterface.create(
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#usda 1.0
2+
3+
def "model"
4+
{
5+
6+
def Sphere "sphere"
7+
{
8+
rel material:binding = </model/materials/textureParameterTest>
9+
}
10+
11+
def Scope "materials"
12+
{
13+
14+
def Material "textureParameterTest"
15+
{
16+
token outputs:surface.connect = </model/materials/textureParameterTest/previewSurface.outputs:surface>
17+
18+
def Shader "previewSurface"
19+
{
20+
uniform token info:id = "UsdPreviewSurface"
21+
color3f inputs:diffuseColor.connect = </model/materials/textureParameterTest/relativeTexture.outputs:rgb>
22+
normal3f inputs:normal.connect = </model/materials/textureParameterTest/relativeUDIMTexture.outputs:rgb>
23+
float inputs:roughness.connect = </model/materials/textureParameterTest/udimTexture.outputs:r>
24+
token outputs:surface
25+
}
26+
27+
def Shader "relativeTexture"
28+
{
29+
uniform token info:id = "UsdUVTexture"
30+
asset inputs:file = @../myTexture.tx@
31+
vector3f outputs:rgb
32+
}
33+
34+
def Shader "relativeUDIMTexture"
35+
{
36+
uniform token info:id = "UsdUVTexture"
37+
asset inputs:file = @../myTexture.<UDIM>.tx@
38+
vector3f outputs:rgb
39+
40+
}
41+
42+
def Shader "udimTexture"
43+
{
44+
uniform token info:id = "UsdUVTexture"
45+
asset inputs:file = @/full/path/to/myTexture.<UDIM>.tx@
46+
float outputs:r
47+
}
48+
}
49+
}
50+
}
51+
52+

0 commit comments

Comments
 (0)