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

Revision 5064, 18.5 kB (checked in by robert, 9 years ago)

Build fixes to cope with changes to Producer/osgProducer.

  • 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#include <osg/io_utils>
15
16#if defined (WIN32) && !defined(__CYGWIN__)
17#include <winsock.h>
18#endif
19
20#include "receiver.h"
21#include "broadcaster.h"
22
23
24const unsigned int MAX_NUM_EVENTS = 10;
25const unsigned int SWAP_BYTES_COMPARE = 0x12345678;
26class CameraPacket {
27    public:
28   
29   
30        CameraPacket():_masterKilled(false)
31        {
32            _byte_order = SWAP_BYTES_COMPARE;
33        }
34       
35        void setPacket(const osg::Matrix& matrix,const osg::FrameStamp* frameStamp)
36        {
37            _matrix = matrix;
38            if (frameStamp)
39            {
40                _frameStamp    = *frameStamp;
41            }
42        }
43       
44        void getModelView(osg::Matrix& matrix,float angle_offset=0.0f)
45        {
46       
47            matrix = _matrix * osg::Matrix::rotate(osg::DegreesToRadians(angle_offset),0.0f,1.0f,0.0f);
48        }
49       
50        void readEventQueue(osgProducer::Viewer& viewer);
51       
52        void writeEventQueue(osgProducer::Viewer& viewer);
53
54        void setMasterKilled(const bool flag) { _masterKilled = flag; }
55        const bool getMasterKilled() const { return _masterKilled; }
56       
57        unsigned int    _byte_order;
58        bool            _masterKilled;
59        osg::Matrix     _matrix;
60
61        // note don't use a ref_ptr as used elsewhere for FrameStamp
62        // since we don't want to copy the pointer - but the memory.
63        // FrameStamp doesn't have a private destructor to allow
64        // us to do this, even though its a reference counted object.   
65        osg::FrameStamp  _frameStamp;
66       
67        osgGA::EventQueue::Events _events;
68       
69};
70
71class DataConverter
72{
73    public:
74
75        DataConverter(unsigned int numBytes):
76            _startPtr(0),
77            _endPtr(0),
78            _swapBytes(false),
79            _currentPtr(0)
80        {
81            _currentPtr = _startPtr = new char[numBytes];
82            _endPtr = _startPtr+numBytes;
83            _numBytes = numBytes;
84        }
85
86        char* _startPtr;
87        char* _endPtr;
88        unsigned int _numBytes;
89        bool _swapBytes;
90
91        char* _currentPtr;
92       
93        void reset()
94        {
95            _currentPtr = _startPtr;
96        }
97
98        inline void write1(char* ptr)
99        {
100            if (_currentPtr+1>=_endPtr) return;
101
102            *(_currentPtr++) = *(ptr);
103        }
104
105        inline void read1(char* ptr)
106        {
107            if (_currentPtr+1>=_endPtr) return;
108
109            *(ptr) = *(_currentPtr++);
110        }
111
112        inline void write2(char* ptr)
113        {
114            if (_currentPtr+2>=_endPtr) return;
115
116            *(_currentPtr++) = *(ptr++);
117            *(_currentPtr++) = *(ptr);
118        }
119
120        inline void read2(char* ptr)
121        {
122            if (_currentPtr+2>=_endPtr) return;
123
124            if (_swapBytes)
125            {
126                *(ptr+1) = *(_currentPtr++);
127                *(ptr) = *(_currentPtr++);
128            }
129            else
130            {
131                *(ptr++) = *(_currentPtr++);
132                *(ptr) = *(_currentPtr++);
133            }
134        }
135
136        inline void write4(char* ptr)
137        {
138            if (_currentPtr+4>=_endPtr) return;
139
140            *(_currentPtr++) = *(ptr++);
141            *(_currentPtr++) = *(ptr++);
142            *(_currentPtr++) = *(ptr++);
143            *(_currentPtr++) = *(ptr);
144        }
145
146        inline void read4(char* ptr)
147        {
148            if (_currentPtr+4>=_endPtr) return;
149
150            if (_swapBytes)
151            {
152                *(ptr+3) = *(_currentPtr++);
153                *(ptr+2) = *(_currentPtr++);
154                *(ptr+1) = *(_currentPtr++);
155                *(ptr) = *(_currentPtr++);
156            }
157            else
158            {
159                *(ptr++) = *(_currentPtr++);
160                *(ptr++) = *(_currentPtr++);
161                *(ptr++) = *(_currentPtr++);
162                *(ptr) = *(_currentPtr++);
163            }
164        }
165
166        inline void write8(char* ptr)
167        {
168            if (_currentPtr+8>=_endPtr) return;
169
170            *(_currentPtr++) = *(ptr++);
171            *(_currentPtr++) = *(ptr++);
172            *(_currentPtr++) = *(ptr++);
173            *(_currentPtr++) = *(ptr++);
174
175            *(_currentPtr++) = *(ptr++);
176            *(_currentPtr++) = *(ptr++);
177            *(_currentPtr++) = *(ptr++);
178            *(_currentPtr++) = *(ptr);
179        }
180
181        inline void read8(char* ptr)
182        {
183            char* endPtr = _currentPtr+8;
184            if (endPtr>=_endPtr) return;
185
186            if (_swapBytes)
187            {
188                *(ptr+7) = *(_currentPtr++);
189                *(ptr+6) = *(_currentPtr++);
190                *(ptr+5) = *(_currentPtr++);
191                *(ptr+4) = *(_currentPtr++);
192
193                *(ptr+3) = *(_currentPtr++);
194                *(ptr+2) = *(_currentPtr++);
195                *(ptr+1) = *(_currentPtr++);
196                *(ptr) = *(_currentPtr++);
197            }
198            else
199            {
200                *(ptr++) = *(_currentPtr++);
201                *(ptr++) = *(_currentPtr++);
202                *(ptr++) = *(_currentPtr++);
203                *(ptr++) = *(_currentPtr++);
204
205                *(ptr++) = *(_currentPtr++);
206                *(ptr++) = *(_currentPtr++);
207                *(ptr++) = *(_currentPtr++);
208                *(ptr) = *(_currentPtr++);
209            }
210        }
211
212        inline void writeChar(char c)               { write1(&c); }
213        inline void writeUChar(unsigned char c)     { write1((char*)&c); }
214        inline void writeShort(short c)             { write2((char*)&c); }
215        inline void writeUShort(unsigned short c)   { write2((char*)&c); }
216        inline void writeInt(int c)                 { write4((char*)&c); }
217        inline void writeUInt(unsigned int c)       { write4((char*)&c); }
218        inline void writeFloat(float c)             { write4((char*)&c); }
219        inline void writeDouble(double c)           { write8((char*)&c); }
220
221        inline char readChar() { char c; read1(&c); return c; }
222        inline unsigned char readUChar() { unsigned char c; read1((char*)&c); return c; }
223        inline short readShort() { short c; read2((char*)&c); return c; }
224        inline unsigned short readUShort() { unsigned short c; read2((char*)&c); return c; }
225        inline int readInt() { int c; read4((char*)&c); return c; }
226        inline unsigned int readUInt() { unsigned int c; read4((char*)&c); return c; }
227        inline float readFloat() { float c; read4((char*)&c); return c; }
228        inline double readDouble() { double c; read8((char*)&c); return c; }
229
230        void write(const osg::FrameStamp& fs)
231        {
232            osg::notify(osg::NOTICE)<<"writeFramestamp = "<<fs.getFrameNumber()<<" "<<fs.getReferenceTime()<<std::endl;
233
234            writeUInt(fs.getFrameNumber());
235            writeDouble(fs.getReferenceTime());
236        }
237
238        void read(osg::FrameStamp& fs)
239        {
240            fs.setFrameNumber(readUInt());
241            fs.setReferenceTime(readDouble());
242
243            osg::notify(osg::NOTICE)<<"readFramestamp = "<<fs.getFrameNumber()<<" "<<fs.getReferenceTime()<<std::endl;
244        }
245
246        void write(const osg::Matrix& matrix)
247        {
248            writeDouble(matrix(0,0));
249            writeDouble(matrix(0,1));
250            writeDouble(matrix(0,2));
251            writeDouble(matrix(0,3));
252
253            writeDouble(matrix(1,0));
254            writeDouble(matrix(1,1));
255            writeDouble(matrix(1,2));
256            writeDouble(matrix(1,3));
257
258            writeDouble(matrix(2,0));
259            writeDouble(matrix(2,1));
260            writeDouble(matrix(2,2));
261            writeDouble(matrix(2,3));
262
263            writeDouble(matrix(3,0));
264            writeDouble(matrix(3,1));
265            writeDouble(matrix(3,2));
266            writeDouble(matrix(3,3));
267
268            osg::notify(osg::NOTICE)<<"writeMatrix = "<<matrix<<std::endl;
269
270        }
271
272        void read(osg::Matrix& matrix)
273        {
274            matrix(0,0) = readDouble();
275            matrix(0,1) = readDouble();
276            matrix(0,2) = readDouble();
277            matrix(0,3) = readDouble();
278
279            matrix(1,0) = readDouble();
280            matrix(1,1) = readDouble();
281            matrix(1,2) = readDouble();
282            matrix(1,3) = readDouble();
283
284            matrix(2,0) = readDouble();
285            matrix(2,1) = readDouble();
286            matrix(2,2) = readDouble();
287            matrix(2,3) = readDouble();
288
289            matrix(3,0) = readDouble();
290            matrix(3,1) = readDouble();
291            matrix(3,2) = readDouble();
292            matrix(3,3) = readDouble();
293
294            osg::notify(osg::NOTICE)<<"readMatrix = "<<matrix<<std::endl;
295
296        }
297
298        void write(const osgGA::GUIEventAdapter& event)
299        {
300            writeUInt(event.getEventType());
301            writeUInt(event.getKey());
302            writeUInt(event.getButton());
303            writeFloat(event.getXmin());
304            writeFloat(event.getXmax());
305            writeFloat(event.getYmin());
306            writeFloat(event.getYmax());
307            writeFloat(event.getX());
308            writeFloat(event.getY());
309            writeUInt(event.getButtonMask());
310            writeUInt(event.getModKeyMask());
311            writeDouble(event.getTime());
312        }
313
314        void read(osgGA::GUIEventAdapter& event)
315        {
316            event.setEventType((osgGA::GUIEventAdapter::EventType)readUInt());
317            event.setKey(readUInt());
318            event.setButton(readUInt());
319            event.setXmin(readFloat());
320            event.setXmax(readFloat());
321            event.setYmin(readFloat());
322            event.setYmax(readFloat());
323            event.setX(readFloat());
324            event.setY(readFloat());
325            event.setButtonMask(readUInt());
326            event.setModKeyMask(readUInt());
327            event.setTime(readDouble());
328        }
329       
330        void write(CameraPacket& cameraPacket)
331        {
332            writeUInt(cameraPacket._byte_order);
333           
334            writeUInt(cameraPacket._masterKilled);
335           
336            write(cameraPacket._matrix);
337            write(cameraPacket._frameStamp);
338       
339            writeUInt(cameraPacket._events.size());
340            for(osgGA::EventQueue::Events::iterator itr = cameraPacket._events.begin();
341                itr != cameraPacket._events.end();
342                ++itr)
343            {
344                write(*(*itr));
345            }
346        }
347
348        void read(CameraPacket& cameraPacket)
349        {
350            cameraPacket._byte_order = readUInt();
351            if (cameraPacket._byte_order != SWAP_BYTES_COMPARE)
352            {
353                _swapBytes = !_swapBytes;
354            }
355           
356            cameraPacket._masterKilled = readUInt();
357           
358            read(cameraPacket._matrix);
359            read(cameraPacket._frameStamp);
360       
361            cameraPacket._events.clear();
362            unsigned int numEvents = readUInt();
363            for(unsigned int i=0;i<numEvents;++i)
364            {
365                osgGA::GUIEventAdapter* event = new osgGA::GUIEventAdapter;
366                read(*(event));
367                cameraPacket._events.push_back(event);
368            }
369        }
370};
371
372void CameraPacket::readEventQueue(osgProducer::Viewer& viewer)
373{
374    _events.clear();
375
376    viewer.getKeyboardMouseCallback()->copyEventQueue(_events);
377
378    osg::notify(osg::INFO)<<"written events = "<<_events.size()<<std::endl;
379}
380
381void CameraPacket::writeEventQueue(osgProducer::Viewer& viewer)
382{
383    osg::notify(osg::INFO)<<"recieved events = "<<_events.size()<<std::endl;
384
385    // copy the events to osgProducer style events.
386    viewer.getKeyboardMouseCallback()->appendEventQueue(_events);
387}
388
389
390
391enum ViewerMode
392{
393    STAND_ALONE,
394    SLAVE,
395    MASTER
396};
397
398int main( int argc, char **argv )
399{
400    // use an ArgumentParser object to manage the program arguments.
401    osg::ArgumentParser arguments(&argc,argv);
402   
403    // set up the usage document, in case we need to print out how to use this program.
404    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.");
405    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
406    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
407    arguments.getApplicationUsage()->addCommandLineOption("-m","Set viewer to MASTER mode, sending view via packets.");
408    arguments.getApplicationUsage()->addCommandLineOption("-s","Set viewer to SLAVE mode, reciving view via packets.");
409    arguments.getApplicationUsage()->addCommandLineOption("-n <int>","Socket number to transmit packets");
410    arguments.getApplicationUsage()->addCommandLineOption("-f <float>","Field of view of camera");
411    arguments.getApplicationUsage()->addCommandLineOption("-o <float>","Offset angle of camera");
412   
413    // construct the viewer.
414    osgProducer::Viewer viewer(arguments);
415
416    // set up the value with sensible default event handlers.
417    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
418
419    // get details on keyboard and mouse bindings used by the viewer.
420    viewer.getUsage(*arguments.getApplicationUsage());
421
422
423    // read up the osgcluster specific arguments.
424    ViewerMode viewerMode = STAND_ALONE;
425    while (arguments.read("-m")) viewerMode = MASTER;
426    while (arguments.read("-s")) viewerMode = SLAVE;
427   
428    int socketNumber=8100;
429    while (arguments.read("-n",socketNumber)) ;
430
431    float camera_fov=-1.0f;
432    while (arguments.read("-f",camera_fov))
433    {
434    }
435
436    float camera_offset=45.0f;
437    while (arguments.read("-o",camera_offset)) ;
438
439
440    // if user request help write it out to cout.
441    if (arguments.read("-h") || arguments.read("--help"))
442    {
443        arguments.getApplicationUsage()->write(std::cout);
444        return 1;
445    }
446
447    // any option left unread are converted into errors to write out later.
448    arguments.reportRemainingOptionsAsUnrecognized();
449
450    // report any errors if they have occured when parsing the program aguments.
451    if (arguments.errors())
452    {
453        arguments.writeErrorMessages(std::cout);
454        return 1;
455    }
456   
457    if (arguments.argc()<=1)
458    {
459        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
460        return 1;
461    }
462   
463   
464    // load model.
465    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);
466
467   
468    // set the scene to render
469    viewer.setSceneData(rootnode.get());
470
471    // create the windows and run the threads.
472    viewer.realize();
473
474
475    // 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.
476    if (camera_fov>0.0f)
477    {
478        float aspectRatio = tan( osg::DegreesToRadians(viewer.getLensVerticalFov()*0.5)) / tan(osg::DegreesToRadians(viewer.getLensHorizontalFov()*0.5));
479        float new_fovy = osg::RadiansToDegrees(atan( aspectRatio * tan( osg::DegreesToRadians(camera_fov*0.5))))*2.0f;
480        std::cout << "setting lens perspective : original "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
481        viewer.setLensPerspective(camera_fov,new_fovy,1.0f,1000.0f);
482        std::cout << "setting lens perspective : new "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
483    }
484
485
486    CameraPacket *cp = new CameraPacket;
487
488    // objects for managing the broadcasting and recieving of camera packets.
489    Broadcaster     bc;
490    Receiver        rc;
491
492    bc.setPort(static_cast<short int>(socketNumber));
493    rc.setPort(static_cast<short int>(socketNumber));
494
495    bool masterKilled = false;
496   
497    DataConverter scratchPad(1024);
498
499    while( !viewer.done() && !masterKilled )
500    {
501        // wait for all cull and draw threads to complete.
502        viewer.sync();
503
504        osg::Timer_t startTick = osg::Timer::instance()->tick();
505                 
506        // special handling for working as a cluster.
507        switch (viewerMode)
508        {
509        case(MASTER):
510            {
511               
512                // take camera zero as the guide.
513                osg::Matrix modelview(viewer.getCamera(0)->getViewMatrix());
514               
515                cp->setPacket(modelview,viewer.getFrameStamp());
516               
517                cp->readEventQueue(viewer);
518
519                scratchPad.reset();
520                scratchPad.write(*cp);
521
522                scratchPad.reset();
523                scratchPad.read(*cp);
524
525                bc.setBuffer(scratchPad._startPtr, scratchPad._numBytes);
526               
527                std::cout << "bc.sync()"<<scratchPad._numBytes<<std::endl;
528
529                bc.sync();
530               
531            }
532            break;
533        case(SLAVE):
534            {
535
536                rc.setBuffer(scratchPad._startPtr, scratchPad._numBytes);
537
538                rc.sync();
539               
540                scratchPad.reset();
541                scratchPad.read(*cp);
542   
543                cp->writeEventQueue(viewer);
544
545                if (cp->getMasterKilled())
546                {
547                    std::cout << "Received master killed."<<std::endl;
548                    // break out of while (!done) loop since we've now want to shut down.
549                    masterKilled = true;
550                }
551            }
552            break;
553        default:
554            // no need to anything here, just a normal interactive viewer.
555            break;
556        }
557         
558        osg::Timer_t endTick = osg::Timer::instance()->tick();
559       
560        osg::notify(osg::INFO)<<"Time to do cluster sync "<<osg::Timer::instance()->delta_m(startTick,endTick)<<std::endl;
561
562        // update the scene by traversing it with the the update visitor which will
563        // call all node update callbacks and animations.
564        viewer.update();
565
566        if (viewerMode==SLAVE)
567        {
568            osg::Matrix modelview;
569            cp->getModelView(modelview,camera_offset);
570       
571            viewer.setView(modelview);
572        }
573
574        // fire off the cull and draw traversals of the scene.
575        if(!masterKilled)
576            viewer.frame();
577       
578    }
579
580    // wait for all cull and draw threads to complete before exit.
581    viewer.sync();
582
583    // if we are master clean up by telling all slaves that we're going down.
584    if (viewerMode==MASTER)
585    {
586        // need to broadcast my death.
587        cp->setPacket(osg::Matrix::identity(),viewer.getFrameStamp());
588        cp->setMasterKilled(true);
589
590        bc.setBuffer(cp, sizeof( CameraPacket ));
591        bc.sync();
592
593        std::cout << "Broadcasting death."<<std::endl;
594
595    }
596
597    return 0;
598}
Note: See TracBrowser for help on using the browser.