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

Revision 4471, 12.2 kB (checked in by robert, 9 years ago)

Added extra debug info.

  • 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 = 0;
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    std::cout<<"written events = "<<_numEvents<<std::endl;
184}
185
186void CameraPacket::writeEventQueue(osgProducer::Viewer& viewer)
187{
188    std::cout<<"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
215    // use an ArgumentParser object to manage the program arguments.
216    osg::ArgumentParser arguments(&argc,argv);
217   
218    // set up the usage document, in case we need to print out how to use this program.
219    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.");
220    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
221    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
222    arguments.getApplicationUsage()->addCommandLineOption("-m","Set viewer to MASTER mode, sending view via packets.");
223    arguments.getApplicationUsage()->addCommandLineOption("-s","Set viewer to SLAVE mode, reciving view via packets.");
224    arguments.getApplicationUsage()->addCommandLineOption("-n <int>","Socket number to transmit packets");
225    arguments.getApplicationUsage()->addCommandLineOption("-f <float>","Field of view of camera");
226    arguments.getApplicationUsage()->addCommandLineOption("-o <float>","Offset angle of camera");
227   
228    // construct the viewer.
229    osgProducer::Viewer viewer(arguments);
230
231    // set up the value with sensible default event handlers.
232    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
233
234    // get details on keyboard and mouse bindings used by the viewer.
235    viewer.getUsage(*arguments.getApplicationUsage());
236
237
238    // read up the osgcluster specific arguments.
239    ViewerMode viewerMode = STAND_ALONE;
240    while (arguments.read("-m")) viewerMode = MASTER;
241    while (arguments.read("-s")) viewerMode = SLAVE;
242   
243    int socketNumber=8100;
244    while (arguments.read("-n",socketNumber)) ;
245
246    float camera_fov=-1.0f;
247    while (arguments.read("-f",camera_fov))
248    {
249    }
250
251    float camera_offset=45.0f;
252    while (arguments.read("-o",camera_offset)) ;
253
254
255    // if user request help write it out to cout.
256    if (arguments.read("-h") || arguments.read("--help"))
257    {
258        arguments.getApplicationUsage()->write(std::cout);
259        return 1;
260    }
261
262    // any option left unread are converted into errors to write out later.
263    arguments.reportRemainingOptionsAsUnrecognized();
264
265    // report any errors if they have occured when parsing the program aguments.
266    if (arguments.errors())
267    {
268        arguments.writeErrorMessages(std::cout);
269        return 1;
270    }
271   
272    if (arguments.argc()<=1)
273    {
274        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
275        return 1;
276    }
277   
278   
279    // load model.
280    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);
281
282   
283    // set the scene to render
284    viewer.setSceneData(rootnode.get());
285
286    // create the windows and run the threads.
287    viewer.realize();
288
289
290    // 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.
291    if (camera_fov>0.0f)
292    {
293        float aspectRatio = tan( osg::DegreesToRadians(viewer.getLensVerticalFov()*0.5)) / tan(osg::DegreesToRadians(viewer.getLensHorizontalFov()*0.5));
294        float new_fovy = osg::RadiansToDegrees(atan( aspectRatio * tan( osg::DegreesToRadians(camera_fov*0.5))))*2.0f;
295        std::cout << "setting lens perspective : original "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
296        viewer.setLensPerspective(camera_fov,new_fovy,1.0f,1000.0f);
297        std::cout << "setting lens perspective : new "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
298    }
299
300
301    CameraPacket *cp = new CameraPacket;
302    // objects for managing the broadcasting and recieving of camera packets.
303    Broadcaster     bc;
304    Receiver        rc;
305
306    bc.setPort(static_cast<short int>(socketNumber));
307    rc.setPort(static_cast<short int>(socketNumber+1));
308
309    bool masterKilled = false;
310
311    while( !viewer.done() && !masterKilled )
312    {
313        // wait for all cull and draw threads to complete.
314        viewer.sync();
315
316        osg::Timer_t startTick = osg::Timer::instance()->tick();
317                 
318        // special handling for working as a cluster.
319        switch (viewerMode)
320        {
321        case(MASTER):
322            {
323               
324                // take camera zero as the guide.
325                osg::Matrix modelview(viewer.getCameraConfig()->getCamera(0)->getViewMatrix());
326               
327                cp->setPacket(modelview,viewer.getFrameStamp());
328               
329                cp->readEventQueue(viewer);
330
331                bc.setBuffer(cp, sizeof( CameraPacket ));
332               
333                std::cout << "bc.sync()"<<sizeof( CameraPacket )<<std::endl;
334
335                bc.sync();
336               
337            }
338            break;
339        case(SLAVE):
340            {
341
342                rc.setBuffer(cp, sizeof( CameraPacket ));
343
344                std::cout << "rc.sync()"<<sizeof( CameraPacket )<<std::endl;
345
346                rc.sync();
347   
348                std::cout << "done"<<std::endl;
349
350                cp->checkByteOrder();
351
352                // cp->writeEventQueue(viewer);
353
354                if (cp->getMasterKilled())
355                {
356                    std::cout << "received master killed"<<std::endl;
357                    // break out of while (!done) loop since we've now want to shut down.
358                    masterKilled = true;
359                }
360            }
361            break;
362        default:
363            // no need to anything here, just a normal interactive viewer.
364            break;
365        }
366         
367        osg::Timer_t endTick = osg::Timer::instance()->tick();
368       
369        osg::notify(osg::NOTICE)<<"Time to do sync "<<osg::Timer::instance()->delta_m(startTick,endTick)<<std::endl;
370
371        // update the scene by traversing it with the the update visitor which will
372        // call all node update callbacks and animations.
373        viewer.update();
374
375        if (viewerMode==SLAVE)
376        {
377            osg::Matrix modelview;
378            cp->getModelView(modelview,camera_offset);
379       
380            viewer.setView(modelview);
381        }
382
383        // fire off the cull and draw traversals of the scene.
384        if(!masterKilled)
385            viewer.frame();
386       
387    }
388
389    // wait for all cull and draw threads to complete before exit.
390    viewer.sync();
391
392    // if we are master clean up by telling all slaves that we're going down.
393    if (viewerMode==MASTER)
394    {
395        // need to broadcast my death.
396        cp->setPacket(osg::Matrix::identity(),viewer.getFrameStamp());
397        cp->setMasterKilled(true);
398
399        bc.setBuffer(cp, sizeof( CameraPacket ));
400        bc.sync();
401
402        std::cout << "broadcasting death"<<std::endl;
403
404    }
405
406    return 0;
407}
Note: See TracBrowser for help on using the browser.