Show
Ignore:
Timestamp:
05/08/07 14:18:57 (8 years ago)
Author:
robert
Message:

Firt cut at full dome correction of wrap around movies and imagery

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/examples/osgmovie/osgmovie.cpp

    r5953 r6624  
    1111#include <osg/Texture2D> 
    1212#include <osg/TextureRectangle> 
     13#include <osg/TextureCubeMap> 
    1314#include <osg/TexMat> 
    1415#include <osg/CullFace> 
     
    2627public: 
    2728 
    28     MovieEventHandler() {} 
     29    MovieEventHandler():_trackMouse(false) {} 
     30     
     31    void setMouseTracking(bool track) { _trackMouse = track; } 
     32    bool getMouseTracking() const { return _trackMouse; } 
    2933     
    3034    void set(osg::Node* node); 
     
    9296 
    9397 
     98    bool            _trackMouse; 
    9499    ImageStreamList _imageStreamList; 
    95100     
     
    117122        case(osgGA::GUIEventAdapter::RELEASE): 
    118123        { 
    119  
    120             osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); 
    121             osgUtil::LineSegmentIntersector::Intersections intersections; 
    122             if (view && view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections)) 
    123             { 
    124  
    125                 // use the nearest intersection                  
    126                 const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin()); 
    127                 osg::Drawable* drawable = intersection.drawable.get(); 
    128                 osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0; 
    129                 osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0; 
    130                 if (vertices) 
    131                 { 
    132                     // get the vertex indices. 
    133                     const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList; 
    134                     const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList; 
    135  
    136                     if (indices.size()==3 && ratios.size()==3) 
     124            if (_trackMouse) 
     125            { 
     126                osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); 
     127                osgUtil::LineSegmentIntersector::Intersections intersections; 
     128                if (view && view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections)) 
     129                { 
     130 
     131                    // use the nearest intersection                  
     132                    const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin()); 
     133                    osg::Drawable* drawable = intersection.drawable.get(); 
     134                    osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0; 
     135                    osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0; 
     136                    if (vertices) 
    137137                    { 
    138                         unsigned int i1 = indices[0]; 
    139                         unsigned int i2 = indices[1]; 
    140                         unsigned int i3 = indices[2]; 
    141  
    142                         float r1 = ratios[0]; 
    143                         float r2 = ratios[1]; 
    144                         float r3 = ratios[2]; 
    145  
    146                         osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0; 
    147                         osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords); 
    148                         if (texcoords_Vec2Array) 
     138                        // get the vertex indices. 
     139                        const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList; 
     140                        const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList; 
     141 
     142                        if (indices.size()==3 && ratios.size()==3) 
    149143                        { 
    150                             // we have tex coord array so now we can compute the final tex coord at the point of intersection.                                 
    151                             osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1]; 
    152                             osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2]; 
    153                             osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3]; 
    154                             osg::Vec2 tc = tc1*r1 + tc2*r2 + tc3*r3; 
    155  
    156                             osg::notify(osg::NOTICE)<<"We hit tex coords "<<tc<<std::endl; 
    157  
     144                            unsigned int i1 = indices[0]; 
     145                            unsigned int i2 = indices[1]; 
     146                            unsigned int i3 = indices[2]; 
     147 
     148                            float r1 = ratios[0]; 
     149                            float r2 = ratios[1]; 
     150                            float r3 = ratios[2]; 
     151 
     152                            osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0; 
     153                            osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords); 
     154                            if (texcoords_Vec2Array) 
     155                            { 
     156                                // we have tex coord array so now we can compute the final tex coord at the point of intersection.                                 
     157                                osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1]; 
     158                                osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2]; 
     159                                osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3]; 
     160                                osg::Vec2 tc = tc1*r1 + tc2*r2 + tc3*r3; 
     161 
     162                                osg::notify(osg::NOTICE)<<"We hit tex coords "<<tc<<std::endl; 
     163 
     164                            } 
    158165                        } 
     166                        else 
     167                        { 
     168                            osg::notify(osg::NOTICE)<<"Intersection has insufficient indices to work with"; 
     169                        } 
     170 
    159171                    } 
    160                     else 
    161                     { 
    162                         osg::notify(osg::NOTICE)<<"Intersection has insufficient indices to work with"; 
    163                     } 
    164  
    165172                } 
    166             } 
    167             else 
    168             { 
    169                 osg::notify(osg::NOTICE)<<"No intersection"<<std::endl; 
     173                else 
     174                { 
     175                    osg::notify(osg::NOTICE)<<"No intersection"<<std::endl; 
     176                } 
    170177            } 
    171178            break; 
     
    277284} 
    278285 
     286osg::Geometry* createDomeDistortionMesh(const osg::Vec3& origin, const osg::Vec3& widthVector, const osg::Vec3& heightVector, 
     287                                        osg::ArgumentParser& arguments) 
     288{ 
     289    double sphere_radius = 1.0; 
     290    if (arguments.read("--radius", sphere_radius)) {} 
     291 
     292    double collar_radius = 0.45; 
     293    if (arguments.read("--collar", collar_radius)) {} 
     294 
     295    osg::Vec3d center(0.0,0.0,0.0); 
     296    osg::Vec3d eye(0.0,0.0,0.0); 
     297     
     298    double distance = sqrt(sphere_radius*sphere_radius - collar_radius*collar_radius); 
     299    if (arguments.read("--distance", distance)) {} 
     300     
     301    bool centerProjection = false; 
     302 
     303    osg::Vec3d projector = eye - osg::Vec3d(0.0,0.0, distance); 
     304     
     305     
     306    osg::notify(osg::NOTICE)<<"Projector position = "<<projector<<std::endl; 
     307    osg::notify(osg::NOTICE)<<"distance = "<<distance<<std::endl; 
     308 
     309 
     310    // create the quad to visualize. 
     311    osg::Geometry* geometry = new osg::Geometry(); 
     312 
     313    geometry->setSupportsDisplayList(false); 
     314 
     315    osg::Vec3 xAxis(widthVector); 
     316    float width = widthVector.length(); 
     317    xAxis /= width; 
     318 
     319    osg::Vec3 yAxis(heightVector); 
     320    float height = heightVector.length(); 
     321    yAxis /= height; 
     322     
     323    int noSteps = 50; 
     324 
     325    osg::Vec3Array* vertices = new osg::Vec3Array; 
     326    osg::Vec2Array* texcoords = new osg::Vec2Array; 
     327    osg::Vec4Array* colors = new osg::Vec4Array; 
     328 
     329    osg::Vec3 bottom = origin; 
     330    osg::Vec3 dx = xAxis*(width/((float)(noSteps-1))); 
     331    osg::Vec3 dy = yAxis*(height/((float)(noSteps-1))); 
     332     
     333    osg::Vec3d screenCenter = origin + widthVector*0.5f + heightVector*0.5f; 
     334    float screenRadius = heightVector.length() * 0.5f; 
     335 
     336    osg::Vec3 cursor = bottom; 
     337    int i,j; 
     338     
     339    for(i=0;i<noSteps;++i) 
     340    { 
     341        osg::Vec3 cursor = bottom+dy*(float)i; 
     342        for(j=0;j<noSteps;++j) 
     343        { 
     344            osg::Vec2 delta(cursor.x() - screenCenter.x(), cursor.y() - screenCenter.y()); 
     345            double theta = atan2(delta.x(), delta.y()); 
     346            if (theta<0.0) theta += 2*osg::PI; 
     347            double phi = osg::PI_2 * delta.length() / screenRadius; 
     348            if (phi > osg::PI_2) phi = osg::PI_2; 
     349 
     350            double f = distance * sin(phi); 
     351            double e = distance * cos(phi) + sqrt( sphere_radius*sphere_radius - f*f); 
     352            double l = e * cos(phi); 
     353            double h = e * sin(phi); 
     354            double gamma = atan2(h, l-distance); 
     355 
     356            osg::Vec2 texcoord(theta/(2.0*osg::PI), 1.0-gamma/osg::PI); 
     357 
     358            osg::notify(osg::NOTICE)<<"cursor = "<<cursor<< " theta = "<<theta<< "phi="<<phi<<" gamma = "<<gamma<<" texcoord="<<texcoord<<std::endl; 
     359 
     360            vertices->push_back(cursor); 
     361            colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); 
     362            texcoords->push_back(texcoord); 
     363 
     364            cursor += dx; 
     365        } 
     366        // osg::notify(osg::NOTICE)<<std::endl; 
     367    } 
     368     
     369    // pass the created vertex array to the points geometry object. 
     370    geometry->setVertexArray(vertices); 
     371 
     372    geometry->setColorArray(colors); 
     373    geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX); 
     374 
     375    geometry->setTexCoordArray(0,texcoords); 
     376 
     377    for(i=0;i<noSteps-1;++i) 
     378    { 
     379        osg::DrawElementsUShort* elements = new osg::DrawElementsUShort(osg::PrimitiveSet::QUAD_STRIP); 
     380        for(j=0;j<noSteps;++j) 
     381        { 
     382            elements->push_back(j+(i+1)*noSteps); 
     383            elements->push_back(j+(i)*noSteps); 
     384        } 
     385        geometry->addPrimitiveSet(elements); 
     386    } 
     387     
     388    return geometry; 
     389} 
     390 
     391 
     392void setDomeCorrection(osgViewer::Viewer& viewer, osg::ArgumentParser& arguments) 
     393{ 
     394    // enforce single threading right now to avoid double buffering of RTT texture 
     395    viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded); 
     396  
     397    osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); 
     398    if (!wsi)  
     399    { 
     400        osg::notify(osg::NOTICE)<<"Error, no WindowSystemInterface available, cannot create windows."<<std::endl; 
     401        return; 
     402    } 
     403 
     404    unsigned int width, height; 
     405    wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), width, height); 
     406 
     407    while (arguments.read("--width",width)) {} 
     408    while (arguments.read("--height",height)) {} 
     409 
     410    osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; 
     411    traits->x = 0; 
     412    traits->y = 0; 
     413    traits->width = width; 
     414    traits->height = height; 
     415    traits->windowDecoration = false; 
     416    traits->doubleBuffer = true; 
     417    traits->sharedContext = 0; 
     418     
     419     
     420 
     421    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 
     422    if (!gc) 
     423    { 
     424        osg::notify(osg::NOTICE)<<"GraphicsWindow has not been created successfully."<<std::endl; 
     425        return; 
     426    } 
     427 
     428    osg::ref_ptr<osg::Drawable> distortionCorrectionMash = createDomeDistortionMesh(osg::Vec3(0.0f,0.0f,0.0f), osg::Vec3(width,0.0f,0.0f), osg::Vec3(0.0f,height,0.0f), arguments); 
     429 
     430    osg::Texture* texture = 0; 
     431    for(int i=1;i<arguments.argc() && !texture;++i) 
     432    { 
     433        if (arguments.isString(i)) 
     434        { 
     435            osg::Image* image = osgDB::readImageFile(arguments[i]); 
     436            osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image); 
     437            if (imagestream) imagestream->play(); 
     438 
     439            if (image) 
     440            { 
     441#if 0             
     442                texture = new osg::TextureRectangle(image); 
     443#else 
     444                texture = new osg::Texture2D(image); 
     445#endif 
     446            } 
     447        } 
     448    } 
     449     
     450    if (!texture) 
     451    { 
     452        return; 
     453    } 
     454 
     455    // distortion correction set up. 
     456    { 
     457        osg::Geode* geode = new osg::Geode(); 
     458        geode->addDrawable(distortionCorrectionMash.get()); 
     459 
     460        // new we need to add the texture to the mesh, we do so by creating a  
     461        // StateSet to contain the Texture StateAttribute. 
     462        osg::StateSet* stateset = geode->getOrCreateStateSet(); 
     463        stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON); 
     464        stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); 
     465#if 0         
     466        osg::TexMat* texmat = new osg::TexMat; 
     467        texmat->setScaleByTextureRectangleSize(true); 
     468        stateset->setTextureAttributeAndModes(0, texmat, osg::StateAttribute::ON); 
     469#endif 
     470        osg::ref_ptr<osg::Camera> camera = new osg::Camera; 
     471        camera->setGraphicsContext(gc.get()); 
     472        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); 
     473        camera->setClearColor( osg::Vec4(0.1,0.1,1.0,1.0) ); 
     474        camera->setViewport(new osg::Viewport(0, 0, width, height)); 
     475        GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT; 
     476        camera->setDrawBuffer(buffer); 
     477        camera->setReadBuffer(buffer); 
     478        camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 
     479        camera->setAllowEventFocus(false); 
     480        //camera->setInheritanceMask(camera->getInheritanceMask() & ~osg::CullSettings::CLEAR_COLOR & ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE); 
     481        //camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); 
     482         
     483        camera->setProjectionMatrixAsOrtho2D(0,width,0,height); 
     484        camera->setViewMatrix(osg::Matrix::identity()); 
     485 
     486        // add subgraph to render 
     487        camera->addChild(geode); 
     488         
     489        camera->setName("DistortionCorrectionCamera"); 
     490 
     491        viewer.addSlave(camera.get(), osg::Matrixd(), osg::Matrixd(), false); 
     492    } 
     493     
     494    viewer.getCamera()->setNearFarRatio(0.0001f); 
     495} 
     496 
    279497int main(int argc, char** argv) 
    280498{ 
     
    289507    arguments.getApplicationUsage()->addCommandLineOption("--texture2D","Use Texture2D rather than TextureRectangle."); 
    290508    arguments.getApplicationUsage()->addCommandLineOption("--shader","Use shaders to post process the video."); 
     509    arguments.getApplicationUsage()->addCommandLineOption("--dome","Use full dome distortion correction."); 
    291510     
    292511    bool useTextureRectangle = true; 
     
    351570 
    352571 
    353     for(int i=1;i<arguments.argc();++i) 
    354     { 
    355         if (arguments.isString(i)) 
    356         { 
    357             osg::Image* image = osgDB::readImageFile(arguments[i]); 
    358             osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image); 
    359             if (imagestream) imagestream->play(); 
    360              
    361             if (image) 
    362             { 
    363                 geode->addDrawable(myCreateTexturedQuadGeometry(pos,image->s(),image->t(),image, useTextureRectangle)); 
    364                  
    365                 pos.z() += image->t()*1.5f; 
    366             } 
    367             else 
    368             { 
    369                 std::cout<<"Unable to read file "<<arguments[i]<<std::endl; 
    370             }             
    371         } 
    372     } 
    373      
    374     if (geode->getNumDrawables()==0) 
    375     { 
    376         // nothing loaded. 
    377         arguments.getApplicationUsage()->write(std::cout); 
    378         return 1; 
    379     } 
     572    if (arguments.read("--dome") || arguments.read("--puffer") ) 
     573    {     
     574        setDomeCorrection(viewer, arguments); 
     575    } 
     576    else 
     577    { 
     578        for(int i=1;i<arguments.argc();++i) 
     579        { 
     580            if (arguments.isString(i)) 
     581            { 
     582                osg::Image* image = osgDB::readImageFile(arguments[i]); 
     583                osg::ImageStream* imagestream = dynamic_cast<osg::ImageStream*>(image); 
     584                if (imagestream) imagestream->play(); 
     585 
     586                if (image) 
     587                { 
     588                    geode->addDrawable(myCreateTexturedQuadGeometry(pos,image->s(),image->t(),image, useTextureRectangle)); 
     589 
     590                    pos.z() += image->t()*1.5f; 
     591                } 
     592                else 
     593                { 
     594                    std::cout<<"Unable to read file "<<arguments[i]<<std::endl; 
     595                }             
     596            } 
     597        } 
     598        if (!viewer.getSceneData()) 
     599        { 
     600            arguments.getApplicationUsage()->write(std::cout); 
     601            return 1; 
     602        } 
     603    } 
     604     
    380605 
    381606    // pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate. 
    382607    MovieEventHandler* meh = new MovieEventHandler(); 
    383608    geode->setEventCallback(meh); 
    384     meh->set(geode.get()); 
     609    meh->set(viewer.getSceneData()); 
    385610 
    386611    // report any errors if they have occured when parsing the program aguments. 
     
    397622    } 
    398623 
     624 
    399625    // set the scene to render 
    400626    viewer.setSceneData(geode.get());