From d38fcc9979829d2d988d63f7bab85a1ef1452543 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Mon, 22 Nov 2010 09:10:40 +0100 Subject: [PATCH] panoramic spherical distortion This supports the panoramic distortion option, as found in osgViewer, in the camera file syntax of flightgear. --- docs-mini/README.multiscreen | 82 ++++++++++++ src/Main/CameraGroup.cxx | 244 ++++++++++++++++++++++++++++++++++- src/Main/CameraGroup.hxx | 7 + 3 files changed, 330 insertions(+), 3 deletions(-) diff --git a/docs-mini/README.multiscreen b/docs-mini/README.multiscreen index 9954f13f9..042bbac84 100644 --- a/docs-mini/README.multiscreen +++ b/docs-mini/README.multiscreen @@ -133,6 +133,30 @@ window, camera, or gui tags. This specifies an orthographic view. The parameters are the sames as the frustum node's. + texture + This tag indicates that the camera renders to a texture instead of the + framebuffer. For now the following tags are supported, but obviously + different texture formats should be specified too. + name - string + The name of the texture. This can be referred to by other cameras. + width, height - double + The dimensions of the texture + + panoramic-distortion + This tag cause the camera to create distortion geometry that + corrects for projection onto a spherical screen. It is equivalent to + the --panoramic-sd option to osgviewer. + + texture - string + The name of a texture, created by another camera, that will be + rendered on the distortion correction geometry. + + radius - double + Radius of string + + collar - double + size of screen collar. + gui This is a special camera node that displays the 2D GUI. @@ -313,3 +337,61 @@ accounted for. + +This example renders the scene for projection onto a spherical screen. + + + + + + + + main + + 0 + 0 + + 1024 + 768 + + + 0 + + + 0.133 + -0.133 + -.1668 + .1668 + 0.4 + 120000.0 + + + mainview + 1024 + 768 + + + + main + + 768 + 0 + 0 + 1024 + -1.0 + 1.0 + + + mainview + + + + + main + + + + + + + diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 0fb2f2e56..ae4cf48df 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -36,9 +36,13 @@ #include #include +#include #include #include +#include +#include #include +#include #include #include @@ -148,7 +152,18 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera, // resized; if the the viewport isn't copied here, it gets updated // twice and ends up with the wrong value. farCamera->setViewport(simgear::clone(camera->getViewport())); - _viewer->addSlave(farCamera, view, projection, useMasterSceneData); + farCamera->setDrawBuffer(camera->getDrawBuffer()); + farCamera->setReadBuffer(camera->getReadBuffer()); + farCamera->setRenderTargetImplementation( + camera->getRenderTargetImplementation()); + const Camera::BufferAttachmentMap& bufferMap + = camera->getBufferAttachmentMap(); + if (bufferMap.count(Camera::COLOR_BUFFER) != 0) { + farCamera->attach( + Camera::COLOR_BUFFER, + bufferMap.find(Camera::COLOR_BUFFER)->second._texture); + } + _viewer->addSlave(farCamera, projection, view, useMasterSceneData); installCullVisitor(farCamera); info->farCamera = farCamera; info->farSlaveIndex = _viewer->getNumSlaves() - 1; @@ -156,7 +171,7 @@ CameraInfo* CameraGroup::addCamera(unsigned flags, Camera* camera, camera->setCullMask(camera->getCullMask() & ~simgear::BACKGROUND_BIT); camera->setClearMask(GL_DEPTH_BUFFER_BIT); } - _viewer->addSlave(camera, view, projection, useMasterSceneData); + _viewer->addSlave(camera, projection, view, useMasterSceneData); installCullVisitor(camera); info->camera = camera; info->slaveIndex = _viewer->getNumSlaves() - 1; @@ -297,6 +312,199 @@ void buildViewport(flightgear::CameraInfo* info, SGPropertyNode* viewportNode, namespace flightgear { +// Mostly copied from osg's osgViewer/View.cpp + +static osg::Geometry* createParoramicSphericalDisplayDistortionMesh( + const Vec3& origin, const Vec3& widthVector, const Vec3& heightVector, + double sphere_radius, double collar_radius, + Image* intensityMap = 0, const Matrix& projectorMatrix = Matrix()) +{ + 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 flip = false; + bool texcoord_flip = false; + + osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance); + + + OSG_INFO<<"createParoramicSphericalDisplayDistortionMesh : Projector position = "<getStringValue(); + TextureMap::iterator itr = _textureTargets.find(texName); + if (itr == _textureTargets.end()) { + // error + return; + } + Viewport* viewport = camera->getViewport(); + float width = viewport->width(); + float height = viewport->height(); + TextureRectangle* texRect = itr->second.get(); + double radius = psNode->getDoubleValue("radius", 1.0); + double collar = psNode->getDoubleValue("collar", 0.45); + Geode* geode = new Geode(); + geode->addDrawable(createParoramicSphericalDisplayDistortionMesh( + Vec3(0.0f,0.0f,0.0f), Vec3(width,0.0f,0.0f), + 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. + StateSet* stateset = geode->getOrCreateStateSet(); + stateset->setTextureAttributeAndModes(0, texRect, StateAttribute::ON); + stateset->setMode(GL_LIGHTING, StateAttribute::OFF); + + TexMat* texmat = new TexMat; + texmat->setScaleByTextureRectangleSize(true); + stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON); +#if 0 + if (!applyIntensityMapAsColours && intensityMap) + { + stateset->setTextureAttributeAndModes(1, new osg::Texture2D(intensityMap), osg::StateAttribute::ON); + } +#endif + // add subgraph to render + camera->addChild(geode); + camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); + camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); + camera->setCullingMode(osg::CullSettings::NO_CULLING); + camera->setName("DistortionCorrectionCamera"); +} + CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode) { WindowBuilder *wBuild = WindowBuilder::getWindowBuilder(); @@ -390,13 +598,43 @@ CameraInfo* CameraGroup::buildCamera(SGPropertyNode* cameraNode) double sheary = cameraNode->getDoubleValue("shear-y", 0); pOff.makeTranslate(-shearx, -sheary, 0); } - CameraInfo* info = addCamera(cameraFlags, camera, pOff, vOff); + const SGPropertyNode* textureNode = cameraNode->getNode("texture"); + if (textureNode) { + string texName = textureNode->getStringValue("name"); + int tex_width = textureNode->getIntValue("width"); + int tex_height = textureNode->getIntValue("height"); + TextureRectangle* texture = new TextureRectangle; + + texture->setTextureSize(tex_width, tex_height); + texture->setInternalFormat(GL_RGB); + texture->setFilter(Texture::MIN_FILTER, Texture::LINEAR); + texture->setFilter(Texture::MAG_FILTER, Texture::LINEAR); + texture->setWrap(Texture::WRAP_S, Texture::CLAMP_TO_EDGE); + texture->setWrap(Texture::WRAP_T, Texture::CLAMP_TO_EDGE); + camera->setDrawBuffer(GL_FRONT); + camera->setReadBuffer(GL_FRONT); + camera->setRenderTargetImplementation(Camera::FRAME_BUFFER_OBJECT); + camera->attach(Camera::COLOR_BUFFER, texture); + _textureTargets[texName] = texture; + } else { + camera->setDrawBuffer(GL_BACK); + camera->setReadBuffer(GL_BACK); + } + const SGPropertyNode* psNode = cameraNode->getNode("panoramic-spherical"); + bool useMasterSceneGraph = !psNode; + CameraInfo* info = addCamera(cameraFlags, camera, vOff, pOff, + useMasterSceneGraph); // If a viewport isn't set on the camera, then it's hard to dig it // out of the SceneView objects in the viewer, and the coordinates // of mouse events are somewhat bizzare. SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true); buildViewport(info, viewportNode, window->gc->getTraits()); updateCameras(info); + // Distortion camera needs the viewport which is created by addCamera(). + if (psNode) { + info->flags = info->flags | VIEW_ABSOLUTE; + buildDistortionCamera(psNode, camera); + } return info; } diff --git a/src/Main/CameraGroup.hxx b/src/Main/CameraGroup.hxx index 79d0d33d4..1e18e28e1 100644 --- a/src/Main/CameraGroup.hxx +++ b/src/Main/CameraGroup.hxx @@ -17,6 +17,7 @@ #ifndef CAMERAGROUP_HXX #define CAMERAGROUP_HXX 1 +#include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include // For osgUtil::LineSegmentIntersector::Intersections, which is a typedef. #include @@ -178,6 +180,9 @@ public: /** Update camera properties after a resize event. */ void resized(); + + void buildDistortionCamera(const SGPropertyNode* psNode, + osg::Camera* camera); protected: CameraList _cameras; osg::ref_ptr _viewer; @@ -186,6 +191,8 @@ protected: float _zNear; float _zFar; float _nearField; + typedef std::map > TextureMap; + TextureMap _textureTargets; }; }