/* osgVisual test. distortionNG, experimental. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "extViewer.h" #include "distortionNG.h" #include #include #include #include #include #include #include #include #include #include "DistortionManipulator.h" extViewer::extViewer() : Viewer() { } extViewer::extViewer(osg::ArgumentParser& arguments) : Viewer(arguments) { // Add help for command-line options here arguments.getApplicationUsage()->addCommandLineOption("--distort","load distortion file and set up geometrical distortion for viewer. This includes blending"); arguments.getApplicationUsage()->addCommandLineOption("--blend","Set up viewer vor simple blending CullDrawThreadPerContext threading model for viewer."); osgDB::Registry::instance()->addFileExtensionAlias("dist", "osgt"); } extViewer::extViewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop) : Viewer(viewer, copyop) { } extViewer::~extViewer() { } static osg::Geometry* createMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, unsigned int columns, unsigned int rows, const osg::Matrix& projectorMatrix) { // Create Quad to render on osg::ref_ptr geom = new osg::Geometry; geom->setUseDisplayList( false ); osg::Vec3 xAxis(widthVector); float width = widthVector.length(); xAxis /= width; osg::Vec3 yAxis(heightVector); float height = heightVector.length(); yAxis /= height; osg::Vec3 dx = xAxis*(width/((float)(columns-1))); osg::Vec3 dy = yAxis*(height/((float)(rows-1))); // Create vertices and coordinates osg::Vec3Array* vertices = new osg::Vec3Array; osg::Vec2Array* texcoords0 = new osg::Vec2Array; osg::Vec4Array* colors = new osg::Vec4Array; geom->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); for ( unsigned int row=0; rowpush_back( origin+dy*row+dx*col ); // Create tex coordinates osg::Vec2 texcoord = osg::Vec2((float)col/(float)(columns-1), (float)row/(float)(rows-1)); // Set Coordinates for RTT-Texture (scene rendering) texcoords0->push_back( texcoord ); // Set Color of the mesh node colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); } } // Pass the created vertex array to the points geometry object. geom->setUseVertexBufferObjects( true ); geom->setVertexArray(vertices); geom->setColorArray(colors); geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX); geom->setTexCoordArray(0,texcoords0); // Quads grid for ( unsigned int row=0; row de = new osg::DrawElementsUInt(osg::PrimitiveSet::QUAD_STRIP, columns*2); // columns*2 = number of involved vertices for this strip. for ( unsigned int col=0; coladdPrimitiveSet( de.get() ); } //// Triangle grid //for ( unsigned int row=0; row de = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP, columns * 2 ); // for ( unsigned int col=0; coladdPrimitiveSet( de.get() ); //} return geom.release(); } void extViewer::setUpViewForManualDistortion(unsigned int screenNum, osg::Image* intensityMap, const osg::Matrixd& projectorMatrix) { OSG_INFO<<"View::setUpViewForManualDistortion(sn="<setIntensityMap( intensityMap ); _distortionSet->setDistortionMeshRows( 20 ); _distortionSet->setDistortionMeshColumns( 20 ); osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { OSG_NOTICE<<"Error, no WindowSystemInterface available, cannot create windows."<getScreenResolution(si, width, height); 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_NOTICE<<"GraphicsWindow has not been created successfully."<getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar); double newAspectRatio = double(traits->width) / double(traits->height); double aspectRatioChange = newAspectRatio / aspectRatio; if (aspectRatioChange != 1.0) { _camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0); } int tex_width = width; int tex_height = height; int camera_width = tex_width; int camera_height = tex_height; osg::TextureRectangle* sceneTexture = new osg::TextureRectangle; sceneTexture->setTextureSize(tex_width, tex_height); sceneTexture->setInternalFormat(GL_RGB); sceneTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); sceneTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); sceneTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE); sceneTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE); #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 // Scene camera { osg::ref_ptr camera = new osg::Camera; camera->setName("Scene cam"); 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, sceneTexture); addSlave(camera.get(), osg::Matrixd(), osg::Matrixd()); } // distortion correction set up. { osg::Geode* geode = new osg::Geode(); // new we need to add the scene texture to the mesh, we do so by creating a // StateSet to contain the Texture StateAttribute. osg::StateSet* stateset = geode->getOrCreateStateSet(); stateset->setTextureAttributeAndModes(_distortionSet->getTexUnitScene(), sceneTexture,osg::StateAttribute::ON); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); osg::TexMat* texmat = new osg::TexMat; texmat->setScaleByTextureRectangleSize(true); stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON); setUpIntensityMapBlending(_distortionSet, stateset, screenNum); osg::Geometry* distortionMesh = createMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), 20, 20, projectorMatrix); geode->addDrawable(distortionMesh); 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.0,0.0,0.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()); // selector geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); geode->getOrCreateStateSet()->setAttributeAndModes( new osg::PolygonOffset(1.0f, 1.0f) ); osg::ref_ptr selectorHandler = new distortionHandler( camera, distortionMesh ); osg::ref_ptr root = new osg::Group; root->addChild(geode); osg::Geode* selectorHighlighter = selectorHandler->createVertexHighlighter(); selectorHighlighter->setCullingActive(false); // disable the culling for the selector, otherwise the selector is culled away on the edge. root->addChild(selectorHighlighter); addEventHandler( selectorHandler.get() ); camera->addChild(root); // Avoid that the highlighter is culled away osg::CullSettings::CullingMode mode = camera->getCullingMode(); camera->setCullingMode( mode & (~osg::CullSettings::SMALL_FEATURE_CULLING) ); // Add the distortionHandler osgViewer::DistortionManipulator* distManip = new osgViewer::DistortionManipulator(); distManip->setDistortionSet(_distortionSet); addEventHandler(distManip); camera->setName("Dist Cam"); addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); } } void extViewer::setUpIntensityMapBlending(osgViewer::DistortionSet* distSet, osg::StateSet* stateset, unsigned int screenNum) { osg::Image* intensityMap = _distortionSet->getIntensityMap(); if(intensityMap == NULL) return; if(stateset == NULL) { OSG_NOTICE<<"Error, no intensityMap or stateset for intensityMapBlending specified."<getScreenResolution(si, width, height); // Resize intensityMap if the dimensions are wrong if(intensityMap->s()!=width || intensityMap->t()!=height) intensityMap->scaleImage(width, height, intensityMap->r()); osg::TextureRectangle* intensityMapTexture = new osg::TextureRectangle(intensityMap); intensityMapTexture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); intensityMapTexture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR); intensityMapTexture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE); intensityMapTexture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE); stateset->setTextureAttributeAndModes(_distortionSet->getTexUnitIntensityMap(), intensityMapTexture, osg::StateAttribute::ON); // create shaders for blending osg::Program* distortProgram = new osg::Program; distortProgram->setName( "intensityMapBlending" ); osg::Shader* fShader = osg::Shader::readShaderFile( osg::Shader::FRAGMENT, "shader.frag" ); fShader->setName("intensityMapFragShader"); if ( fShader ) { distortProgram->addShader( fShader ); stateset->addUniform( new osg::Uniform("sceneTexture", (int)_distortionSet->getTexUnitScene()) ); stateset->addUniform( new osg::Uniform("intensityMapTexture", (int)_distortionSet->getTexUnitIntensityMap()) ); stateset->setAttributeAndModes(distortProgram, osg::StateAttribute::ON); } } void extViewer::setUpIntensityMapBlending(std::string intensityMap) { // Try to load intensityMap osg::Image* intMap = osgDB::readImageFile(intensityMap); if (!intMap) { osg::notify(osg::WARN) << "Quitting, couldn't find intensity map: " << intensityMap << std::endl; return; } // Create DistortionSet _distortionSet = new osgViewer::DistortionSet(); _distortionSet->setIntensityMap( intMap ); _distortionSet->setDistortionMeshRows( 1 ); _distortionSet->setDistortionMeshColumns( 1 ); _distortionSet->setTexUnitScene( 0 ); _distortionSet->setTexUnitIntensityMap( 1 ); // Todo: call setupDistortion/Blendung to perform the blending }