IECore::CameraPtr GafferScene::camera( const ScenePlug *scene, const ScenePlug::ScenePath &cameraPath, const IECore::CompoundObject *globals ) { ConstCompoundObjectPtr computedGlobals; if( !globals ) { computedGlobals = scene->globalsPlug()->getValue(); globals = computedGlobals.get(); } std::string cameraName; ScenePlug::pathToString( cameraPath, cameraName ); if( !exists( scene, cameraPath ) ) { throw IECore::Exception( "Camera \"" + cameraName + "\" does not exist" ); } IECore::ConstCameraPtr constCamera = runTimeCast<const IECore::Camera>( scene->object( cameraPath ) ); if( !constCamera ) { std::string path; ScenePlug::pathToString( cameraPath, path ); throw IECore::Exception( "Location \"" + cameraName + "\" is not a camera" ); } IECore::CameraPtr camera = constCamera->copy(); camera->setName( cameraName ); const BoolData *cameraBlurData = globals->member<BoolData>( "option:render:cameraBlur" ); const bool cameraBlur = cameraBlurData ? cameraBlurData->readable() : false; camera->setTransform( transform( scene, cameraPath, shutter( globals ), cameraBlur ) ); applyCameraGlobals( camera.get(), globals ); return camera; }
void updateViewportCameraAndOverlay() { if( !m_viewportCameraDirty ) { return; } if( !m_lookThroughCamera ) { m_overlay->setResolutionGate( Box2f() ); m_overlay->setVisible( false ); return; } // The camera will have a resolution and screen window set from the scene // globals. We need to adjust them to fit the viewport appropriately, placing // the resolution gate centrally with a border around it. Start by figuring // out where we'll draw the resolution gate in raster space. IECore::CameraPtr camera = m_lookThroughCamera->copy(); const float borderPixels = 40; const V2f viewport = m_view->viewportGadget()->getViewport(); const V2f insetViewport( max( viewport.x - borderPixels * 2.0f, min( viewport.x, 50.0f ) ), max( viewport.y - borderPixels * 2.0f, min( viewport.y, 50.0f ) ) ); const float insetViewportAspectRatio = insetViewport.x / insetViewport.y; const V2f resolution = camera->parametersData()->member<V2iData>( "resolution" )->readable(); const float pixelAspectRatio = camera->parametersData()->member<FloatData>( "pixelAspectRatio" )->readable(); V2f resolutionGateSize = resolution; resolutionGateSize.x *= pixelAspectRatio; const float resolutionGateAspectRatio = resolutionGateSize.x / resolutionGateSize.y; if( resolutionGateAspectRatio > insetViewportAspectRatio ) { // fit horizontally resolutionGateSize *= insetViewport.x / resolutionGateSize.x; } else { // fit vertically resolutionGateSize *= insetViewport.y / resolutionGateSize.y; } const V2f offset = ( viewport - resolutionGateSize ) / 2.0f; m_overlay->setResolutionGate( Box2f( V2f( offset ), V2f( resolutionGateSize + offset ) ) ); m_overlay->setCropWindow( camera->parametersData()->member<Box2fData>( "cropWindow" )->readable() ); m_overlay->setCaption( boost::str( boost::format( "%dx%d, %.3f, %s" ) % resolution.x % resolution.y % pixelAspectRatio % camera->getName() ) ); m_overlay->setVisible( true ); // Now modify the camera, so that the view through the resolution gate we've calculated // represents the rendered image - this means extending the resolution and screen // window to account for the border area outside the resolution gate. Box2f &screenWindow = camera->parametersData()->member<Box2fData>( "screenWindow" )->writable(); const V2f newScreenWindowSize = screenWindow.size() * viewport / resolutionGateSize; const V2f screenWindowCenter = screenWindow.center(); screenWindow.min = screenWindowCenter - newScreenWindowSize / 2.0f; screenWindow.max = screenWindowCenter + newScreenWindowSize / 2.0f; camera->parameters()["resolution"] = new V2iData( m_view->viewportGadget()->getViewport() ); m_view->viewportGadget()->setCamera( camera.get() ); m_view->viewportGadget()->setCameraEditable( false ); }