Skip to content

Commit aae1162

Browse files
committed
Merge branch 'RB-10.5' into main
2 parents 0d8c169 + e6d4406 commit aae1162

27 files changed

+662
-104
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
buildType: RELEASE
4444
containerImage: ghcr.io/gafferhq/build/build:2.0.0
4545
options: .github/workflows/main/options.posix
46-
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/6.0.0/gafferDependencies-6.0.0-linux.tar.gz
46+
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/7.0.0/gafferDependencies-7.0.0-linux.tar.gz
4747
tests: testCore testCorePython testScene testImage testAlembic testUSD testVDB
4848
publish: true
4949

@@ -52,23 +52,23 @@ jobs:
5252
buildType: DEBUG
5353
containerImage: ghcr.io/gafferhq/build/build:2.0.0
5454
options: .github/workflows/main/options.posix
55-
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/6.0.0/gafferDependencies-6.0.0-linux.tar.gz
55+
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/7.0.0/gafferDependencies-7.0.0-linux.tar.gz
5656
tests: testCore testCorePython testScene testImage testAlembic testUSD testVDB
5757
publish: false
5858

5959
- name: windows-python3
6060
os: windows-2019
6161
buildType: RELEASE
6262
options: .github/workflows/main/options.windows
63-
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/6.0.0/gafferDependencies-6.0.0-windows.zip
63+
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/7.0.0/gafferDependencies-7.0.0-windows.zip
6464
tests: testCore testCorePython testScene testImage testAlembic testUSD testVDB
6565
publish: true
6666

6767
- name: windows-python3-debug
6868
os: windows-2019
6969
buildType: RELWITHDEBINFO
7070
options: .github/workflows/main/options.windows
71-
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/6.0.0/gafferDependencies-6.0.0-windows.zip
71+
dependenciesURL: https://github.com/GafferHQ/dependencies/releases/download/7.0.0/gafferDependencies-7.0.0-windows.zip
7272
tests: testCore testCorePython testScene testImage testAlembic testUSD testVDB
7373
publish: false
7474

Changes

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
10.5.x.x (relative to 10.5.0.0)
1+
10.5.x.x (relative to 10.5.1.0)
22
========
33

4+
5+
10.5.1.0 (relative to 10.5.0.0)
6+
========
7+
8+
Improvements
9+
------------
10+
11+
- USDScene : Added limited support for reading and writing `Volume` prims via `IECoreVDB::VDBObject`.
12+
413
Fixes
514
-----
615

16+
- USDScene : Fixed writing of lights so they are represented as appropriate `UsdLux*Light` prims in USD.
717
- FrameRange : Prevented creation of FrameRanges with negative steps
818
- IECore.dataTypeFromElement : Fixed support for list to Vector conversions
919
- LinkedScene : Fixed bug where `linkLocations` attribute was baked incorrectly if the link target location wasn't the ROOT

SConstruct

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ SConsignFile()
5656

5757
ieCoreMilestoneVersion = 10 # for announcing major milestones - may contain all of the below
5858
ieCoreMajorVersion = 5 # backwards-incompatible changes
59-
ieCoreMinorVersion = 0 # new backwards-compatible features
59+
ieCoreMinorVersion = 1 # new backwards-compatible features
6060
ieCorePatchVersion = 0 # bug fixes
6161
ieCoreVersionSuffix = "" # used for alpha/beta releases. Example: "a1", "b2", etc.
6262

@@ -3041,6 +3041,18 @@ if doConfigure :
30413041
]
30423042
)
30433043

3044+
if haveVDB :
3045+
usdEnv.Append(
3046+
LIBS = [
3047+
os.path.basename( vdbEnv.subst( "$INSTALL_LIB_NAME" ) ),
3048+
"${USD_LIB_PREFIX}usdVol",
3049+
vdbEnv.subst( "openvdb" + env["VDB_LIB_SUFFIX"] )
3050+
],
3051+
CPPDEFINES = [ "IECOREUSD_WITH_OPENVDB" ]
3052+
)
3053+
else :
3054+
usdSources = [ f for f in usdSources if os.path.basename( f ) != "VolumeAlgo.cpp" ]
3055+
30443056
# library
30453057
usdLibrary = usdEnv.SharedLibrary( "lib/" + os.path.basename( usdEnv.subst( "$INSTALL_USDLIB_NAME" ) ), usdSources )
30463058
usdLibraryInstall = usdEnv.Install( os.path.dirname( usdEnv.subst( "$INSTALL_USDLIB_NAME" ) ), usdLibrary )

