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

Revision 9084, 8.9 kB (checked in by robert, 6 years ago)

Wrapped up the various client streaming methods + thread into VncImage? classes.

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
17class 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
80VncImage::VncImage()
81{
82    // setPixelBufferObject(new osg::PixelBufferObject(this);
83
84}
85
86VncImage::~VncImage()
87{
88    close();
89}
90
91bool 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
111void 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}
126
127
128rfbBool VncImage::resizeImage(rfbClient* client)
129{
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;
135
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
145void 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
152class RfbEventHandler : public osgGA::GUIEventHandler
153{
154public:
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
166protected:
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
176bool 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
233bool 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
283int 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),
304                                       0.0f, flip ? 1.0f : 0.0f , 1.0f, flip ? 0.0f : 1.0f);
305
306    osg::Texture2D* texture = new osg::Texture2D(image.get());
307    texture->setResizeNonPowerOfTwoHint(false);
308    texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
309    texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
310    texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
311   
312    pictureQuad->getOrCreateStateSet()->setTextureAttributeAndModes(0,
313                texture,
314                osg::StateAttribute::ON);
315
316    osg::Geode* geode = new osg::Geode;
317    geode->addDrawable(pictureQuad);
318   
319    viewer.setSceneData(geode);
320
321    viewer.addEventHandler(new osgViewer::StatsHandler);
322    viewer.addEventHandler(new RfbEventHandler(image->_client));
323   
324    viewer.setKeyEventSetsDone(0);
325
326    return viewer.run();
327}
Note: See TracBrowser for help on using the browser.