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

Revision 13890, 20.2 kB (checked in by robert, 17 hours ago)

From Jason Beverage, "It looks like the Callback header got accidentally removed from the CMakeLists.txt in the submission yesterday for the geometry instancing example."

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