contrib/IECoreUSD/include/IECoreUSD/ShaderAlgo.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,13 @@ namespace ShaderAlgo
5757
IECOREUSD_API pxr::UsdShadeOutput writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer );
5858

5959
/// Reads a ShaderNetwork from a material output, typically obtained from `UsdShadeMaterial::GetOutput()`.
60-
IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdShadeOutput &output );
60+
IECOREUSD_API IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdShadeOutput &output );
6161

6262
#if PXR_VERSION >= 2111
63+
/// Writes a UsdLuxLight from a shader network.
64+
IECOREUSD_API void writeLight( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim prim );
6365
/// Reads a ShaderNetwork from a light.
64-
IECoreScene::ShaderNetworkPtr readShaderNetwork( const pxr::UsdLuxLightAPI &light );
66+
IECOREUSD_API IECoreScene::ShaderNetworkPtr readLight( const pxr::UsdLuxLightAPI &light );
6567
#endif
6668

6769
} // namespace ShaderAlgo

contrib/IECoreUSD/python/IECoreUSD/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@
3232
#
3333
##########################################################################
3434

35+
# In the ImageEngine env, if _IECoreUSD is imported before these pxr modules,
36+
# we get a weird exception when we later load the pxr modules. We're not
37+
# 100% sure why this is happening, but importing them first isn't
38+
# unreasonable.
39+
__import__( "pxr.Kind" )
40+
__import__( "pxr.Vt" )
41+
__import__( "pxr.Sdf" )
42+
3543
from ._IECoreUSD import *
3644

3745
__import__( "IECore" ).loadConfig( "CORTEX_STARTUP_PATHS", subdirectory = "IECoreUSD" )

contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp

Lines changed: 159 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@
4343

4444
#if PXR_VERSION >= 2111
4545
#include "pxr/usd/usdLux/cylinderLight.h"
46+
#include "pxr/usd/usdLux/nonboundableLightBase.h"
4647
#include "pxr/usd/usdLux/sphereLight.h"
48+
49+
#include "pxr/usd/usd/schemaRegistry.h"
4750
#endif
4851

4952
#include "boost/algorithm/string/replace.hpp"
@@ -217,87 +220,89 @@ IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath
217220
}
218221
}
219222

220-
} // namespace
221-
222-
pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer )
223+
IECoreScene::ConstShaderNetworkPtr adaptShaderNetworkForWriting( const IECoreScene::ShaderNetwork *shaderNetwork )
223224
{
224-
IECoreScene::ShaderNetworkPtr shaderNetworkWithAdapters = shaderNetwork->copy();
225-
IECoreScene::ShaderNetworkAlgo::expandSplines( shaderNetworkWithAdapters.get() );
226-
IECoreScene::ShaderNetworkAlgo::addComponentConnectionAdapters( shaderNetworkWithAdapters.get() );
225+
IECoreScene::ShaderNetworkPtr result = shaderNetwork->copy();
226+
IECoreScene::ShaderNetworkAlgo::expandSplines( result.get() );
227+
IECoreScene::ShaderNetworkAlgo::addComponentConnectionAdapters( result.get() );
228+
return result;
229+
}
227230

