root/OpenSceneGraph/trunk/examples/osgvnc/osgvnc.cpp @ 9083

Revision 9083, 7.9 kB (checked in by robert, 6 years ago)

Implemented keyboard and mouse dispatch from vnc client to vnc server.

Line 
1#include <osg/Image>
2#include <osg/Geometry>
3#include <osg/Texture2D>
4
5#include <osgGA/TrackballManipulator>
6
7#include <osgViewer/Viewer>
8#include <osgViewer/ViewerEventHandlers>
9
10#include <iostream>
11#include <osg/io_utils>
12
13extern "C" {
14#include <rfb/rfbclient.h>
15}
16
17static rfbBool resizeImage(rfbClient* client)
18{
19    osg::Image* image = (osg::Image*)(rfbClientGetClientData(client, 0));
20   
21    int width=client->width;
22    int height=client->height;
23    int depth=client->format.bitsPerPixel;
24
25    std::cout<<"resize "<<width<<", "<<height<<", "<<depth<<" image = "<<image<<std::endl;
26
27    image->allocateImage(width,height,1,GL_RGBA,GL_UNSIGNED_BYTE);
28   
29    client->frameBuffer= (uint8_t*)(image->data());
30   
31    return TRUE;
32}
33
34static void updateImage(rfbClient* client,int x,int y,int w,int h)
35{
36    osg::Image* image = (osg::Image*)(rfbClientGetClientData(client, 0));
37    image->dirty();
38}
39
40
41class RfbEventHandler : public osgGA::GUIEventHandler
42{
43public:
44
45    RfbEventHandler(rfbClient* client):
46        _client(client) {}
47   
48    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv);
49   
50    rfbKeySym key2rfbKeySym(int key)
51    {
52        return rfbKeySym(key);
53    }
54
55protected:
56
57    virtual ~RfbEventHandler() {}
58   
59    bool mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const;
60
61    rfbClient*  _client;
62   
63};
64
65bool RfbEventHandler::mousePosition(osgViewer::View* view, osg::NodeVisitor* nv, const osgGA::GUIEventAdapter& ea, int& x, int &y) const
66{
67    osgUtil::LineSegmentIntersector::Intersections intersections;
68    bool foundIntersection = view==0 ? false :
69        (nv==0 ? view->computeIntersections(ea.getX(), ea.getY(), intersections) :
70                 view->computeIntersections(ea.getX(), ea.getY(), nv->getNodePath(), intersections));
71
72    if (foundIntersection)
73    {
74
75        osg::Vec2 tc(0.5f,0.5f);
76
77        // use the nearest intersection                 
78        const osgUtil::LineSegmentIntersector::Intersection& intersection = *(intersections.begin());
79        osg::Drawable* drawable = intersection.drawable.get();
80        osg::Geometry* geometry = drawable ? drawable->asGeometry() : 0;
81        osg::Vec3Array* vertices = geometry ? dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()) : 0;
82        if (vertices)
83        {
84            // get the vertex indices.
85            const osgUtil::LineSegmentIntersector::Intersection::IndexList& indices = intersection.indexList;
86            const osgUtil::LineSegmentIntersector::Intersection::RatioList& ratios = intersection.ratioList;
87
88            if (indices.size()==3 && ratios.size()==3)
89            {
90                unsigned int i1 = indices[0];
91                unsigned int i2 = indices[1];
92                unsigned int i3 = indices[2];
93
94                float r1 = ratios[0];
95                float r2 = ratios[1];
96                float r3 = ratios[2];
97
98                osg::Array* texcoords = (geometry->getNumTexCoordArrays()>0) ? geometry->getTexCoordArray(0) : 0;
99                osg::Vec2Array* texcoords_Vec2Array = dynamic_cast<osg::Vec2Array*>(texcoords);
100                if (texcoords_Vec2Array)
101                {
102                    // we have tex coord array so now we can compute the final tex coord at the point of intersection.                               
103                    osg::Vec2 tc1 = (*texcoords_Vec2Array)[i1];
104                    osg::Vec2 tc2 = (*texcoords_Vec2Array)[i2];
105                    osg::Vec2 tc3 = (*texcoords_Vec2Array)[i3];
106                    tc = tc1*r1 + tc2*r2 + tc3*r3;
107                }
108            }
109
110        }
111
112        x = int( float(_client->width) * tc.x() );
113        y = int( float(_client->height) * tc.y() );
114
115        return true;
116    }
117   
118    return false;
119}
120
121
122bool RfbEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor* nv)
123{
124    switch(ea.getEventType())
125    {
126        case(osgGA::GUIEventAdapter::MOVE):
127        case(osgGA::GUIEventAdapter::DRAG):
128        case(osgGA::GUIEventAdapter::PUSH):
129        case(osgGA::GUIEventAdapter::RELEASE):
130        {
131            osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
132            int x,y;
133            if (mousePosition(view, nv, ea, x, y))
134            {
135                SendPointerEvent(_client,x,y, ea.getButtonMask());
136                return true;
137            }
138            break;
139        }
140        case(osgGA::GUIEventAdapter::KEYDOWN):
141        case(osgGA::GUIEventAdapter::KEYUP):
142        {
143            osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
144            int x,y;
145            bool sendKeyEvent = mousePosition(view, nv, ea, x, y);
146       
147            if (sendKeyEvent)
148            {
149                SendKeyEvent(_client,
150                    key2rfbKeySym(ea.getKey()),
151                    (ea.getEventType()==osgGA::GUIEventAdapter::KEYDOWN)?TRUE:FALSE);
152
153                return true;
154            }
155            else
156            {
157                if (ea.getKey()==osgGA::GUIEventAdapter::KEY_Escape)
158                {
159                    osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
160                    if (viewer) viewer->setDone(true);
161                }
162            }
163           
164        }
165
166        default:
167            return false;
168    }
169    return false;
170}
171
172class RfbThread : public OpenThreads::Thread
173{
174public:
175   
176    RfbThread(rfbClient* client):
177        _client(client),
178        _done(false) {}
179   
180    virtual ~RfbThread()
181    {
182        _done = true;
183        cancel();
184        while(isRunning())
185        {
186            OpenThreads::Thread::YieldCurrentThread();
187        }
188    }
189
190    virtual void run()
191    {
192        do
193        {
194            int i=WaitForMessage(_client,500);
195            if(i<0)
196                return;
197            if(i)
198                if(!HandleRFBServerMessage(_client))
199                return;
200               
201        } while (!_done && !testCancel());
202    }
203   
204    rfbClient*  _client;
205    bool        _done;
206   
207};
208
209int main(int argc,char** argv)
210{
211    osg::ref_ptr<osg::Image> image = new osg::Image;
212    // image->setPixelBufferObject(new osg::PixelBufferObject(image.get()));
213
214    /* 16-bit: client=rfbGetClient(5,3,2); */
215    rfbClient* client=rfbGetClient(8,3,4);
216    client->canHandleNewFBSize = TRUE;
217    client->MallocFrameBuffer = resizeImage;
218    client->GotFrameBufferUpdate = updateImage;
219    client->HandleKeyboardLedState = 0;
220    client->HandleTextChat = 0;
221
222    rfbClientSetClientData(client, 0, image.get());
223
224    if(!rfbInitClient(client,&argc,argv))
225        return 1;
226
227    osg::ArgumentParser arguments(&argc, argv);
228    osgViewer::Viewer viewer;
229
230
231    bool xyPlane = false;
232    bool flip = true;
233    float width = image->s();
234    float height = image->t();
235
236    osg::Geometry* pictureQuad = osg::createTexturedQuadGeometry(osg::Vec3(0.0f,0.0f,0.0f),
237                                       osg::Vec3(width,0.0f,0.0f),
238                                       xyPlane ? osg::Vec3(0.0f,height,0.0f) : osg::Vec3(0.0f,0.0f,height),
239                                       0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f);
240
241    osg::Texture2D* texture = new osg::Texture2D(image.get());
242    texture->setResizeNonPowerOfTwoHint(false);
243    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
244    texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
245    texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
246   
247    pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
248                texture,
249                osg::StateAttribute::ON);
250
251    osg::Geode* geode = new osg::Geode;
252    geode->addDrawable(pictureQuad);
253   
254    viewer.setSceneData(geode);
255
256    viewer.addEventHandler(new osgViewer::StatsHandler);
257    viewer.addEventHandler(new RfbEventHandler(client));
258   
259    RfbThread rfbThread(client);
260    rfbThread.startThread();
261   
262    viewer.setKeyEventSetsDone(0);
263
264    return viewer.run();
265
266    // rfbClientCleanup(cl);
267}
Note: See TracBrowser for help on using the browser.