From c40ce535f2ca56f829ef2a5ea44a55933766eac0 Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Thu, 26 Jun 2025 17:27:13 -0700 Subject: [PATCH 1/2] USD CameraAlgo : Only write authored shutter values to USD This avoids baking in our default [-0.5, 0.5] shutter when writing a camera with no shutter to USD. --- Changes | 3 +++ .../IECoreUSD/src/IECoreUSD/CameraAlgo.cpp | 19 +++++++++++-------- .../IECoreUSD/test/IECoreUSD/USDSceneTest.py | 15 +++++++++++++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Changes b/Changes index 70a465f377..bb9987df41 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,10 @@ 10.x.x.x (relative to 10.5.x.x) ======== +Fixes +----- +- USDScene : Fixed writing of shutter values from cameras without a `shutter` parameter. The `shutter:open` and `shutter:close` attributes are now omitted instead of being written with Cortex's default -0.5, 0.5 shutter values. 10.5.x.x (relative to 10.5.15.0) ======== diff --git a/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp index 0016156808..e3313958b6 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp @@ -188,14 +188,17 @@ bool writeCamera( const IECoreScene::Camera *camera, const pxr::UsdStagePtr &sta usdCamera.GetFStopAttr().Set( camera->getFStop() ); usdCamera.GetFocusDistanceAttr().Set( camera->getFocusDistance() ); - /// \todo This is documented as being specified in UsdTimeCode units, - /// in which case I think we should be converting from seconds using - /// `stage->GetTimeCodesPerSecond()`. Having looked at both the Maya - /// and Houdini plugin sources, I've been unable to find evidence for - /// anyone else doing this though, so maybe it's one of those things - /// everyone is just getting wrong? - usdCamera.GetShutterOpenAttr().Set( (double)camera->getShutter()[0] ); - usdCamera.GetShutterCloseAttr().Set( (double)camera->getShutter()[1] ); + if( camera->hasShutter() ) + { + /// \todo This is documented as being specified in UsdTimeCode units, + /// in which case I think we should be converting from seconds using + /// `stage->GetTimeCodesPerSecond()`. Having looked at both the Maya + /// and Houdini plugin sources, I've been unable to find evidence for + /// anyone else doing this though, so maybe it's one of those things + /// everyone is just getting wrong? + usdCamera.GetShutterOpenAttr().Set( (double)camera->getShutter()[0] ); + usdCamera.GetShutterCloseAttr().Set( (double)camera->getShutter()[1] ); + } return true; } diff --git a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py index b3f1328108..efbc19b977 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -1285,6 +1285,13 @@ def formatCameraName( **kw ) : name = formatCameraName( scale = scale ) testCameras[name] = c + for shutterOpen in [ 0, -0.25, -1.0 ] : + for shutterClose in [ 0, 0.25, 1.0 ] : + c = IECoreScene.Camera() + c.setShutter( imath.V2f( shutterOpen, shutterClose ) ) + name = formatCameraName( shutterOpen = shutterOpen, shutterClose = shutterClose ) + testCameras[name] = c + root = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write ) for name, c in testCameras.items() : @@ -1321,8 +1328,12 @@ def formatCameraName( **kw ) : self.assertEqual( c.clippingRange.max, cortexCam.getClippingPlanes()[1] ) self.assertEqual( c.fStop, cortexCam.getFStop() ) self.assertEqual( c.focusDistance, cortexCam.getFocusDistance() ) - self.assertEqual( cG.GetShutterOpenAttr().Get(), cortexCam.getShutter()[0] ) - self.assertEqual( cG.GetShutterCloseAttr().Get(), cortexCam.getShutter()[1] ) + if cortexCam.hasShutter() : + self.assertEqual( cG.GetShutterOpenAttr().Get(), cortexCam.getShutter()[0] ) + self.assertEqual( cG.GetShutterCloseAttr().Get(), cortexCam.getShutter()[1] ) + else : + self.assertFalse( cG.GetShutterOpenAttr().HasAuthoredValue() ) + self.assertFalse( cG.GetShutterCloseAttr().HasAuthoredValue() ) try : from pxr import CameraUtil From 494496c1a3202845a20db4773437835fa21f188c Mon Sep 17 00:00:00 2001 From: Murray Stevenson <50844517+murraystevenson@users.noreply.github.com> Date: Thu, 26 Jun 2025 17:27:23 -0700 Subject: [PATCH 2/2] USD CameraAlgo : Only read authored shutter values from USD This avoids cameras read from USD files ending up with USD's default [0, 0] shutter when the USD camera has no shutter values. --- Changes | 4 +++- contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp | 11 ++++++++--- contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py | 1 + 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Changes b/Changes index bb9987df41..dafed3ac37 100644 --- a/Changes +++ b/Changes @@ -4,7 +4,9 @@ Fixes ----- -- USDScene : Fixed writing of shutter values from cameras without a `shutter` parameter. The `shutter:open` and `shutter:close` attributes are now omitted instead of being written with Cortex's default -0.5, 0.5 shutter values. +- USDScene : + - Fixed writing of shutter values from cameras without a `shutter` parameter. The `shutter:open` and `shutter:close` attributes are now omitted instead of being written with Cortex's default -0.5, 0.5 shutter values. + - Fixed reading of shutter values from cameras without `shutter:open` and `shutter:close` attributes. The `shutter` parameter is now omitted instead of being created with USD's default 0, 0 shutter values. 10.5.x.x (relative to 10.5.15.0) ======== diff --git a/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp b/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp index e3313958b6..677c4b25d8 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/CameraAlgo.cpp @@ -111,9 +111,14 @@ IECore::ObjectPtr readCamera( pxr::UsdGeomCamera &camera, pxr::UsdTimeCode time, result->setFocusDistance( focusDistance ); Imath::V2d shutter; - camera.GetShutterOpenAttr().Get( &shutter[0], time ); - camera.GetShutterCloseAttr().Get( &shutter[1], time ); - result->setShutter( shutter ); + auto shutterOpenAttr = camera.GetShutterOpenAttr(); + auto shutterCloseAttr = camera.GetShutterCloseAttr(); + if( shutterOpenAttr.HasAuthoredValue() || shutterCloseAttr.HasAuthoredValue() ) + { + shutterOpenAttr.Get( &shutter[0], time ); + shutterCloseAttr.Get( &shutter[1], time ); + result->setShutter( shutter ); + } return result; } diff --git a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py index efbc19b977..7badc3b74c 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -1400,6 +1400,7 @@ def assertVectorsAlmostEqual( a, b,**kw ) : self.assertEqual( c2.getClippingPlanes(), c.getClippingPlanes() ) self.assertEqual( c2.getFStop(), c.getFStop() ) self.assertEqual( c2.getFocusDistance(), c.getFocusDistance() ) + self.assertEqual( c2.hasShutter(), c.hasShutter() ) self.assertEqual( c2.getShutter(), c.getShutter() ) assertVectorsAlmostEqual( c2.frustum().min(), c.frustum().min(), places = 6 )