228-
IECoreScene::ShaderNetwork::Parameter networkOutput = shaderNetworkWithAdapters->getOutput();
229-
if( networkOutput.shader.string() == "" )
231+
pxr::UsdShadeConnectableAPI createShaderPrim( const IECoreScene::Shader *shader, const pxr::UsdStagePtr &stage, const pxr::SdfPath &path )
232+
{
233+
pxr::UsdShadeShader usdShader = pxr::UsdShadeShader::Define( stage, path );
234+
if( !usdShader )
230235
{
231-
// This could theoretically happen, but a shader network with no output is not useful in any way
232-
IECore::msg(
233-
IECore::Msg::Warning, "IECoreUSD::ShaderAlgo::writeShaderNetwork",
234-
"No output shader in network"
235-
);
236+
throw IECore::Exception( "Could not create shader at " + path.GetAsString() );
236237
}
237-
238-
pxr::UsdShadeOutput networkOutUsd;
239-
for( const auto &shader : shaderNetworkWithAdapters->shaders() )
238+
const std::string type = shader->getType();
239+
std::string typePrefix;
240+
size_t typeColonPos = type.find( ":" );
241+
if( typeColonPos != std::string::npos )
240242
{
241-
pxr::SdfPath usdShaderPath = shaderContainer.GetPath().AppendChild( pxr::TfToken( pxr::TfMakeValidIdentifier( shader.first.string() ) ) );
242-
pxr::UsdShadeShader usdShader = pxr::UsdShadeShader::Define( shaderContainer.GetStage(), usdShaderPath );
243-
if( !usdShader )
243+
typePrefix = type.substr( 0, typeColonPos ) + ":";
244+
if( typePrefix == "ai:" )
244245
{
245-
throw IECore::Exception( "Could not create shader at: " + shaderContainer.GetPath().GetString() + " / " + shader.first.string() );
246-
}
247-
std::string type = shader.second->getType();
248-
std::string typePrefix;
249-
size_t typeColonPos = type.find( ":" );
250-
if( typeColonPos != std::string::npos )
251-
{
252-
typePrefix = type.substr( 0, typeColonPos ) + ":";
253-
if( typePrefix == "ai:" )
254-
{
255-
typePrefix = "arnold:";
256-
}
246+
typePrefix = "arnold:";
257247
}
258-
usdShader.SetShaderId( pxr::TfToken( typePrefix + shader.second->getName() ) );
248+
}
249+
usdShader.SetShaderId( pxr::TfToken( typePrefix + shader->getName() ) );
250+
251+
return usdShader.ConnectableAPI();
252+
}
259253

