root/OpenSceneGraph/trunk/examples/osgcluster/osgcluster.cpp @ 4472

Revision 4472, 12.4 kB (checked in by robert, 9 years ago)

Improved support for keyboard/mouse events in osgcluster.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#ifdef USE_MEM_CHECK
2#include <mcheck.h>
3#endif
4
5#include <osg/Group>
6#include <osg/Notify>
7
8#include <osgDB/Registry>
9#include <osgDB/ReadFile>
10
11#include <osgProducer/Viewer>
12
13#include <osg/Quat>
14
15#if defined (WIN32) && !defined(__CYGWIN__)
16#include <winsock.h>
17#endif
18
19#include "receiver.h"
20#include "broadcaster.h"
21
22typedef unsigned char * BytePtr;
23template <class T>
24inline void swapBytes(  T &s )
25{
26    if( sizeof( T ) == 1 ) return;
27
28    T d = s;
29    BytePtr sptr = (BytePtr)&s;
30    BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
31
32    for( unsigned int i = 0; i < sizeof(T); i++ )
33        *(sptr++) = *(dptr--);
34}
35
36class PackedEvent
37{
38    public:
39        PackedEvent():
40            _eventType(osgProducer::EventAdapter::NONE),
41            _key(0),
42            _button(0),
43            _Xmin(0),_Xmax(0),
44            _Ymin(0),_Ymax(0),
45            _mx(0),
46            _my(0),
47            _buttonMask(0),
48            _modKeyMask(0),
49            _time(0.0) {}
50
51
52        void set(const osgProducer::EventAdapter& event)
53        {
54            _eventType = event._eventType;
55            _key = event._key;
56            _button = event._button;
57            _Xmin = event._Xmin;
58            _Xmax = event._Xmax;
59            _Ymin = event._Ymin;
60            _Ymax = event._Ymax;
61            _mx = event._mx;
62            _my = event._my;
63            _buttonMask = event._buttonMask;
64            _modKeyMask = event._modKeyMask;
65            _time = event._time;
66        }
67
68        void get(osgProducer::EventAdapter& event)
69        {
70            event._eventType = _eventType;
71            event._key = _key;
72            event._button = _button;
73            event._Xmin = _Xmin;
74            event._Xmax = _Xmax;
75            event._Ymin = _Ymin;
76            event._Ymax = _Ymax;
77            event._mx = _mx;
78            event._my = _my;
79            event._buttonMask = _buttonMask;
80            event._modKeyMask = _modKeyMask;
81            event._time = _time;
82        }
83       
84        void swapBytes()
85        {
86        }
87
88    protected:
89   
90        osgProducer::EventAdapter::EventType _eventType;
91        int _key;
92        int _button;
93        float _Xmin,_Xmax;
94        float _Ymin,_Ymax;
95        float _mx;
96        float _my;
97        unsigned int _buttonMask;
98        unsigned int _modKeyMask;
99        double _time;
100};
101
102const unsigned int MAX_NUM_EVENTS = 10;
103
104class CameraPacket {
105    public:
106   
107   
108        CameraPacket():_masterKilled(false)
109        {
110            _byte_order = 0x12345678;
111        }
112       
113        void setPacket(const osg::Matrix& matrix,const osg::FrameStamp* frameStamp)
114        {
115            _matrix = matrix;
116            if (frameStamp)
117            {
118                _frameStamp    = *frameStamp;
119            }
120        }
121       
122        void getModelView(osg::Matrix& matrix,float angle_offset=0.0f)
123        {
124       
125            matrix = _matrix * osg::Matrix::rotate(osg::DegreesToRadians(angle_offset),0.0f,1.0f,0.0f);
126        }
127       
128        void readEventQueue(osgProducer::Viewer& viewer);
129       
130        void writeEventQueue(osgProducer::Viewer& viewer);
131       
132        void checkByteOrder( void )
133        {
134            if( _byte_order == 0x78563412 )  // We're backwards
135            {
136                swapBytes( _byte_order );
137                swapBytes( _masterKilled );
138                for( int i = 0; i < 16; i++ )
139                swapBytes( _matrix.ptr()[i] );
140
141                    // umm.. we should byte swap _frameStamp too...
142                   
143                   
144                for(unsigned int ei=0; ei<_numEvents; ++ei)
145                {
146                    _events[ei].swapBytes();
147                }
148            }
149        }
150
151       
152        void setMasterKilled(const bool flag) { _masterKilled = flag; }
153        const bool getMasterKilled() const { return _masterKilled; }
154       
155        unsigned int    _byte_order;
156        bool            _masterKilled;
157        osg::Matrix     _matrix;
158
159        // note don't use a ref_ptr as used elsewhere for FrameStamp
160        // since we don't want to copy the pointer - but the memory.
161        // FrameStamp doesn't have a private destructor to allow
162        // us to do this, even though its a reference counted object.   
163        osg::FrameStamp  _frameStamp;
164       
165        unsigned int _numEvents;
166        PackedEvent  _events[MAX_NUM_EVENTS];       
167       
168};
169
170void CameraPacket::readEventQueue(osgProducer::Viewer& viewer)
171{
172    osgProducer::KeyboardMouseCallback::EventQueue queue;
173    viewer.getKeyboardMouseCallback()->copyEventQueue(queue);
174
175    _numEvents = 0;
176    for(osgProducer::KeyboardMouseCallback::EventQueue::iterator itr =queue.begin();
177        itr != queue.end() && _numEvents<MAX_NUM_EVENTS;
178        ++itr, ++_numEvents)
179    {
180        osgProducer::EventAdapter* event = itr->get();
181        _events[_numEvents].set(*event);
182    }
183    osg::notify(osg::INFO)<<"written events = "<<_numEvents<<std::endl;
184}
185
186void CameraPacket::writeEventQueue(osgProducer::Viewer& viewer)
187{
188    osg::notify(osg::INFO)<<"recieved events = "<<_numEvents<<std::endl;
189
190    // copy the packed events to osgProducer style events.
191    osgProducer::KeyboardMouseCallback::EventQueue queue;
192    for(unsigned int ei=0; ei<_numEvents; ++ei)
193    {
194        osgProducer::EventAdapter* event = new osgProducer::EventAdapter;
195        _events[ei].get(*event);
196        queue.push_back(event);
197    }
198   
199    // pass them to the viewer.
200    viewer.getKeyboardMouseCallback()->appendEventQueue(queue);
201}
202
203
204
205enum ViewerMode
206{
207    STAND_ALONE,
208    SLAVE,
209    MASTER
210};
211
212int main( int argc, char **argv )
213{
214    osg::notify(osg::INFO)<<"FrameStamp "<<sizeof(osg::FrameStamp)<<std::endl;
215    osg::notify(osg::INFO)<<"osg::Matrix "<<sizeof(osg::Matrix)<<std::endl;
216    osg::notify(osg::INFO)<<"PackedEvent "<<sizeof(PackedEvent)<<std::endl;
217
218
219    // use an ArgumentParser object to manage the program arguments.
220    osg::ArgumentParser arguments(&argc,argv);
221   
222    // set up the usage document, in case we need to print out how to use this program.
223    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to approach implementation of clustering. Note, cluster support will soon be encompassed in Producer itself.");
224    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
225    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
226    arguments.getApplicationUsage()->addCommandLineOption("-m","Set viewer to MASTER mode, sending view via packets.");
227    arguments.getApplicationUsage()->addCommandLineOption("-s","Set viewer to SLAVE mode, reciving view via packets.");
228    arguments.getApplicationUsage()->addCommandLineOption("-n <int>","Socket number to transmit packets");
229    arguments.getApplicationUsage()->addCommandLineOption("-f <float>","Field of view of camera");
230    arguments.getApplicationUsage()->addCommandLineOption("-o <float>","Offset angle of camera");
231   
232    // construct the viewer.
233    osgProducer::Viewer viewer(arguments);
234
235    // set up the value with sensible default event handlers.
236    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
237
238    // get details on keyboard and mouse bindings used by the viewer.
239    viewer.getUsage(*arguments.getApplicationUsage());
240
241
242    // read up the osgcluster specific arguments.
243    ViewerMode viewerMode = STAND_ALONE;
244    while (arguments.read("-m")) viewerMode = MASTER;
245    while (arguments.read("-s")) viewerMode = SLAVE;
246   
247    int socketNumber=8100;
248    while (arguments.read("-n",socketNumber)) ;
249
250    float camera_fov=-1.0f;
251    while (arguments.read("-f",camera_fov))
252    {
253    }
254
255    float camera_offset=45.0f;
256    while (arguments.read("-o",camera_offset)) ;
257
258
259    // if user request help write it out to cout.
260    if (arguments.read("-h") || arguments.read("--help"))
261    {
262        arguments.getApplicationUsage()->write(std::cout);
263        return 1;
264    }
265
266    // any option left unread are converted into errors to write out later.
267    arguments.reportRemainingOptionsAsUnrecognized();
268
269    // report any errors if they have occured when parsing the program aguments.
270    if (arguments.errors())
271    {
272        arguments.writeErrorMessages(std::cout);
273        return 1;
274    }
275   
276    if (arguments.argc()<=1)
277    {
278        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
279        return 1;
280    }
281   
282   
283    // load model.
284    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);
285
286   
287    // set the scene to render
288    viewer.setSceneData(rootnode.get());
289
290    // create the windows and run the threads.
291    viewer.realize();
292
293
294    // set up the lens after realize as the Producer lens is not set up properly before this.... will need to inveestigate this at a later date.
295    if (camera_fov>0.0f)
296    {
297        float aspectRatio = tan( osg::DegreesToRadians(viewer.getLensVerticalFov()*0.5)) / tan(osg::DegreesToRadians(viewer.getLensHorizontalFov()*0.5));
298        float new_fovy = osg::RadiansToDegrees(atan( aspectRatio * tan( osg::DegreesToRadians(camera_fov*0.5))))*2.0f;
299        std::cout << "setting lens perspective : original "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
300        viewer.setLensPerspective(camera_fov,new_fovy,1.0f,1000.0f);
301        std::cout << "setting lens perspective : new "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
302    }
303
304
305    CameraPacket *cp = new CameraPacket;
306    // objects for managing the broadcasting and recieving of camera packets.
307    Broadcaster     bc;
308    Receiver        rc;
309
310    bc.setPort(static_cast<short int>(socketNumber));
311    rc.setPort(static_cast<short int>(socketNumber));
312
313    bool masterKilled = false;
314
315    while( !viewer.done() && !masterKilled )
316    {
317        // wait for all cull and draw threads to complete.
318        viewer.sync();
319
320        osg::Timer_t startTick = osg::Timer::instance()->tick();
321                 
322        // special handling for working as a cluster.
323        switch (viewerMode)
324        {
325        case(MASTER):
326            {
327               
328                // take camera zero as the guide.
329                osg::Matrix modelview(viewer.getCameraConfig()->getCamera(0)->getViewMatrix());
330               
331                cp->setPacket(modelview,viewer.getFrameStamp());
332               
333                cp->readEventQueue(viewer);
334
335                bc.setBuffer(cp, sizeof( CameraPacket ));
336               
337                std::cout << "bc.sync()"<<sizeof( CameraPacket )<<std::endl;
338
339                bc.sync();
340               
341            }
342            break;
343        case(SLAVE):
344            {
345
346                rc.setBuffer(cp, sizeof( CameraPacket ));
347
348                osg::notify(osg::INFO) << "rc.sync()"<<sizeof( CameraPacket )<<std::endl;
349
350                rc.sync();
351   
352                cp->checkByteOrder();
353
354                cp->writeEventQueue(viewer);
355
356                if (cp->getMasterKilled())
357                {
358                    std::cout << "Received master killed."<<std::endl;
359                    // break out of while (!done) loop since we've now want to shut down.
360                    masterKilled = true;
361                }
362            }
363            break;
364        default:
365            // no need to anything here, just a normal interactive viewer.
366            break;
367        }
368         
369        osg::Timer_t endTick = osg::Timer::instance()->tick();
370       
371        osg::notify(osg::INFO)<<"Time to do cluster sync "<<osg::Timer::instance()->delta_m(startTick,endTick)<<std::endl;
372
373        // update the scene by traversing it with the the update visitor which will
374        // call all node update callbacks and animations.
375        viewer.update();
376
377        if (viewerMode==SLAVE)
378        {
379            osg::Matrix modelview;
380            cp->getModelView(modelview,camera_offset);
381       
382            viewer.setView(modelview);
383        }
384
385        // fire off the cull and draw traversals of the scene.
386        if(!masterKilled)
387            viewer.frame();
388       
389    }
390
391    // wait for all cull and draw threads to complete before exit.
392    viewer.sync();
393
394    // if we are master clean up by telling all slaves that we're going down.
395    if (viewerMode==MASTER)
396    {
397        // need to broadcast my death.
398        cp->setPacket(osg::Matrix::identity(),viewer.getFrameStamp());
399        cp->setMasterKilled(true);
400
401        bc.setBuffer(cp, sizeof( CameraPacket ));
402        bc.sync();
403
404        std::cout << "Broadcasting death."<<std::endl;
405
406    }
407
408    return 0;
409}
Note: See TracBrowser for help on using the browser.