diff --git a/Changes.md b/Changes.md index 4c819e4b818..2cfca36eddb 100644 --- a/Changes.md +++ b/Changes.md @@ -36,7 +36,9 @@ Improvements - Larger backdrops are automatically drawn behind smaller ones, so that nested backdrops will always appear on top. - Added a `depth` plug to assign a manual drawing depth for the rare cases where the automatic depth is unwanted. - ImageStats : Added `areaSource` plug, allowing area to be driven by the input display window or data window. -- 3Delight : Added camera overscan support. +- 3Delight : + - Added camera overscan support. + - NSI scene description export format is now based on file extension - `.nsi` for binary and `.nsia` for ASCII. Fixes ----- @@ -116,6 +118,7 @@ Breaking Changes - Renamed `channels` plug to `shuffles` plug, matching nodes such as ShuffleAttributes and ShufflePrimitiveVariables. - ShuffleUI : Removed `nodeMenuCreateCommand()`. - ImageStatsUI : Removed `postCreate()`. +- 3Delight : Changed NSI scene description export with `.nsi` file extension from ASCII to binary (`.nsia` is used for ASCII now). Build ----- diff --git a/python/IECoreDelightTest/RendererTest.py b/python/IECoreDelightTest/RendererTest.py index c8cc17ff91d..de8d8407d63 100644 --- a/python/IECoreDelightTest/RendererTest.py +++ b/python/IECoreDelightTest/RendererTest.py @@ -68,12 +68,12 @@ def testSceneDescription( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ) + str( self.temporaryDirectory() / "test.nsia" ) ) r.render() - self.assertTrue( ( self.temporaryDirectory() / "test.nsi" ).exists() ) + self.assertTrue( ( self.temporaryDirectory() / "test.nsia" ).exists() ) def testOutput( self ) : @@ -144,7 +144,7 @@ def testAOVs( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ) + str( self.temporaryDirectory() / "test.nsia" ) ) r.output( @@ -163,7 +163,7 @@ def testAOVs( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) self.assertIn( "outputLayer:test", nsi ) self.assertEqual( nsi["outputLayer:test"]["nodeType"], "outputlayer") for k, v in expected.items() : @@ -175,7 +175,7 @@ def testMesh( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) r.object( @@ -187,7 +187,7 @@ def testMesh( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) meshes = { k: v for k, v in nsi.items() if nsi[k]["nodeType"] == "mesh" } self.assertEqual( len( meshes ), 1 ) @@ -228,7 +228,7 @@ def testAnimatedMesh( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) r.object( @@ -244,7 +244,7 @@ def testAnimatedMesh( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) meshes = { k: v for k, v in nsi.items() if nsi[k]["nodeType"] == "mesh" } self.assertEqual( len( meshes ), 1 ) @@ -265,7 +265,7 @@ def testPoints( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) points = IECoreScene.PointsPrimitive( IECore.V3fVectorData( [ imath.V3f( x ) for x in range( 0, 4 ) ] ) ) @@ -283,7 +283,7 @@ def testPoints( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.__assertInNSI( '"P" "v point" 4 [ 0 0 0 1 1 1 2 2 2 3 3 3 ]', nsi ) self.__assertInNSI( '"width" "v float" 4 [ 1 2 3 4 ]', nsi ) @@ -292,7 +292,7 @@ def testPointsWithoutWidth( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) points = IECoreScene.PointsPrimitive( IECore.V3fVectorData( [ imath.V3f( x ) for x in range( 0, 4 ) ] ) ) @@ -306,7 +306,7 @@ def testPointsWithoutWidth( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.__assertInNSI( '"width" "float" 1 1', nsi ) def testCurves( self ) : @@ -314,7 +314,7 @@ def testCurves( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) curves = IECoreScene.CurvesPrimitive( @@ -336,7 +336,7 @@ def testCurves( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.__assertInNSI( '"nvertices" "int" 2 [ 4 4 ]', nsi ) self.__assertInNSI( '"basis" "string" 1 "b-spline"', nsi ) self.__assertInNSI( '"P" "v point" 8 [ 0 0 0 1 1 1 2 2 2 3 3 3 0 0 0 -1 -1 -1 -2 -2 -2 -3 -3 -3 ]', nsi ) @@ -346,7 +346,7 @@ def testDisk( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) r.object( @@ -358,7 +358,7 @@ def testDisk( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) # 3Delight doesn't have a disk, so we must convert to particles self.__assertInNSI( '"particles"', nsi ) @@ -371,7 +371,7 @@ def testSphere( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) r.object( @@ -383,7 +383,7 @@ def testSphere( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) # 3Delight doesn't have a sphere, so we must convert to particles self.__assertInNSI( '"particles"', nsi ) @@ -396,7 +396,7 @@ def testEnvironment( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) r.object( @@ -413,7 +413,7 @@ def testEnvironment( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.__assertInNSI( '"environment"', nsi ) self.__assertInNSI( '"angle" "double" 1 25', nsi ) @@ -423,7 +423,7 @@ def testAttributes( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) r.attributes( IECore.CompoundObject( { @@ -435,7 +435,7 @@ def testAttributes( self ) : del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.__assertInNSI( '"visibility.diffuse" "int" 1 1', nsi ) self.__assertInNSI( '"visibility.camera" "int" 1 0', nsi ) @@ -447,7 +447,7 @@ def testCamera( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) r.camera( @@ -475,7 +475,7 @@ def testCamera( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.__assertInNSI( '"fov" "float" 1 90', nsi ) self.__assertInNSI( '"resolution" "int[2]" 1 [ 2000 1000 ]', nsi ) @@ -490,7 +490,7 @@ def testObjectInstancing( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) m = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( -1 ), imath.V2f( 1 ) ) ) @@ -502,7 +502,7 @@ def testObjectInstancing( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.assertEqual( nsi.count( '"transform"' ), 2 ) self.assertEqual( nsi.count( '"mesh"' ), 1 ) @@ -512,7 +512,7 @@ def testTransform( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) m = IECoreScene.MeshPrimitive.createPlane( imath.Box2f( imath.V2f( -1 ), imath.V2f( 1 ) ) ) @@ -529,7 +529,7 @@ def testTransform( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) self.__assertNotInNSI( 'DeleteAttribute', nsi ) self.__assertNotInNSI( 'SetAttribute "untransformed" "transformationmatrix"', nsi ) @@ -544,7 +544,7 @@ def runSubstitutions( text, attributes ): r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) s = IECoreScene.ShaderNetwork( { "output" : IECoreScene.Shader( "testShader", "surface", { "testStringSubstituted" : text } ) }, output = "output" ) @@ -559,7 +559,7 @@ def runSubstitutions( text, attributes ): r.render() del r - nsi = open( self.temporaryDirectory() / "test.nsi", encoding = "utf-8" ).read() + nsi = open( self.temporaryDirectory() / "test.nsia", encoding = "utf-8" ).read() return re.findall( '\n *"testStringSubstituted" "string" 1 "(.*)" \n', nsi )[0] self.assertEqual( runSubstitutions( " TEST ", {} ), " TEST " ) @@ -573,7 +573,7 @@ def testMessageHandler( self ) : for renderType, fileName, expected in ( ( RenderType.Batch, "", 2 ), ( RenderType.Interactive, "", 2 ), - ( RenderType.SceneDescription, str( self.temporaryDirectory() / "test.nsi" ), 1 ) + ( RenderType.SceneDescription, str( self.temporaryDirectory() / "test.nsia" ), 1 ) ) : with IECore.CapturingMessageHandler() as fallbackHandler : @@ -606,7 +606,7 @@ def testOptions( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ) + str( self.temporaryDirectory() / "test.nsia" ) ) options = [ @@ -645,7 +645,7 @@ def testOptions( self ) : r.render() del r - nsi = self.__parse( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parse( self.temporaryDirectory() / "test.nsia" ) for name, value, type in options : self.__assertInNSI( @@ -664,7 +664,7 @@ def testVDB( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) vdb = IECoreVDB.VDBObject( ( pathlib.Path( __file__ ).parent / "volumes" / "sphere.vdb" ).as_posix() ) @@ -673,7 +673,7 @@ def testVDB( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) self.assertIn( "test_vdb", nsi ) self.assertEqual( nsi["test_vdb"]["nodeType"], "transform" ) @@ -691,7 +691,7 @@ def testShaderAttributes( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) surfaceNetwork = IECoreScene.ShaderNetwork( @@ -725,7 +725,7 @@ def testShaderAttributes( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) allAttributes = { k: v for k, v in nsi.items() if nsi[k]["nodeType"] == "attributes" } self.assertEqual( len( allAttributes ), 1 ) @@ -759,7 +759,7 @@ def test3DelightSplineParameters( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) os.environ["OSL_SHADER_PATHS"] += os.pathsep + ( pathlib.Path( __file__ ).parent / "shaders" ).as_posix() @@ -846,7 +846,7 @@ def test3DelightSplineParameters( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) shaders = { k: v for k, v in nsi.items() if nsi[k]["nodeType"] == "shader" } self.assertEqual( len( shaders ), 1 ) @@ -922,7 +922,7 @@ def testGafferSplineParameters( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) network = IECoreScene.ShaderNetwork( @@ -960,7 +960,7 @@ def testGafferSplineParameters( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) shaders = { k: v for k, v in nsi.items() if nsi[k]["nodeType"] == "shader" } self.assertEqual( len( shaders ), 1 ) @@ -985,7 +985,7 @@ def testUVCoordShaderInserted( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) s = IECoreScene.ShaderNetwork( @@ -1003,7 +1003,7 @@ def testUVCoordShaderInserted( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) shaders = { k: v for k, v in nsi.items() if nsi[k]["nodeType"] == "shader" } @@ -1020,7 +1020,7 @@ def testUVCoordShaderNotInserted( self ) : r = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) s = IECoreScene.ShaderNetwork( @@ -1042,7 +1042,7 @@ def testUVCoordShaderNotInserted( self ) : r.render() del r - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) shaders = { k: v for k, v in nsi.items() if nsi[k]["nodeType"] == "shader" } @@ -1064,7 +1064,7 @@ def testCornersAndCreases( self ) : renderer = GafferScene.Private.IECoreScenePreview.Renderer.create( "3Delight", GafferScene.Private.IECoreScenePreview.Renderer.RenderType.SceneDescription, - str( self.temporaryDirectory() / "test.nsi" ), + str( self.temporaryDirectory() / "test.nsia" ), ) renderer.object( "testPlane", mesh, renderer.attributes( IECore.CompoundObject() ) ) @@ -1072,7 +1072,7 @@ def testCornersAndCreases( self ) : renderer.render() del renderer - nsi = self.__parseDict( self.temporaryDirectory() / "test.nsi" ) + nsi = self.__parseDict( self.temporaryDirectory() / "test.nsia" ) mesh = next( node for node in nsi.values() if node["nodeType"] == "mesh" ) self.assertEqual( mesh["subdivision.creasevertices"], [ 0, 1, 1, 2 ] ) diff --git a/src/IECoreDelight/Renderer.cpp b/src/IECoreDelight/Renderer.cpp index 20b4d9b1b9a..2ea8893f57f 100644 --- a/src/IECoreDelight/Renderer.cpp +++ b/src/IECoreDelight/Renderer.cpp @@ -1087,11 +1087,13 @@ class DelightRenderer final : public IECoreScenePreview::Renderer vector params; const char *apistream = "apistream"; + const char *streamformat = "autonsi"; const char *fileNamePtr = fileName.c_str(); if( renderType == SceneDescription ) { params = { { "type", &apistream, NSITypeString, 0, 1, 0 }, + { "streamformat", &streamformat, NSITypeString, 0, 1, 0 }, { "streamfilename", &fileNamePtr, NSITypeString , 0, 1, 0 } }; }