260-
for( const auto &p : shader.second->parametersData()->readable() )
254+
void writeShaderParameterValues( const IECoreScene::Shader *shader, pxr::UsdShadeConnectableAPI usdShader )
255+
{
256+
for( const auto &p : shader->parametersData()->readable() )
257+
{
258+
const pxr::TfToken usdParameterName = toUSDParameterName( p.first );
259+
pxr::UsdShadeInput input = usdShader.GetInput( usdParameterName );
260+
if( !input )
261261
{
262-
pxr::UsdShadeInput input = usdShader.CreateInput(
262+
input = usdShader.CreateInput(
263263
toUSDParameterName( p.first ),
264-
DataAlgo::valueTypeName( p.second.get() )
264+
IECoreUSD::DataAlgo::valueTypeName( p.second.get() )
265265
);
266-
input.Set( DataAlgo::toUSD( p.second.get() ) );
267266
}
268-
269-
if( networkOutput.shader == shader.first )
267+
if( auto *s = IECore::runTimeCast<IECore::StringData>( p.second.get() ) )
270268
{
271-
pxr::TfToken outName( networkOutput.name.string() );
272-
if( outName.GetString().size() == 0 )
269+
// USD has several "stringy" types - convert if necessary.
270+
if( input.GetTypeName() == pxr::SdfValueTypeNames->Token )
273271
{
274-
outName = pxr::TfToken( "DEFAULT_OUTPUT" );
272+
input.Set( pxr::TfToken( s->readable() ) );
273+
continue;
274+
}
275+
else if( input.GetTypeName().GetType().IsA<pxr::SdfAssetPath>() )
276+
{
277+
input.Set( pxr::SdfAssetPath( s->readable() ) );
278+
continue;
275279
}
276-
277-
// \todo - we should probably be correctly tracking the output type if it is typed?
278-
// Currently, we don't really track output types in Gaffer.
279-
networkOutUsd = usdShader.CreateOutput( outName, pxr::SdfValueTypeNames->Token );
280280
}
281+
input.Set( IECoreUSD::DataAlgo::toUSD( p.second.get() ) );
282+
}
281283

282-
const IECore::BoolData* adapterMeta = shader.second->blindData()->member<IECore::BoolData>( IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel() );
283-
if( adapterMeta && adapterMeta->readable() )
284-
{
285-
usdShader.GetPrim().SetMetadata( g_adapterLabelToken, true );
286-
}
284+
const IECore::BoolData *adapterMeta = shader->blindData()->member<IECore::BoolData>( IECoreScene::ShaderNetworkAlgo::componentConnectionAdapterLabel() );
285+
if( adapterMeta && adapterMeta->readable() )
286+
{
287+
usdShader.GetPrim().SetMetadata( g_adapterLabelToken, true );
287288
}
289+
}
288290

289-
for( const auto &shader : shaderNetworkWithAdapters->shaders() )
291+
using ShaderMap = std::unordered_map<IECore::InternedString, pxr::UsdShadeConnectableAPI>;
292+
void writeShaderConnections( const IECoreScene::ShaderNetwork *shaderNetwork, const ShaderMap &usdShaders )
293+
{
294+
for( const auto &shader : shaderNetwork->shaders() )
290295
{
291-
pxr::UsdShadeShader usdShader = pxr::UsdShadeShader::Get( shaderContainer.GetStage(), shaderContainer.GetPath().AppendChild( pxr::TfToken( pxr::TfMakeValidIdentifier( shader.first.string() ) ) ) );
292-
for( const auto &c : shaderNetworkWithAdapters->inputConnections( shader.first ) )
296+
pxr::UsdShadeConnectableAPI usdShader = usdShaders.at( shader.first );
297+
for( const auto &c : shaderNetwork->inputConnections( shader.first ) )
293298
{
294299
pxr::UsdShadeInput dest = usdShader.GetInput( pxr::TfToken( c.destination.name.string() ) );
295-
if( ! dest.GetPrim().IsValid() )
300+
if( !dest )
296301
{
297302
dest = usdShader.CreateInput( toUSDParameterName( c.destination.name ), pxr::SdfValueTypeNames->Token );
298303
}
299304

300-
pxr::UsdShadeShader sourceUsdShader = pxr::UsdShadeShader::Get( shaderContainer.GetStage(), shaderContainer.GetPath().AppendChild( pxr::TfToken( pxr::TfMakeValidIdentifier( c.source.shader.string() ) ) ) );
305+
pxr::UsdShadeShader sourceUsdShader = usdShaders.at( c.source.shader );
301306
std::string sourceOutputName = c.source.name.string();
302307
if( sourceOutputName.size() == 0 )
303308
{
@@ -306,9 +311,51 @@ pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene
306311
pxr::UsdShadeOutput source = sourceUsdShader.CreateOutput( pxr::TfToken( sourceOutputName ), dest.GetTypeName() );
307312
dest.ConnectToSource( source );
308313
}
314+
}
315+
}
316+
317+
} // namespace
318+
319+
pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer )
320+
{
321+
IECoreScene::ConstShaderNetworkPtr adaptedNetwork = adaptShaderNetworkForWriting( shaderNetwork );
322+
shaderNetwork = adaptedNetwork.get();
309323

324+
IECoreScene::ShaderNetwork::Parameter networkOutput = shaderNetwork->getOutput();
325+
if( networkOutput.shader.string() == "" )
326+
{
327+
// This could theoretically happen, but a shader network with no output is not useful in any way
328+
IECore::msg(
329+
IECore::Msg::Warning, "IECoreUSD::ShaderAlgo::writeShaderNetwork",
330+
"No output shader in network"
331+
);
332+
}
333+
334+
ShaderMap usdShaders;
335+
pxr::UsdShadeOutput networkOutUsd;
336+
for( const auto &shader : shaderNetwork->shaders() )
337+
{
338+
const pxr::SdfPath usdShaderPath = shaderContainer.GetPath().AppendChild( pxr::TfToken( pxr::TfMakeValidIdentifier( shader.first.string() ) ) );
339+
pxr::UsdShadeConnectableAPI usdShader = createShaderPrim( shader.second.get(), shaderContainer.GetStage(), usdShaderPath );
340+
writeShaderParameterValues( shader.second.get(), usdShader );
341+
usdShaders[shader.first] = usdShader;
342+
343+
if( networkOutput.shader == shader.first )
344+
{
345+
pxr::TfToken outName( networkOutput.name.string() );
346+
if( outName.GetString().size() == 0 )
347+
{
348+
outName = pxr::TfToken( "DEFAULT_OUTPUT" );
349+
}
350+
351+
// \todo - we should probably be correctly tracking the output type if it is typed?
352+
// Currently, we don't really track output types in Gaffer.
353+
networkOutUsd = usdShader.CreateOutput( outName, pxr::SdfValueTypeNames->Token );
354+
}
310355
}
311356

357+
writeShaderConnections( shaderNetwork, usdShaders );
358+
312359
return networkOutUsd;
313360
}
314361

