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

Revision 9637, 19.6 kB (checked in by robert, 5 years ago)

Warning fixes

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