From a1e05276849f7903fa15ec20ce907d4c3035a020 Mon Sep 17 00:00:00 2001 From: Andrew Kaufman Date: Tue, 26 Jan 2021 15:40:20 -0800 Subject: [PATCH 1/2] IECoreUSD : Add SceneAlgo::sceneFromStage This utility can be used to wrap a live UsdStage into an IECoreScene::SceneInterface (as though the stage was already written to a file) --- .../IECoreUSD/include/IECoreUSD/SceneAlgo.h | 59 +++++++++++++++++++ contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp | 47 +++++++++++++++ contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp | 21 ++++++- contrib/IECoreUSD/src/IECoreUSD/USDScene.h | 5 ++ .../src/IECoreUSD/bindings/IEUSDModule.cpp | 12 ++++ .../IECoreUSD/test/IECoreUSD/USDSceneTest.py | 43 ++++++++++++++ 6 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h create mode 100644 contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp diff --git a/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h b/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h new file mode 100644 index 0000000000..80fb8918e7 --- /dev/null +++ b/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h @@ -0,0 +1,59 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2021, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Image Engine Design nor the names of any +// other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef IECOREUSD_SCENEALGO_H +#define IECOREUSD_SCENEALGO_H + +#include "IECoreUSD/Export.h" + +#include "IECoreScene/SceneInterface.h" + +IECORE_PUSH_DEFAULT_VISIBILITY +#include "pxr/usd/usd/stage.h" +IECORE_POP_DEFAULT_VISIBILITY + +namespace IECoreUSD +{ + +namespace SceneAlgo +{ + +/// Wrap a UsdStage into a Cortex SceneInterface +IECOREUSD_API IECoreScene::SceneInterfacePtr sceneFromStage( const pxr::UsdStageRefPtr &stage ); + +} // namespace SceneAlgo + +} // namespace IECoreUSD + +#endif // IECOREUSD_SCENEALGO_H diff --git a/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp new file mode 100644 index 0000000000..7b9ad2aa30 --- /dev/null +++ b/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp @@ -0,0 +1,47 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2021, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of Image Engine Design nor the names of any +// other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#include "IECoreUSD/SceneAlgo.h" +#include "IECoreUSD/USDScene.h" + +using namespace std; +using namespace pxr; +using namespace IECore; +using namespace IECoreScene; +using namespace IECoreUSD; + +SceneInterfacePtr IECoreUSD::SceneAlgo::sceneFromStage( const pxr::UsdStageRefPtr &stage ) +{ + return new USDScene( stage ); +} diff --git a/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp b/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp index 34f532ba63..bd90663a63 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp @@ -361,8 +361,13 @@ class USDScene::IO : public RefCounted throw Exception( "Unsupported OpenMode" ); } - m_timeCodesPerSecond = m_stage->GetTimeCodesPerSecond(); - m_rootPrim = m_stage->GetPseudoRoot(); + initStage(); + } + + IO( const pxr::UsdStageRefPtr &stage, IndexedIO::OpenMode openMode ) + : m_fileName( "" ), m_openMode( openMode ), m_stage( stage ) + { + initStage(); } ~IO() override @@ -377,6 +382,12 @@ class USDScene::IO : public RefCounted } } + void initStage() + { + m_timeCodesPerSecond = m_stage->GetTimeCodesPerSecond(); + m_rootPrim = m_stage->GetPseudoRoot(); + } + const std::string &fileName() const { return m_fileName; @@ -448,6 +459,12 @@ USDScene::USDScene( const std::string &fileName, IndexedIO::OpenMode openMode ) { } +USDScene::USDScene( const pxr::UsdStageRefPtr &stage ) + : m_root( new IO( stage, IndexedIO::Read ) ), + m_location( new Location( m_root->root() ) ) +{ +} + USDScene::USDScene( IOPtr io, LocationPtr location ) : m_root( io ), m_location( location ) { diff --git a/contrib/IECoreUSD/src/IECoreUSD/USDScene.h b/contrib/IECoreUSD/src/IECoreUSD/USDScene.h index 013e166dce..f72359f4c9 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/USDScene.h +++ b/contrib/IECoreUSD/src/IECoreUSD/USDScene.h @@ -41,6 +41,10 @@ #include "IECore/PathMatcherData.h" +IECORE_PUSH_DEFAULT_VISIBILITY +#include "pxr/usd/usd/stage.h" +IECORE_POP_DEFAULT_VISIBILITY + namespace IECoreUSD { @@ -49,6 +53,7 @@ class USDScene : public IECoreScene::SceneInterface public: IE_CORE_DECLARERUNTIMETYPEDEXTENSION( USDScene, IECoreUSD::USDSceneTypeId, IECoreScene::SceneInterface ) USDScene( const std::string &path, IECore::IndexedIO::OpenMode mode ); + explicit USDScene( const pxr::UsdStageRefPtr &stage ); ~USDScene() override; diff --git a/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp b/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp index b845b4fe93..34a3d1027b 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp @@ -34,6 +34,18 @@ #include "boost/python.hpp" +#include "IECoreUSD/SceneAlgo.h" + +using namespace boost::python; +using namespace IECoreUSD; + BOOST_PYTHON_MODULE( _IECoreUSD ) { + { + object module( borrowed( PyImport_AddModule( "IECoreUSD.SceneAlgo" ) ) ); + scope().attr( "SceneAlgo" ) = module; + scope moduleScope( module ); + + def( "sceneFromStage", &SceneAlgo::sceneFromStage ); + } } diff --git a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py index e990936639..e5c109ce04 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -2320,5 +2320,48 @@ def testSkelBlendShapes( self ) : self.assertAlmostEqual( arm_10["P"].data[i].y, expected_10[i].y, 5 ) self.assertAlmostEqual( arm_10["P"].data[i].z, expected_10[i].z, 5 ) + def testSceneFromStage( self ) : + + stage = pxr.Usd.Stage.CreateInMemory() + pxr.UsdGeom.Xform.Define( stage, "/a" ) + pxr.UsdGeom.Camera.Define( stage, "/a/c" ) + stage.OverridePrim( "/a/b" ).GetReferences().AddReference( os.path.join( os.path.dirname( __file__ ), "data", "cube.usda" ), "/pCube1" ) + + scene = IECoreUSD.SceneAlgo.sceneFromStage( stage ) + self.assertEqual( scene.childNames(), [ "a" ] ) + + a = scene.child( "a" ) + self.assertEqual( set( a.childNames() ), { "b", "c" } ) + + b = a.child( "b" ) + self.assertEqual( b.childNames(), [] ) + self.assertEqual( b.hasObject(), True ) + refScene = IECoreScene.SceneInterface.create( os.path.join( os.path.dirname( __file__ ), "data", "cube.usda" ), IECore.IndexedIO.OpenMode.Read ) + refCube = refScene.child( "pCube1" ) + self.assertEqual( b.readObject( 0 ), refCube.readObject( 0 ) ) + + c = a.child( "c" ) + self.assertEqual( c.childNames(), [] ) + self.assertEqual( c.hasObject(), True ) + refCam = IECoreScene.Camera() + refCam.setProjection( "perspective" ) + refCam.setFocalLength( 50 ) + refCam.setAperture( imath.V2f( 20.9549999, 15.2908001 ) ) + refCam.setApertureOffset( imath.V2f( 0, 0 ) ) + refCam.setClippingPlanes( imath.V2f( 1, 1000000 ) ) + refCam.setFocalLengthWorldScale( 0.1 ) + refCam.setFocusDistance( 0 ) + refCam.setFStop( 0 ) + refCam.setShutter( imath.V2f( 0, 0 ) ) + self.assertEqual( c.readObject( 0 ), refCam ) + + # change the stage + stage.OverridePrim( "/a/d" ).GetReferences().AddReference( os.path.join( os.path.dirname( __file__ ), "data", "cube.usda" ), "/pCube1" ) + self.assertEqual( set( a.childNames() ), { "b", "c", "d" } ) + d = a.child( "d" ) + self.assertEqual( d.childNames(), [] ) + self.assertEqual( d.hasObject(), True ) + self.assertEqual( d.readObject( 0 ), refCube.readObject( 0 ) ) + if __name__ == "__main__": unittest.main() From 8c672c7280d4ce63723bb64fc55f98a62bd657c9 Mon Sep 17 00:00:00 2001 From: Andrew Kaufman Date: Wed, 27 Jan 2021 09:28:43 -0800 Subject: [PATCH 2/2] WIP UsdStageCache Wrappers --- .../IECoreUSD/include/IECoreUSD/SceneAlgo.h | 8 +++++ contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp | 31 +++++++++++++++++++ .../src/IECoreUSD/bindings/IEUSDModule.cpp | 4 +++ .../IECoreUSD/test/IECoreUSD/USDSceneTest.py | 3 +- 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h b/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h index 80fb8918e7..320953d3eb 100644 --- a/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h +++ b/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h @@ -41,6 +41,7 @@ IECORE_PUSH_DEFAULT_VISIBILITY #include "pxr/usd/usd/stage.h" +#include "pxr/usd/usd/stageCache.h" IECORE_POP_DEFAULT_VISIBILITY namespace IECoreUSD @@ -52,6 +53,13 @@ namespace SceneAlgo /// Wrap a UsdStage into a Cortex SceneInterface IECOREUSD_API IECoreScene::SceneInterfacePtr sceneFromStage( const pxr::UsdStageRefPtr &stage ); +// \todo: remove this and make it part of the normal SceneInterface factory +IECOREUSD_API IECoreScene::SceneInterfacePtr getScene( int stageId ); + +IECOREUSD_API int cacheStage( const pxr::UsdStageRefPtr &stage ); +IECOREUSD_API int getStageId( const pxr::UsdStageRefPtr &stage ); +IECOREUSD_API bool eraseStage( int stageId ); + } // namespace SceneAlgo } // namespace IECoreUSD diff --git a/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp index 7b9ad2aa30..8e58639a31 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp @@ -45,3 +45,34 @@ SceneInterfacePtr IECoreUSD::SceneAlgo::sceneFromStage( const pxr::UsdStageRefPt { return new USDScene( stage ); } + +namespace +{ + +UsdStageCache &stageCache() +{ + static UsdStageCache *g_stageCache = new UsdStageCache; + return *g_stageCache; +} + +} // namespace + +SceneInterfacePtr IECoreUSD::SceneAlgo::getScene( int stageId ) +{ + return new USDScene( ::stageCache().Find( UsdStageCache::Id::FromLongInt( stageId ) ) ); +} + +int IECoreUSD::SceneAlgo::cacheStage( const UsdStageRefPtr &stage ) +{ + return ::stageCache().Insert( stage ).ToLongInt(); +} + +int IECoreUSD::SceneAlgo::getStageId( const UsdStageRefPtr &stage ) +{ + return ::stageCache().GetId( stage ).ToLongInt(); +} + +bool IECoreUSD::SceneAlgo::eraseStage( int stageId ) +{ + return ::stageCache().Erase( UsdStageCache::Id::FromLongInt( stageId ) ); +} diff --git a/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp b/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp index 34a3d1027b..a6b2085e4f 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp @@ -47,5 +47,9 @@ BOOST_PYTHON_MODULE( _IECoreUSD ) scope moduleScope( module ); def( "sceneFromStage", &SceneAlgo::sceneFromStage ); + def( "getScene", &SceneAlgo::getScene ); + def( "cacheStage", &SceneAlgo::cacheStage ); + def( "getStageId", &SceneAlgo::getStageId ); + def( "eraseStage", &SceneAlgo::eraseStage ); } } diff --git a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py index e5c109ce04..f71eea82e8 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -2327,7 +2327,8 @@ def testSceneFromStage( self ) : pxr.UsdGeom.Camera.Define( stage, "/a/c" ) stage.OverridePrim( "/a/b" ).GetReferences().AddReference( os.path.join( os.path.dirname( __file__ ), "data", "cube.usda" ), "/pCube1" ) - scene = IECoreUSD.SceneAlgo.sceneFromStage( stage ) + id = IECoreUSD.SceneAlgo.cacheStage( stage ) + scene = IECoreUSD.SceneAlgo.getScene( id ) self.assertEqual( scene.childNames(), [ "a" ] ) a = scene.child( "a" )