/* 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 "DistortionManipulator.h" #include "extViewer.h" #include #include #include #include #include #include #include #include "DistortionSetupStrategy.h" using namespace osg; using namespace osgViewer; DistortionManipulator::DistortionManipulator(extViewer* viewer, DistortionSet* ds) : _highlightColor( osg::Vec4(1.0f, 1.0f, 0.0f, 1.0f) ), _distortionSet( ds ), _viewer(viewer) { activeSetupMode = DISABLED; activeDistortionMode = MESH; activeManualSetupMode = DISTORTION; activeVisualizationMode = NONE; _delegatedDistortionSetupStrategy = NULL; _highlighter = NULL; createVertexHighlighter(); createHUD(); _camera = 0; //_distortionMesh(distortionMesh) // Create Shader to visualize intensitymap during blending setup. osg::Shader* sh = osg::Shader::readShaderFile( osg::Shader::FRAGMENT, "shaderIntensityMapVis.frag" ); sh->setName("shaderIntensityMapVis"); ds->setShaderIntensityMapVis( sh ); //LF Get Screen Resolution for Cursor Position Scaling osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), _screenPixWidth, _screenPixHeight); } DistortionManipulator::~DistortionManipulator() { } void DistortionManipulator::getUsage(osg::ApplicationUsage& usage) const { usage.addKeyboardMouseBinding("Keypad 0","Show/Hide distortion HUD."); usage.addKeyboardMouseBinding("Keypad 1","Reset distortion."); usage.addKeyboardMouseBinding("Keypad 2","Reset intensity blending."); usage.addKeyboardMouseBinding("Keypad 4","Toggles Setup Mode between DISABLED, MANUAL & DELEGATED."); usage.addKeyboardMouseBinding("Keypad 5","MANUAL Mode: Toggle between blending & distortion setup."); usage.addKeyboardMouseBinding("Keypad 6","MANUAL Mode: Toggle if distortion drags affect mesh or rtt texture coordinates."); // Defaults to Mesh usage.addKeyboardMouseBinding("Keypad 7","Show distortion mesh / intensity map / none."); usage.addKeyboardMouseBinding("Keypad 8","Save distortion set."); // via plugin } bool DistortionManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv) { switch(ea.getEventType()) { case(osgGA::GUIEventAdapter::MOVE): break; case(osgGA::GUIEventAdapter::DRAG): { if ( activeSetupMode == MANUAL) { OSG_ALWAYS<(&aa); if ( viewer ) { osg::notify(osg::ALWAYS)<getDistortionInternals()->setValue(DistortionSet::HIGHLIGHTER, true); break; } case MANUAL : { activeSetupMode = DELEGATED; _distortionSet->getDistortionInternals()->setValue(DistortionSet::HIGHLIGHTER, false); OSG_NOTICE<<"SetupMode DELEGATED activated"<getDistortionInternals()->setValue(DistortionSet::HIGHLIGHTER, false); OSG_NOTICE<<"SetupMode DISABLED activated"< defaults to Mesh { activeDistortionMode = (activeDistortionMode==MESH?TEXCOORDINATES:MESH); updateHUD(); return(true); } if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Home) // KP 7: Show distortion mesh / intensity map / none. { switch(activeVisualizationMode) { case DISTORTION_MESH : { activeVisualizationMode = INTENSITY_MAP; showDistortionMesh(false); showIntensityMap(true); break; } case INTENSITY_MAP : { activeVisualizationMode = NONE; showDistortionMesh(false); showIntensityMap(false); break; } case NONE : { activeVisualizationMode = DISTORTION_MESH; showDistortionMesh(true); showIntensityMap(false); break; } } updateHUD(); return(true); } if (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Up) // KP 8: Save distortion set via plugin { OSG_ALWAYS<<"KEY_KP_8 : todo: Save DistortionContainer"<delegateDistortionSetup(_distortionSet); if( _distortionSet->isDirty() && _viewer.valid()) { updateDistortionSetup(); } //OSG_ALWAYS<<"..done"< image = _distortionSet->getIntensityMap(); OSG_ALWAYS<<"Reseting IntensityMap Blending."<isDataContiguous()) { OSG_WARN<<"Warning: DistortionManipulator does not support working with non contiguous imagery as blendmaps!"<data(); for(unsigned int i=0;igetTotalSizeInBytes();i++) { *dataPtr++ = 255; } image->dirty(); } void DistortionManipulator::resetDistortion() { if(!_distortionSet.valid()) return; _distortionSet->setDistortionMeshDimensions(2, 2, true); // Reset dimensions and coordinates/texcoords & rebuild mesh data _distortionSet->dirtyMesh(); // Restore ProjectionMatrix // Set up basic projection Matrix double fovy = 30., aspectRatio = 1., zNear = 1., zFar = 1000.; _distortionSet->getProjectionOffset().makePerspective( fovy, aspectRatio, zNear, zFar ); double newAspectRatio = double(_distortionSet->getIntensityMap()->s()) / double(_distortionSet->getIntensityMap()->t()); double aspectRatioChange = newAspectRatio / aspectRatio; if (aspectRatioChange != 1.0) { _distortionSet->getProjectionOffset() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0); } _distortionSet->dirtyMatrix(); } void DistortionManipulator::showDistortionMesh(bool show) { osg::StateSet* stateset = _distortionSet->getDistortionInternals()->getChild(DistortionSet::MESH)->getOrCreateStateSet(); // Append a PolygonMode stateset if required osg::PolygonMode* polyModeObj = dynamic_cast(stateset->getAttribute(osg::StateAttribute::POLYGONMODE)); if (!polyModeObj) { polyModeObj = new osg::PolygonMode; stateset->setAttribute(polyModeObj, osg::StateAttribute::PROTECTED|osg::StateAttribute::ON); } // Set Polygonmode if(show) polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); else polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::FILL); } void DistortionManipulator::showIntensityMap(bool show) { if(_distortionSet.valid()) { osg::StateSet* stateset = _distortionSet->getDistortionInternals()->getChild(DistortionSet::MESH)->getOrCreateStateSet(); osg::Program* program = static_cast(stateset->getAttribute(::osg::StateAttribute::PROGRAM)); if(show) { program->removeShader( _distortionSet->getShaderIntensityMap() ); program->addShader( _distortionSet->getShaderIntensityMapVis() ); } else { program->removeShader( _distortionSet->getShaderIntensityMapVis() ); program->addShader( _distortionSet->getShaderIntensityMap() ); } } } void DistortionManipulator::createVertexHighlighter() { osg::ref_ptr colors = new osg::Vec4Array(1); (*colors)[0] = _highlightColor; _highlighter = new osg::Geometry; _highlighter->setDataVariance( osg::Object::DYNAMIC ); _highlighter->setUseDisplayList( false ); _highlighter->setUseVertexBufferObjects( true ); _highlighter->setVertexArray( new osg::Vec3Array(1) ); // The highlighter vertex is updated by computeSelectedVertex(..) _highlighter->setColorArray( colors.get() ); _highlighter->setColorBinding( osg::Geometry::BIND_OVERALL ); _highlighter->addPrimitiveSet( new osg::DrawArrays(GL_POINTS, 0, 1) ); osg::ref_ptr geode = new osg::Geode; geode->addDrawable( _highlighter.get() ); geode->getOrCreateStateSet()->setAttributeAndModes( new osg::Point(8.0f) ); geode->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); geode->setCullingActive(false); // disable the culling for the selector, otherwise the selector is culled away on the edge. _distortionSet->getDistortionInternals()->addChild(geode, false); // = child #1 :definition: child #0 = mesh, #1 = highlighter, #2 HUD } void DistortionManipulator::createHUD() { osg::ref_ptr geode = new osg::Geode; osg::StateSet* stateSet = geode->getOrCreateStateSet(); stateSet->setRenderBinDetails( 99, "RenderBin"); // disable depth test to ensure that it is always drawn. stateSet->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); stateSet->setMode(GL_LIGHTING,osg::StateAttribute::OFF); // Modify StateSet to protect it against state changes by the stateset Manipulator osg::PolygonMode* polyModeObj = new osg::PolygonMode; stateSet->setAttribute(polyModeObj, osg::StateAttribute::PROTECTED|osg::StateAttribute::ON); // Add Text: osg::Vec3 position(20.0f,120.0f,0.0f); osg::Vec3 delta(0.0f,-25.0f,0.0f); std::string timesFont("fonts/arial.ttf"); { osg::ref_ptr textHeader = new osgText::Text; textHeader->setText("Distortion Setup:"); textHeader->setFont(timesFont); textHeader->setPosition(position); textHeader->setCharacterSize(21); textHeader->setDataVariance(osg::Object::STATIC); geode->addDrawable( textHeader ); position += delta; hudSetupMode = new osgText::Text; hudSetupMode->setFont(timesFont); hudSetupMode->setPosition(position); hudSetupMode->setCharacterSize(21); hudSetupMode->setDataVariance(osg::Object::DYNAMIC); geode->addDrawable( hudSetupMode ); position += delta; hudDistortionMode = new osgText::Text; hudDistortionMode->setFont(timesFont); hudDistortionMode->setPosition(position); hudDistortionMode->setCharacterSize(21); hudDistortionMode->setDataVariance(osg::Object::DYNAMIC); geode->addDrawable( hudDistortionMode ); position += delta; hudManualSetupMode = new osgText::Text; hudManualSetupMode->setFont(timesFont); hudManualSetupMode->setPosition(position); hudManualSetupMode->setCharacterSize(21); hudManualSetupMode->setDataVariance(osg::Object::DYNAMIC); geode->addDrawable( hudManualSetupMode ); position += delta; hudVisualizationMode = new osgText::Text; hudVisualizationMode->setFont(timesFont); hudVisualizationMode->setPosition(position); hudVisualizationMode->setCharacterSize(21); hudVisualizationMode->setDataVariance(osg::Object::DYNAMIC); geode->addDrawable( hudVisualizationMode ); } updateHUD(); _distortionSet->getDistortionInternals()->addChild(geode, false); // = child #2. The definition is: child #0 = mesh, #1 = highlighter, #2 HUD } void DistortionManipulator::updateHUD() { switch(activeSetupMode) { case DISABLED : hudSetupMode->setText("Setup Mode : DISABLED"); break; case MANUAL : hudSetupMode->setText("Setup Mode : MANUAL"); break; case DELEGATED : hudSetupMode->setText("Setup Mode : DELEGATED"); break; default: hudSetupMode->setText(""); }; switch(activeDistortionMode) { case MESH : hudDistortionMode->setText("Distortion Mode : MESH"); break; case TEXCOORDINATES : hudDistortionMode->setText("Distortion Mode : TEXCOORDINATES"); break; default: hudDistortionMode->setText(""); }; switch(activeManualSetupMode) { case DISTORTION : hudManualSetupMode->setText("Manual Setup Mode : DISTORTION"); break; case BLENDING : hudManualSetupMode->setText("Manual Setup Mode : BLENDING"); break; default: hudManualSetupMode->setText(""); }; switch(activeVisualizationMode) { case DISTORTION_MESH : hudVisualizationMode->setText("Visualization Mode : DISTORTION_MESH"); break; case INTENSITY_MAP : hudVisualizationMode->setText("Visualization Mode : INTENSITY_MAP"); break; case NONE : hudVisualizationMode->setText("Visualization Mode : NONE"); break; default: hudVisualizationMode->setText(""); }; } void DistortionManipulator::computeSelectedVertex( osgUtil::LineSegmentIntersector::Intersection& result ) { osg::Geometry* geom = dynamic_cast( result.drawable.get() ); if ( !geom || geom==_highlighter ) return; osg::Vec3Array* vertices = dynamic_cast( geom->getVertexArray() ); osg::Vec3Array* selVertices = dynamic_cast( _highlighter->getVertexArray() ); if ( !vertices || !selVertices ) return; OSG_NOTIFY(osg::ALWAYS)<<"size of vertices="<size()<getCameraManipulator()==NULL) { _viewer->getCamera()->setViewMatrix(viewMatrix); } else { _viewer->getCameraManipulator()->setByMatrix(osg::Matrixd::inverse(viewMatrix)); } /**************************************/ /*** End of Testcase "Garching" ***/ /**************************************/ #endif _viewer->getCamera()->setProjectionMatrix(osg::Matrix::identity()); // Get slave struct to update the offset matrixes. //Slave Camera Settings osgViewer::View::Slave* sceneSlave = _viewer->findSlaveForCamera( _distortionSet->getSceneCamera() ); sceneSlave->_projectionOffset = _distortionSet->getProjectionOffset(); sceneSlave->_viewOffset = _distortionSet->getViewOffset(); #if 0 // Print viewMatrixAsLookAt for Debug Purposes osg::Vec3 Eye,Focus,Vertical; _viewer->getCamera()->getViewMatrixAsLookAt(Eye,Focus,Vertical); OSG_ALWAYS<<"Camera Eyepoint: X:"<getDistortionMesh()->size();i++) { osg::Vec4 tmpSrc = _distortionSet->getDistortionMesh()->at(i); // Scale vector with the screen resolution osg::Vec3 tmpVec = osg::Vec3( tmpSrc.x()*_screenPixWidth, tmpSrc.y()*_screenPixHeight, 0.0 ); vertices->push_back( tmpVec ); //OSG_ALWAYS<<"Transfering mesh vertex : X:"<push_back(tmpTexCoords); //OSG_ALWAYS<<"Transfering texcoord vertex : X:"<push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); } // --------- Apply Arrays ----------------- osg::Geometry* geom = _distortionSet->getDistortionInternals()->getChild(osgViewer::DistortionSet::MESH)->asGeode()->getDrawable(0)->asGeometry(); // If arraysize differs: Replace primite sets bool regeneratePrimitiveSets = true; osg::Vec3Array* prevArray = dynamic_cast(geom->getVertexArray()); if(prevArray) regeneratePrimitiveSets = prevArray->size()!=vertices->size()?true:false; // Set new Arrays geom->setVertexArray(vertices); geom->setTexCoordArray(0, texCoords); // todo: 0 ist hardcoded und müsste durch getTexUnitScene() ersetzt werden geom->setColorArray(colors); // If required: regenerate primitiveset: OSG_ALWAYS<<"PrimitiveSet regeneration required!"<removePrimitiveSet(0, geom->getNumPrimitiveSets()); //// Create new primitives : Quads grid unsigned int rows = _distortionSet->getDistortionMeshRows(); unsigned int columns = _distortionSet->getDistortionMeshColumns(); 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() ); } }