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

Revision 4473, 17.8 kB (checked in by robert, 9 years ago)

Implement a scratch pad for writing and read data to, to solve issue between
running a master and slave on a mix of 32bit and 64bit.

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