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

Revision 4474, 18.2 kB (checked in by robert, 9 years ago)

Added scratch pad reset.

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