diff --git a/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h b/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h new file mode 100644 index 0000000000..320953d3eb --- /dev/null +++ b/contrib/IECoreUSD/include/IECoreUSD/SceneAlgo.h @@ -0,0 +1,67 @@ +////////////////////////////////////////////////////////////////////////// +// +// 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" +#include "pxr/usd/usd/stageCache.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 ); + +// \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 + +#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..8e58639a31 --- /dev/null +++ b/contrib/IECoreUSD/src/IECoreUSD/SceneAlgo.cpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////// +// +// 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 ); +} + +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/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..a6b2085e4f 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/bindings/IEUSDModule.cpp @@ -34,6 +34,22 @@ #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 ); + 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 e990936639..f71eea82e8 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -2320,5 +2320,49 @@ 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" ) + + id = IECoreUSD.SceneAlgo.cacheStage( stage ) + scene = IECoreUSD.SceneAlgo.getScene( id ) + 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()