diff --git a/include/osgViewer/View b/include/osgViewer/View index 7db8eeb93..b0b83de2d 100644 --- a/include/osgViewer/View +++ b/include/osgViewer/View @@ -143,6 +143,13 @@ class OSGVIEWER_EXPORT View : public osg::View, public osgGA::GUIActionAdapter /** Convinience method for a single Camara associated with a single full screen GraphicsWindow.*/ void setUpViewOnSingleScreen(unsigned int screenNum=0); + + /** Convinience method for spherical display using 6 slave cameras rendering the 6 sides of a cube map, and 7th camera doing distortion correction to present on a spherical display.*/ + void setUpViewFor3DSphericalDisplay(double radius=1.0, double collar=0.45, unsigned int screenNum=0, osg::Image* intensityMap=0); + + /** Convinience method for spherical display by rendering main scene to as panoramic 2:1 texture and then doing distortion correction to present onto a spherical display.*/ + void setUpViewForPanoramicSphericalDisplay(double radius=1.0, double collar=0.45, unsigned int screenNum=0, osg::Image* intensityMap=0); + /** Return true if this view contains a specified camera.*/ bool containsCamera(const osg::Camera* camera) const; diff --git a/src/osgViewer/View.cpp b/src/osgViewer/View.cpp index a7914f8a3..37cee2d76 100644 --- a/src/osgViewer/View.cpp +++ b/src/osgViewer/View.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -62,7 +63,6 @@ public: ViewerCoordinateFrameCallback(osgViewer::View* view): _view(view) {} - virtual osg::CoordinateFrame getCoordinateFrame(const osg::Vec3d& position) const { @@ -652,6 +652,366 @@ void View::setUpViewOnSingleScreen(unsigned int screenNum) _camera->setReadBuffer(buffer); } +static osg::Geometry* create3DSphericalDisplayDistortionMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, double sphere_radius, double collar_radius) +{ + osg::Vec3d center(0.0,0.0,0.0); + osg::Vec3d eye(0.0,0.0,0.0); + + double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius); + + bool centerProjection = false; + + osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance); + + osg::notify(osg::NOTICE)<<"Projector position = "<getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height); + + osg::GraphicsContext::ScreenIdentifier si; + si.readDISPLAY(); + + // displayNum has not been set so reset it to 0. + if (si.displayNum<0) si.displayNum = 0; + + si.screenNum = screenNum; + + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->hostName = si.hostName; + traits->displayNum = si.displayNum; + traits->screenNum = si.screenNum; + traits->x = 0; + traits->y = 0; + traits->width = width; + traits->height = height; + traits->windowDecoration = false; + traits->doubleBuffer = true; + traits->sharedContext = 0; + + + osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); + if (!gc) + { + osg::notify(osg::NOTICE)<<"GraphicsWindow has not been created successfully."<setTextureSize(tex_width, tex_height); + texture->setInternalFormat(GL_RGB); + texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); + texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); + +#if 0 + osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::SEPERATE_WINDOW; + GLenum buffer = GL_FRONT; +#else + osg::Camera::RenderTargetImplementation renderTargetImplementation = osg::Camera::FRAME_BUFFER_OBJECT; + GLenum buffer = GL_FRONT; +#endif + + // front face + { + osg::ref_ptr camera = new osg::Camera; + camera->setName("Front face camera"); + camera->setGraphicsContext(gc.get()); + camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); + camera->setDrawBuffer(buffer); + camera->setReadBuffer(buffer); + camera->setAllowEventFocus(false); + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplementation(renderTargetImplementation); + + // attach the texture and use it as the color buffer. + camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_Y); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd()); + } + + + // top face + { + osg::ref_ptr camera = new osg::Camera; + camera->setName("Top face camera"); + camera->setGraphicsContext(gc.get()); + camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); + GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; + camera->setDrawBuffer(buffer); + camera->setReadBuffer(buffer); + camera->setAllowEventFocus(false); + + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplementation(renderTargetImplementation); + + // attach the texture and use it as the color buffer. + camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_Z); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(-90.0f), 1.0,0.0,0.0)); + } + + // left face + { + osg::ref_ptr camera = new osg::Camera; + camera->setName("Left face camera"); + camera->setGraphicsContext(gc.get()); + camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); + camera->setDrawBuffer(buffer); + camera->setReadBuffer(buffer); + camera->setAllowEventFocus(false); + + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplementation(renderTargetImplementation); + + // attach the texture and use it as the color buffer. + camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_X); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0,1.0,0.0) * osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0,0.0,1.0)); + } + + // right face + { + osg::ref_ptr camera = new osg::Camera; + camera->setName("Right face camera"); + camera->setGraphicsContext(gc.get()); + camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); + camera->setDrawBuffer(buffer); + camera->setReadBuffer(buffer); + camera->setAllowEventFocus(false); + + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplementation(renderTargetImplementation); + + // attach the texture and use it as the color buffer. + camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::POSITIVE_X); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0,1.0,0.0 ) * osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0,0.0,1.0)); + } + + // bottom face + { + osg::ref_ptr camera = new osg::Camera; + camera->setGraphicsContext(gc.get()); + camera->setName("Bottom face camera"); + camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); + camera->setDrawBuffer(buffer); + camera->setReadBuffer(buffer); + camera->setAllowEventFocus(false); + + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplementation(renderTargetImplementation); + + // attach the texture and use it as the color buffer. + camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_Z); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(90.0f), 1.0,0.0,0.0) * osg::Matrixd::rotate(osg::inDegrees(180.0f), 0.0,0.0,1.0)); + } + + // back face + { + osg::ref_ptr camera = new osg::Camera; + camera->setName("Back face camera"); + camera->setGraphicsContext(gc.get()); + camera->setViewport(new osg::Viewport(0,0,camera_width, camera_height)); + camera->setDrawBuffer(buffer); + camera->setReadBuffer(buffer); + camera->setAllowEventFocus(false); + + // tell the camera to use OpenGL frame buffer object where supported. + camera->setRenderTargetImplementation(renderTargetImplementation); + + // attach the texture and use it as the color buffer. + camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, osg::TextureCubeMap::NEGATIVE_Y); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd::rotate(osg::inDegrees(180.0f), 1.0,0.0,0.0)); + } + + getCamera()->setProjectionMatrixAsPerspective(90.0f, 1.0, 1, 1000.0); + + // distortion correction set up. + { + osg::Geode* geode = new osg::Geode(); + geode->addDrawable(create3DSphericalDisplayDistortionMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), radius, collar)); + + // new we need to add the texture to the mesh, we do so by creating a + // StateSet to contain the Texture StateAttribute. + osg::StateSet* stateset = geode->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); + stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); + + osg::ref_ptr camera = new osg::Camera; + camera->setGraphicsContext(gc.get()); + camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); + camera->setClearColor( osg::Vec4(0.1,0.1,1.0,1.0) ); + camera->setViewport(new osg::Viewport(0, 0, width, height)); + GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; + camera->setDrawBuffer(buffer); + camera->setReadBuffer(buffer); + camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); + camera->setAllowEventFocus(false); + //camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE); + //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); + + camera->setProjectionMatrixAsOrtho2D(0,width,0,height); + camera->setViewMatrix(osg::Matrix::identity()); + + // add subgraph to render + camera->addChild(geode); + + camera->setName("DistortionCorrectionCamera"); + + addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); + } + + getCamera()->setNearFarRatio(0.0001f); + + if (getLightingMode()==osg::View::HEADLIGHT) + { + // set a local light source for headlight to ensure that lighting is consistent across sides of cube. + getLight()->setPosition(osg::Vec4(0.0f,0.0f,0.0f,1.0f)); + } +} + +void View::setUpViewForPanoramicSphericalDisplay(double radius, double collar, unsigned int screenNum, osg::Image* intensityMap) +{ + osg::notify(osg::NOTICE)<<"View::setUpViewForPanoramicSphericalDisplay(rad="< #include +#include #include #include @@ -60,8 +61,33 @@ Viewer::Viewer(osg::ArgumentParser& arguments) int x = -1, y = -1, width = -1, height = -1; while (arguments.read("--window",x,y,width,height)) {} + + bool ss3d = false; + if ((ss3d=arguments.read("--3d-ss")) || arguments.read("--panoramic-ss")) + { + double radius = 1.0; + while (arguments.read("--radius",radius)) {} - if (width>0 && height>0) + double collar = 0.45; + while (arguments.read("--collar",collar)) {} + + std::string intensityMapFilename; + while (arguments.read("--im",intensityMapFilename)) {} + + osg::ref_ptr intensityMap = intensityMapFilename.empty() ? 0 : osgDB::readImageFile(intensityMapFilename); + + if (screenNum<0) screenNum = 0; + + if (ss3d) + { + setUpViewFor3DSphericalDisplay(radius, collar, screenNum, intensityMap.get()); + } + else + { + setUpViewForPanoramicSphericalDisplay(radius, collar, screenNum, intensityMap.get()); + } + } + else if (width>0 && height>0) { if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum); else setUpViewInWindow(x,y,width,height);