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

Revision 5920, 18.5 kB (checked in by robert, 8 years ago)

Ported osgcluster to osgViewer.

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