Show
Ignore:
Timestamp:
11/03/08 16:58:02 (5 years ago)
Author:
robert
Message:

Refactored osgvnc example to utilise the new vnc plugin

Files:
1 modified

Legend:

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

    r9084 r9090  
    1111#include <osg/io_utils> 
    1212 
    13 extern "C" { 
    14 #include <rfb/rfbclient.h> 
    15 } 
    16  
    17 class VncImage : public osg::Image 
    18 { 
    19     public: 
    20      
    21         VncImage(); 
    22  
    23         bool connect(int* argc, char** argv); 
    24          
    25         void close(); 
    26  
    27         static rfbBool resizeImage(rfbClient* client); 
    28          
    29         static void updateImage(rfbClient* client,int x,int y,int w,int h); 
    30          
    31     protected: 
    32      
    33         virtual ~VncImage(); 
    34  
    35         class RfbThread : public osg::Referenced, public OpenThreads::Thread 
    36         { 
    37         public: 
    38  
    39             RfbThread(rfbClient* client): 
    40                 _client(client), 
    41                 _done(false) {} 
    42  
    43             virtual ~RfbThread() 
    44             { 
    45                 _done = true; 
    46                 cancel(); 
    47                 while(isRunning())  
    48                 { 
    49                     OpenThreads::Thread::YieldCurrentThread(); 
    50                 } 
    51             } 
    52  
    53             virtual void run() 
    54             { 
    55                 do 
    56                 { 
    57                     int i=WaitForMessage(_client,500); 
    58                     if(i<0) 
    59                         return; 
    60                     if(i) 
    61                         if(!HandleRFBServerMessage(_client)) 
    62                         return; 
    63  
    64                 } while (!_done && !testCancel()); 
    65             } 
    66  
    67             rfbClient*  _client; 
    68             bool        _done; 
    69  
    70         }; 
    71  
    72     public: 
    73  
    74         rfbClient* _client; 
    75  
    76         osg::ref_ptr<RfbThread> _rfbThread; 
    77        
    78 }; 
    79  
    80 VncImage::VncImage() 
    81 { 
    82     // setPixelBufferObject(new osg::PixelBufferObject(this); 
    83  
    84 } 
    85  
    86 VncImage::~VncImage() 
    87 { 
    88     close(); 
    89 } 
    90  
    91 bool VncImage::connect(int* argc, char** argv) 
    92 { 
    93     if (_client) close(); 
    94  
    95     _client = rfbGetClient(8,3,4); 
    96     _client->canHandleNewFBSize = TRUE; 
    97     _client->MallocFrameBuffer = resizeImage; 
    98     _client->GotFrameBufferUpdate = updateImage; 
    99     _client->HandleKeyboardLedState = 0; 
    100     _client->HandleTextChat = 0; 
    101  
    102     rfbClientSetClientData(_client, 0, this); 
    103      
    104     if (rfbInitClient(_client,argc,argv)) 
    105     { 
    106         _rfbThread = new RfbThread(_client); 
    107         _rfbThread->startThread(); 
    108     } 
    109 } 
    110  
    111 void VncImage::close() 
    112 { 
    113     if (_rfbThread.valid()) 
    114     { 
    115         // stop the client thread 
    116         _rfbThread = 0; 
    117     } 
    118  
    119     if (_client) 
    120     { 
    121         // close the client 
    122         rfbClientCleanup(_client); 
    123         _client = 0; 
    124     } 
    125 } 
     13#include <osgDB/ReadFile> 
    12614 
    12715 
    128 rfbBool VncImage::resizeImage(rfbClient* client)  
     16osg::Node* createInteractiveQuad(const osg::Vec3& origin, osg::Vec3& widthAxis, osg::Vec3& heightAxis,  
     17                                 osg::Image* image) 
    12918{ 
    130     osg::Image* image = (osg::Image*)(rfbClientGetClientData(client, 0)); 
    131      
    132     int width=client->width; 
    133     int height=client->height; 
    134     int depth=client->format.bitsPerPixel; 
     19    bool flip = image->getOrigin()==osg::Image::TOP_LEFT; 
    13520 
    136     std::cout<<"resize "<<width<<", "<<height<<", "<<depth<<" image = "<<image<<std::endl; 
    137  
    138     image->allocateImage(width,height,1,GL_RGBA,GL_UNSIGNED_BYTE); 
    139      
    140     client->frameBuffer= (uint8_t*)(image->data()); 
    141      
    142     return TRUE; 
    143 } 
    144  
    145 void VncImage::updateImage(rfbClient* client,int x,int y,int w,int h) 
    146 { 
    147     osg::Image* image = (osg::Image*)(rfbClientGetClientData(client, 0)); 
    148     image->dirty(); 
    149 } 
    150  
    151  
    152 class RfbEventHandler : public osgGA::GUIEventHandler 
    153 { 
    154 public: 
    155  
    156     RfbEventHandler(rfbClient* client): 
    157         _client(client) {} 
    158      
    159     virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv); 
    160      
    161     rfbKeySym key2rfbKeySym(int key) 
    162     { 
    163         return rfbKeySym(key); 
    164     } 
    165  
    166 protected: 
    167  
    168     virtual ~RfbEventHandler() {} 
    169      
    170     bool mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const; 
    171  
    172     rfbClient*  _client; 
    173      
    174 }; 
    175  
    176 bool RfbEventHandler::mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const 
    177 { 
    178     osgUtil::LineSegmentIntersector::Intersections intersections; 
    179     bool foundIntersection = view==0 ? false : 
    180         (nv==0 ? view->computeIntersections(ea.getX(), ea.getY(), intersections) : 
    181                  view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections)); 
    182  
    183     if (foundIntersection) 
    184     { 
    185  
    186         osg::Vec2 tc(0.5f,0.5f); 
    187  
    188         // use the nearest intersection                  
    189         const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin()); 
    190         osg::Drawable* drawable = intersection.drawable.get(); 
    191         osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0; 
    192         osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0; 
    193         if (vertices) 
    194         { 
    195             // get the vertex indices. 
    196             const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList; 
    197             const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList; 
    198  
    199             if (indices.size()==3 && ratios.size()==3) 
    200             { 
    201                 unsigned int i1 = indices[0]; 
    202                 unsigned int i2 = indices[1]; 
    203                 unsigned int i3 = indices[2]; 
    204  
    205                 float r1 = ratios[0]; 
    206                 float r2 = ratios[1]; 
    207                 float r3 = ratios[2]; 
    208  
    209                 osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0; 
    210                 osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords); 
    211                 if (texcoords_Vec2Array) 
    212                 { 
    213                     // we have tex coord array so now we can compute the final tex coord at the point of intersection.                                 
    214                     osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1]; 
    215                     osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2]; 
    216                     osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3]; 
    217                     tc = tc1*r1 + tc2*r2 + tc3*r3; 
    218                 } 
    219             } 
    220  
    221         } 
    222  
    223         x = int( float(_client->width) * tc.x() ); 
    224         y = int( float(_client->height) * tc.y() ); 
    225  
    226         return true; 
    227     } 
    228      
    229     return false; 
    230 } 
    231  
    232  
    233 bool RfbEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv) 
    234 { 
    235     switch(ea.getEventType()) 
    236     { 
    237         case(osgGA::GUIEventAdapter::MOVE): 
    238         case(osgGA::GUIEventAdapter::DRAG): 
    239         case(osgGA::GUIEventAdapter::PUSH): 
    240         case(osgGA::GUIEventAdapter::RELEASE): 
    241         { 
    242             osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); 
    243             int x,y; 
    244             if (mousePosition(view, nv, ea, x, y)) 
    245             { 
    246                 SendPointerEvent(_client,x,y, ea.getButtonMask()); 
    247                 return true; 
    248             } 
    249             break; 
    250         } 
    251         case(osgGA::GUIEventAdapter::KEYDOWN): 
    252         case(osgGA::GUIEventAdapter::KEYUP): 
    253         { 
    254             osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); 
    255             int x,y; 
    256             bool sendKeyEvent = mousePosition(view, nv, ea, x, y); 
    257          
    258             if (sendKeyEvent) 
    259             { 
    260                 SendKeyEvent(_client, 
    261                     key2rfbKeySym(ea.getKey()), 
    262                     (ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN)?TRUE:FALSE); 
    263  
    264                 return true; 
    265             } 
    266             else 
    267             { 
    268                 if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Escape) 
    269                 { 
    270                     osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa); 
    271                     if (viewer) viewer->setDone(true); 
    272                 } 
    273             } 
    274              
    275         } 
    276  
    277         default: 
    278             return false; 
    279     } 
    280     return false; 
    281 } 
    282  
    283 int main(int argc,char** argv) 
    284 { 
    285     osg::ref_ptr<VncImage> image = new VncImage; 
    286  
    287     if (image->connect(&argc,argv)) 
    288     { 
    289         return 1; 
    290     } 
    291  
    292     osg::ArgumentParser arguments(&argc, argv); 
    293     osgViewer::Viewer viewer; 
    294  
    295  
    296     bool xyPlane = false; 
    297     bool flip = true; 
    298     float width = image->s(); 
    299     float height = image->t(); 
    300  
    301     osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f), 
    302                                        osg::Vec3(width,0.0f,0.0f), 
    303                                        xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height), 
     21    osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(origin, widthAxis, heightAxis, 
    30422                                       0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f); 
    30523 
    306     osg::Texture2D* texture = new osg::Texture2D(image.get()); 
     24    osg::Texture2D* texture = new osg::Texture2D(image); 
    30725    texture->setResizeNonPowerOfTwoHint(false); 
    30826    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR); 
     
    31331                texture, 
    31432                osg::StateAttribute::ON); 
     33                 
     34    pictureQuad->setEventCallback(new osgViewer::InteractiveImageHandler(image)); 
    31535 
    31636    osg::Geode* geode = new osg::Geode; 
    31737    geode->addDrawable(pictureQuad); 
    31838     
    319     viewer.setSceneData(geode); 
     39    return geode; 
     40} 
     41 
     42class EscapeHandler : public osgGA::GUIEventHandler 
     43{ 
     44    public: 
     45     
     46        EscapeHandler() {} 
     47 
     48        bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa) 
     49        { 
     50            if (ea.getHandled()) return false; 
     51 
     52            switch(ea.getEventType()) 
     53            { 
     54                case(osgGA::GUIEventAdapter::KEYUP): 
     55                { 
     56                    if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Escape) 
     57                    { 
     58                        osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa); 
     59                        if (view) view->getViewerBase()->setDone(true); 
     60                         
     61                        return true; 
     62                    } 
     63                } 
     64 
     65                default: 
     66                    return false; 
     67            } 
     68            return false; 
     69        } 
     70}; 
     71 
     72int main(int argc,char** argv) 
     73{ 
     74 
     75    osg::ArgumentParser arguments(&argc, argv); 
     76    osgViewer::Viewer viewer; 
     77     
     78    typedef std::list< osg::ref_ptr<osg::Image> > Images; 
     79    Images images; 
     80 
     81    std::string hostname; 
     82    while (arguments.read("--host",hostname)) 
     83    { 
     84        osg::ref_ptr<osg::Image> image = osgDB::readImageFile(hostname+std::string(".vnc")); 
     85        if (image.valid()) images.push_back(image.get()); 
     86    } 
     87     
     88    if (images.empty()) 
     89    { 
     90        return 1; 
     91    } 
     92 
     93    bool xyPlane = false; 
     94 
     95    osg::Group* group = new osg::Group; 
     96 
     97    osg::Vec3 origin = osg::Vec3(0.0f,0.0f,0.0f); 
     98    for(Images::iterator itr = images.begin(); 
     99        itr != images.end(); 
     100        ++itr) 
     101    { 
     102        osg::Image* image = itr->get(); 
     103        float width = 1.0; 
     104        float height = float(image->t())/float(image->s()); 
     105        osg::Vec3 widthAxis = osg::Vec3(width,0.0f,0.0f); 
     106        osg::Vec3 heightAxis = xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height); 
     107        group->addChild(createInteractiveQuad(origin, widthAxis, heightAxis, image)); 
     108         
     109        origin += widthAxis*1.1f; 
     110    } 
     111     
     112    viewer.setSceneData(group); 
    320113 
    321114    viewer.addEventHandler(new osgViewer::StatsHandler); 
    322     viewer.addEventHandler(new RfbEventHandler(image->_client)); 
    323115     
     116    // add a custom escape handler, but disable the standard viewer one to enable the vnc images to handle 
     117    // the escape without it getting caught by the viewer. 
     118    viewer.addEventHandler(new EscapeHandler);     
    324119    viewer.setKeyEventSetsDone(0); 
    325120