Skip to content

Commit 2a026fa

Browse files
committed
Merge branch 'RB-10.4' into main
2 parents 09d344b + 6715172 commit 2a026fa

File tree

24 files changed

+992
-103
lines changed

24 files changed

+992
-103
lines changed

Changes

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,31 @@ Breaking Changes
66

77
- Primitive : Changed `variableIndexedView()` return type from `boost::optional` to `std::optional`.
88

9+
10.4.x.x (relative to 10.4.7.0)
10+
========
11+
12+
13+
10.4.7.0 (relative to 10.4.6.0)
14+
========
15+
16+
Improvements
17+
------------
18+
19+
- IECoreGL::PointsPrimitive : Added `renderUsesGLPoints()` method (#1347).
20+
- IECoreGL::CurvesPrimitive : Added `renderUsesGLLines()` method (#1347).
21+
- StringAlgo : Added `concat()` and `toInt()` methods (#1343).
22+
- IECoreScene::ShaderNetworkAlgo (#1343) :
23+
- Added `convertToOSLConventions()`, `expandSplines()` and `collapseSplines()`.
24+
- Deprecated `convertOSLComponentConnections()`, `expandSplineParameters()` and `collapseSplineParameters()`.
25+
- USDScene : Added support for roundtripping connections to SplineData parameters.
26+
27+
Fixes
28+
-----
29+
30+
- IECoreUSD::PrimitiveAlgo (#1346) :
31+
- Fixed reading of primitives containing `primvars:normals`. These are now correctly loaded as a primitive variable called `N`, taking precedence over the UsdGeomPointBased `normals` attribute.
32+
- Fixed writing of indexed normals so that the indexing is retained on load. Note that this means that normals are now _always_ written as `primvars:normals` and never via the UsdGeomPointBased `normals` attribute.
33+
934
10.4.6.0 (relative to 10.4.5.0)
1035
========
1136

SConstruct

Lines changed: 1 addition & 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 = 4 # backwards-incompatible changes
59-
ieCoreMinorVersion = 6 # new backwards-compatible features
59+
ieCoreMinorVersion = 7 # new backwards-compatible features
6060
ieCorePatchVersion = 0 # bug fixes
6161
ieCoreVersionSuffix = "" # used for alpha/beta releases. Example: "a1", "b2", etc.
6262

contrib/IECoreAppleseed/src/IECoreAppleseed/ShaderNetworkAlgo.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,9 @@ namespace ShaderNetworkAlgo
6565

6666
renderer::ShaderGroup *convert( const IECoreScene::ShaderNetwork *shaderNetwork )
6767
{
68-
ShaderNetworkPtr networkCopy;
69-
if( true ) // todo : make conditional on OSL < 1.10
70-
{
71-
networkCopy = shaderNetwork->copy();
72-
IECoreScene::ShaderNetworkAlgo::convertOSLComponentConnections( networkCopy.get() );
73-
shaderNetwork = networkCopy.get();
74-
}
68+
ShaderNetworkPtr networkCopy = shaderNetwork->copy();
69+
IECoreScene::ShaderNetworkAlgo::convertToOSLConventions( networkCopy.get(), 10900 );
70+
shaderNetwork = networkCopy.get();
7571

7672
asf::auto_release_ptr<asr::ShaderGroup> shaderGroup;
7773
shaderGroup = asr::ShaderGroupFactory::create( "shader_group" );
@@ -89,11 +85,7 @@ renderer::ShaderGroup *convert( const IECoreScene::ShaderNetwork *shaderNetwork
8985
shaderType += 4;
9086
}
9187

92-
IECore::ConstCompoundDataPtr expandedParameters = IECoreScene::ShaderNetworkAlgo::expandSplineParameters(
93-
shader->parametersData()
94-
);
95-
96-
asr::ParamArray params( ParameterAlgo::convertShaderParameters( expandedParameters->readable() ) );
88+
asr::ParamArray params( ParameterAlgo::convertShaderParameters( shader->parametersData()->readable() ) );
9789
shaderGroup->add_shader( shaderType, shader->getName().c_str(), handle.c_str(), params );
9890

9991
for( const auto &c : shaderNetwork->inputConnections( handle ) )

contrib/IECoreAppleseed/test/IECoreAppleseed/ShaderNetworkAlgoTest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def testSplines( self ) :
4848

4949
n = IECoreScene.ShaderNetwork(
5050
shaders = {
51-
"test" : IECoreScene.Shader( "test", "test",
51+
"test" : IECoreScene.Shader( "test", "osl:shader",
5252
IECore.CompoundData(
5353
{
5454
"testColorSpline" : IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.linear(), ( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ) ) ) ),

contrib/IECoreUSD/src/IECoreUSD/PrimitiveAlgo.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ void IECoreUSD::PrimitiveAlgo::writePrimitiveVariable( const std::string &name,
9797
writePrimitiveVariable( "st", primitiveVariable, primvarsAPI, time );
9898
return;
9999
}
100+
else if( name == "N" && runTimeCast<const V3fVectorData>( primitiveVariable.data ) )
101+
{
102+
writePrimitiveVariable( "normals", primitiveVariable, primvarsAPI, time );
103+
return;
104+
}
100105

101106
const pxr::SdfValueTypeName valueTypeName = DataAlgo::valueTypeName( primitiveVariable.data.get() );
102107
pxr::UsdGeomPrimvar usdPrimVar = primvarsAPI.CreatePrimvar( pxr::TfToken( name ), valueTypeName );
@@ -121,11 +126,6 @@ void IECoreUSD::PrimitiveAlgo::writePrimitiveVariable( const std::string &name,
121126
{
122127
pointBased.CreatePointsAttr().Set( PrimitiveAlgo::toUSDExpanded( value ), time );
123128
}
124-
else if( name == "N" )
125-
{
126-
pointBased.CreateNormalsAttr().Set( PrimitiveAlgo::toUSDExpanded( value ), time );
127-
pointBased.SetNormalsInterpolation( PrimitiveAlgo::toUSD( value.interpolation ) );
128-
}
129129
else if( name == "velocity" )
130130
{
131131
pointBased.CreateVelocitiesAttr().Set( PrimitiveAlgo::toUSDExpanded( value ), time );
@@ -469,6 +469,23 @@ void IECoreUSD::PrimitiveAlgo::readPrimitiveVariables( const pxr::UsdGeomPrimvar
469469
primitive->variables.erase( it );
470470
}
471471
}
472+
473+
// USD uses "normals" for normals and we use "N".
474+
475+
it = primitive->variables.find( "normals" );
476+
if( it != primitive->variables.end() )
477+
{
478+
if( auto d = runTimeCast<V3fVectorData>( it->second.data ) )
479+
{
480+
// Force the interpretation, since some USD files
481+
// use `vector3f` rather than `normal3f`. I'm looking
482+
// at you, `arnold-usd`.
483+
d->setInterpretation( GeometricData::Normal );
484+
primitive->variables["N"] = it->second;
485+
primitive->variables.erase( it );
486+
}
487+
}
488+
472489
}
473490

474491
void IECoreUSD::PrimitiveAlgo::readPrimitiveVariables( const pxr::UsdGeomPointBased &pointBased, pxr::UsdTimeCode time, IECoreScene::Primitive *primitive, const Canceller *canceller )
@@ -485,9 +502,14 @@ void IECoreUSD::PrimitiveAlgo::readPrimitiveVariables( const pxr::UsdGeomPointBa
485502
}
486503

487504
Canceller::check( canceller );
488-
if( auto n = boost::static_pointer_cast<V3fVectorData>( DataAlgo::fromUSD( pointBased.GetNormalsAttr(), time ) ) )
505+
if( !primitive->variables.count( "N" ) )
489506
{
490-
primitive->variables["N"] = IECoreScene::PrimitiveVariable( PrimitiveAlgo::fromUSD( pointBased.GetNormalsInterpolation() ), n );
507+
// Only load `PointBased::GetNormalsAttr()` if we didn't already load `primvars:normals`.
508+
// From the USD API docs : "If normals and primvars:normals are both specified, the latter has precedence."
509+
if( auto n = boost::static_pointer_cast<V3fVectorData>( DataAlgo::fromUSD( pointBased.GetNormalsAttr(), time ) ) )
510+
{
511+
primitive->variables["N"] = IECoreScene::PrimitiveVariable( PrimitiveAlgo::fromUSD( pointBased.GetNormalsInterpolation() ), n );
512+
}
491513
}
492514
}
493515

contrib/IECoreUSD/src/IECoreUSD/ShaderAlgo.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,6 @@ IECore::InternedString readShaderNetworkWalk( const pxr::SdfPath &anchorPath, co
187187

188188
readAdditionalLightParameters( usdShader.GetPrim(), parameters );
189189

190-
parametersData = boost::const_pointer_cast< IECore::CompoundData >( IECoreScene::ShaderNetworkAlgo::collapseSplineParameters( parametersData ) );
191-
192190
IECoreScene::ShaderPtr newShader = new IECoreScene::Shader( shaderName, shaderType, parametersData );
193191
pxr::VtValue metadataValue;
194192
if( usdShader.GetPrim().GetMetadata( g_adapterLabelToken, &metadataValue ) && metadataValue.Get<bool>() )
@@ -224,6 +222,7 @@ IECoreScene::ShaderNetwork::Parameter readShaderNetworkWalk( const pxr::SdfPath
224222
pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene::ShaderNetwork *shaderNetwork, pxr::UsdPrim shaderContainer )
225223
{
226224
IECoreScene::ShaderNetworkPtr shaderNetworkWithAdapters = shaderNetwork->copy();
225+
IECoreScene::ShaderNetworkAlgo::expandSplines( shaderNetworkWithAdapters.get() );
227226
IECoreScene::ShaderNetworkAlgo::addComponentConnectionAdapters( shaderNetworkWithAdapters.get() );
228227

229228
IECoreScene::ShaderNetwork::Parameter networkOutput = shaderNetworkWithAdapters->getOutput();
@@ -258,11 +257,7 @@ pxr::UsdShadeOutput IECoreUSD::ShaderAlgo::writeShaderNetwork( const IECoreScene
258257
}
259258
usdShader.SetShaderId( pxr::TfToken( typePrefix + shader.second->getName() ) );
260259

261-
262-
IECore::ConstCompoundDataPtr expandedParameters = IECoreScene::ShaderNetworkAlgo::expandSplineParameters(
263-
shader.second->parametersData()
264-
);
265-
for( const auto &p : expandedParameters->readable() )
260+
for( const auto &p : shader.second->parametersData()->readable() )
266261
{
267262
pxr::UsdShadeInput input = usdShader.CreateInput(
268263
toUSDParameterName( p.first ),
@@ -355,6 +350,7 @@ IECoreScene::ShaderNetworkPtr IECoreUSD::ShaderAlgo::readShaderNetwork( const px
355350
result->setOutput( outputHandle );
356351

357352
IECoreScene::ShaderNetworkAlgo::removeComponentConnectionAdapters( result.get() );
353+
IECoreScene::ShaderNetworkAlgo::collapseSplines( result.get() );
358354

359355
return result;
360356
}

contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,7 +1370,9 @@ def testPointBasedPrimvars( self ) :
13701370

13711371
# Make sure we redirect Cortex primitive variables to the correct
13721372
# attributes of UsdGeomPointBased instead of writing them to
1373-
# arbitrary primvars.
1373+
# arbitrary primvars. We don't use the `normals` attribute though,
1374+
# since USD documents `primvars:normals` to take precedence, and
1375+
# it is the only way we can preserve indexed normals.
13741376

13751377
stage = pxr.Usd.Stage.Open( fileName )
13761378
primvarsAPI = pxr.UsdGeom.PrimvarsAPI( stage.GetPrimAtPath( "/test" ) )
@@ -1382,7 +1384,8 @@ def testPointBasedPrimvars( self ) :
13821384

13831385
usdMesh = pxr.UsdGeom.Mesh( stage.GetPrimAtPath( "/test" ) )
13841386
self.assertTrue( usdMesh.GetPointsAttr().HasAuthoredValue() )
1385-
self.assertTrue( usdMesh.GetNormalsAttr().HasAuthoredValue() )
1387+
self.assertFalse( usdMesh.GetNormalsAttr().HasAuthoredValue() )
1388+
self.assertTrue( primvarsAPI.GetPrimvar( "normals" ) )
13861389
self.assertTrue( usdMesh.GetVelocitiesAttr().HasAuthoredValue() )
13871390
if pxr.Usd.GetVersion() >= ( 0, 19, 11 ) :
13881391
self.assertTrue( usdMesh.GetAccelerationsAttr().HasAuthoredValue() )
@@ -2632,6 +2635,12 @@ def testShaders( self ) :
26322635
dest.parameters["a"] = IECore.Color3fData( imath.Color3f( 0.0 ) )
26332636
dest.parameters["b"] = IECore.Color3fData( imath.Color3f( 0.0 ) )
26342637
dest.parameters["c"] = IECore.FloatData( 0.0 )
2638+
dest.parameters["sf"] = IECore.SplineffData( IECore.Splineff( IECore.CubicBasisf.catmullRom(),
2639+
( ( 0, 1 ), ( 10, 2 ), ( 20, 0 ), ( 30, 1 ) )
2640+
) )
2641+
dest.parameters["sc"] = IECore.SplinefColor3fData( IECore.SplinefColor3f( IECore.CubicBasisf.linear(),
2642+
( ( 0, imath.Color3f(1) ), ( 10, imath.Color3f(2) ), ( 20, imath.Color3f(0) ) )
2643+
) )
26352644

26362645
componentConnectionNetwork = IECoreScene.ShaderNetwork()
26372646
componentConnectionNetwork.addShader( "source1", add1 )
@@ -2664,6 +2673,24 @@ def testShaders( self ) :
26642673
) )
26652674
componentConnectionNetwork.setOutput( IECoreScene.ShaderNetwork.Parameter( "dest", "" ) )
26662675

2676+
# Float to spline element connection
2677+
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
2678+
IECoreScene.ShaderNetwork.Parameter( "source1", "out" ),
2679+
IECoreScene.ShaderNetwork.Parameter( "dest", "sf[3].y" )
2680+
) )
2681+
2682+
# Color to spline element connection
2683+
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
2684+
IECoreScene.ShaderNetwork.Parameter( "source3", "out" ),
2685+
IECoreScene.ShaderNetwork.Parameter( "dest", "sc[2].y" )
2686+
) )
2687+
2688+
# Float to spline element component connection
2689+
componentConnectionNetwork.addConnection( IECoreScene.ShaderNetwork.Connection(
2690+
IECoreScene.ShaderNetwork.Parameter( "source1", "out" ),
2691+
IECoreScene.ShaderNetwork.Parameter( "dest", "sc[0].y.g" )
2692+
) )
2693+
26672694
# If we manually create the shaders that are used as adapters for component connections,
26682695
# they should not be automatically removed on import. ( This is implemented using
26692696
# a label for automatically created adapters, stored as blindData in Cortex that is
@@ -3333,5 +3360,51 @@ def testInvalidPrimitiveVariables( self ) :
33333360
del goodCube["uv"]
33343361
self.assertEqual( goodCube, badCube )
33353362

3363+
def testNormalsPrimVar( self ) :
3364+
3365+
root = IECoreScene.SceneInterface.create( os.path.dirname( __file__ ) + "/data/normalsPrimVar.usda", IECore.IndexedIO.OpenMode.Read )
3366+
mesh = root.child( "mesh" ).readObject( 0 )
3367+
3368+
self.assertNotIn( "normals", mesh )
3369+
self.assertIn( "N", mesh )
3370+
self.assertEqual( mesh["N"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.FaceVarying )
3371+
self.assertIsNotNone( mesh["N"].indices )
3372+
3373+
def testNormalsPrimVarBeatsNormalsAttribute( self ) :
3374+
3375+
root = IECoreScene.SceneInterface.create( os.path.dirname( __file__ ) + "/data/normalsAttributeAndPrimVar.usda", IECore.IndexedIO.OpenMode.Read )
3376+
mesh = root.child( "mesh" ).readObject( 0 )
3377+
3378+
self.assertNotIn( "normals", mesh )
3379+
self.assertIn( "N", mesh )
3380+
self.assertEqual( mesh["N"].data, IECore.V3fVectorData( [ imath.V3f( 0, 0, 1 ) ] * 3, IECore.GeometricData.Interpretation.Normal ) )
3381+
self.assertEqual( mesh["N"].interpolation, IECoreScene.PrimitiveVariable.Interpolation.FaceVarying )
3382+
self.assertIsNone( mesh["N"].indices )
3383+
3384+
def testRoundTripIndexedNormals( self ) :
3385+
3386+
mesh = IECoreScene.MeshPrimitive(
3387+
IECore.IntVectorData( [ 3, 3 ] ),
3388+
IECore.IntVectorData( [ 0, 2, 1, 2, 3, 1 ] ),
3389+
"linear",
3390+
IECore.V3fVectorData( [
3391+
imath.V3f( 0, 1, 0 ), imath.V3f( 1, 1, 0 ), imath.V3f( 0, 0, 0 ), imath.V3f( 1, 0, 0 )
3392+
] )
3393+
)
3394+
3395+
mesh["N"] = IECoreScene.PrimitiveVariable(
3396+
IECoreScene.PrimitiveVariable.Interpolation.FaceVarying,
3397+
IECore.V3fVectorData( [ imath.V3f( 0, 0, 1 ) ], IECore.GeometricData.Interpretation.Normal ),
3398+
IECore.IntVectorData( [ 0, 0, 0, 0, 0, 0 ] )
3399+
)
3400+
3401+
fileName = os.path.join( self.temporaryDirectory(), "indexedNormals.usda" )
3402+
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write )
3403+
root.createChild( "mesh" ).writeObject( mesh, 0.0 )
3404+
del root
3405+
3406+
root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read )
3407+
self.assertEqual( root.child( "mesh").readObject( 0.0 ), mesh )
3408+
33363409
if __name__ == "__main__":
33373410
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 Mesh "mesh"
4+
{
5+
int[] faceVertexCounts = [3]
6+
int[] faceVertexIndices = [0, 1, 3]
7+
point3f[] points = [(0, 0, 0), (0, 1, 0), (1, 0, 0)]
8+
normal3f[] primvars:normals = [(0, 0, 1), (0, 0, 1), (0, 0, 1)] (
9+
elementSize = 3
10+
interpolation = "faceVarying"
11+
)
12+
normal3f[] normals = [(0, 0, -1), (0, 0, -1), (0, 0, -1)] (
13+
interpolation = "vertex"
14+
)
15+
uniform token subdivisionScheme = "none"
16+
}

0 commit comments

Comments
 (0)