@@ -357,7 +404,63 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px
357404

358405
#if PXR_VERSION >= 2111
359406

360-
IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const pxr::UsdLuxLightAPI &light )
407+
// This is very similar to `writeShaderNetwork` but with these key differences :
408+
//
409+
// - The output shader is written as a UsdLight-derived prim rather than a UsdShadeShader.
410+
// - The other shaders are parented inside the light.
411+
// - We don't need to create a UsdShadeOutput to return.
412+
void IECoreUSD::ShaderAlgo::writeLight( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim prim )
413+
{
414+
IECoreScene::ConstShaderNetworkPtr adaptedNetwork = adaptShaderNetworkForWriting( shaderNetwork );
415+
shaderNetwork = adaptedNetwork.get();
416+
417+
// Verify that the light shader corresponds to a valid USD light type.
418+
419+
const IECoreScene::Shader *outputShader = shaderNetwork->outputShader();
420+
if( !outputShader )
421+
{
422+
IECore::msg( IECore::Msg::Warning, "ShaderAlgo::writeLight", "No output shader" );
423+
return;
424+
}
425+
426+
pxr::TfType type = pxr::UsdSchemaRegistry::GetInstance().GetTypeFromName( pxr::TfToken( outputShader->getName() ) );
427+
if(
428+
!type.IsA<pxr::UsdLuxBoundableLightBase>() &&
429+
!type.IsA<pxr::UsdLuxNonboundableLightBase>()
430+
)
431+
{
432+
IECore::msg( IECore::Msg::Warning, "ShaderAlgo::writeLight", boost::format( "Shader `%1%` is not a valid UsdLux light type" ) % outputShader->getName() );
433+
return;
434+
}
435+
436+
// Write the light itself onto the prim we've been given.
437+
438+
ShaderMap usdShaders;
439+
prim.SetTypeName( pxr::TfToken( outputShader->getName() ) );
440+
writeShaderParameterValues( outputShader, pxr::UsdShadeConnectableAPI( prim ) );
441+
usdShaders[shaderNetwork->getOutput().shader] = pxr::UsdShadeConnectableAPI( prim );
442+
443+
// Then write any other shaders as child prims so they are
444+
// encapsulated within the light.
445+
446+
for( const auto &shader : shaderNetwork->shaders() )
447+
{
448+
if( shader.second == outputShader )
449+
{
450+
continue;
451+
}
452+
const pxr::SdfPath usdShaderPath = prim.GetPath().AppendChild( pxr::TfToken( pxr::TfMakeValidIdentifier( shader.first.string() ) ) );
453+
pxr::UsdShadeConnectableAPI usdShader = createShaderPrim( shader.second.get(), prim.GetStage(), usdShaderPath );
454+
writeShaderParameterValues( shader.second.get(), usdShader );
455+
usdShaders[shader.first] = usdShader;
456+
}
457+
458+
// Finally, connect everything up.
459+
460+
writeShaderConnections( shaderNetwork, usdShaders );
461+
}
462+
463+
IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readLight( const pxr::UsdLuxLightAPI &light )
361464
{
362465
IECoreScene::ShaderNetworkPtr result = new IECoreScene::ShaderNetwork();
363466
IECoreScene::ShaderNetwork::Parameter lightHandle = readShaderNetworkWalk( light.GetPath().GetParentPath(), pxr::UsdShadeConnectableAPI( light ), *result );

0 commit comments

Comments
 (0)