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

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

From Alberto Luaces,"the current code uses the preprocessor for generating the plugin path in
a way that when CMAKE_INSTALL_PREFIX contains something along the lines
of

/usr/x86_64-linux-gnu/

it gets substituted as

/usr/x86_64-1-gnu/

that is, the string is preprocessed again, thereby making changes to
anything that matches any defined symbol, as "linux" in this example
(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=763816).

Quoting that path directly in CMake scripts solves that problem.
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[6941]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
[1697]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
[5921]29#include <osgGA/TrackballManipulator>
[11622]30#include <osgGA/StateSetManipulator>
[5920]31#include <osgViewer/Viewer>
[11622]32#include <osgViewer/ViewerEventHandlers>
[1697]33
34#include <osg/Quat>
[4475]35#include <osg/io_utils>
[1697]36
[5920]37#include <iostream>
38
[3230]39#if defined (WIN32) && !defined(__CYGWIN__)
[1697]40#include <winsock.h>
41#endif
42
43#include "receiver.h"
44#include "broadcaster.h"
45
46
[4472]47const unsigned int MAX_NUM_EVENTS = 10;
[4473]48const unsigned int SWAP_BYTES_COMPARE = 0x12345678;
[1697]49class CameraPacket {
50    public:
[13890]51
52
53        CameraPacket():_masterKilled(false)
[2371]54        {
[4473]55            _byte_order = SWAP_BYTES_COMPARE;
[2371]56        }
[13890]57
[1704]58        void setPacket(const osg::Matrix& matrix,const osg::FrameStamp* frameStamp)
[1697]59        {
[1704]60            _matrix = matrix;
[1697]61            if (frameStamp)
62            {
63                _frameStamp    = *frameStamp;
64            }
65        }
[13890]66
[1704]67        void getModelView(osg::Matrix& matrix,float angle_offset=0.0f)
[1697]68        {
[13890]69
[2371]70            matrix = _matrix * osg::Matrix::rotate(osg::DegreesToRadians(angle_offset),0.0f,1.0f,0.0f);
[1697]71        }
[13890]72
[5920]73        void readEventQueue(osgViewer::Viewer& viewer);
[13890]74
[5920]75        void writeEventQueue(osgViewer::Viewer& viewer);
[2371]76
[1697]77        void setMasterKilled(const bool flag) { _masterKilled = flag; }
78        const bool getMasterKilled() const { return _masterKilled; }
[13890]79
[3809]80        unsigned int    _byte_order;
[1697]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
[13890]87        // us to do this, even though its a reference counted object.
[1697]88        osg::FrameStamp  _frameStamp;
[13890]89
[5032]90        osgGA::EventQueue::Events _events;
[13890]91
[1697]92};
93
[4473]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;
[13890]115
[4474]116        void reset()
117        {
118            _currentPtr = _startPtr;
119        }
[4473]120
121        inline void write1(char* ptr)
122        {
123            if (_currentPtr+1>=_endPtr) return;
124
[13890]125            *(_currentPtr++) = *(ptr);
[4473]126        }
127
128        inline void read1(char* ptr)
129        {
130            if (_currentPtr+1>=_endPtr) return;
131
[13890]132            *(ptr) = *(_currentPtr++);
[4473]133        }
134
135        inline void write2(char* ptr)
136        {
137            if (_currentPtr+2>=_endPtr) return;
138
[13890]139            *(_currentPtr++) = *(ptr++);
140            *(_currentPtr++) = *(ptr);
[4473]141        }
142
143        inline void read2(char* ptr)
144        {
145            if (_currentPtr+2>=_endPtr) return;
146
147            if (_swapBytes)
148            {
[13890]149                *(ptr+1) = *(_currentPtr++);
150                *(ptr) = *(_currentPtr++);
[4473]151            }
152            else
153            {
[13890]154                *(ptr++) = *(_currentPtr++);
155                *(ptr) = *(_currentPtr++);
[4473]156            }
157        }
158
159        inline void write4(char* ptr)
160        {
161            if (_currentPtr+4>=_endPtr) return;
162
[13890]163            *(_currentPtr++) = *(ptr++);
164            *(_currentPtr++) = *(ptr++);
165            *(_currentPtr++) = *(ptr++);
166            *(_currentPtr++) = *(ptr);
[4473]167        }
168
169        inline void read4(char* ptr)
170        {
171            if (_currentPtr+4>=_endPtr) return;
172
173            if (_swapBytes)
174            {
[13890]175                *(ptr+3) = *(_currentPtr++);
176                *(ptr+2) = *(_currentPtr++);
177                *(ptr+1) = *(_currentPtr++);
178                *(ptr) = *(_currentPtr++);
[4473]179            }
180            else
181            {
[13890]182                *(ptr++) = *(_currentPtr++);
183                *(ptr++) = *(_currentPtr++);
184                *(ptr++) = *(_currentPtr++);
185                *(ptr) = *(_currentPtr++);
[4473]186            }
187        }
188
189        inline void write8(char* ptr)
190        {
191            if (_currentPtr+8>=_endPtr) return;
192
[13890]193            *(_currentPtr++) = *(ptr++);
194            *(_currentPtr++) = *(ptr++);
195            *(_currentPtr++) = *(ptr++);
196            *(_currentPtr++) = *(ptr++);
[4473]197
[13890]198            *(_currentPtr++) = *(ptr++);
199            *(_currentPtr++) = *(ptr++);
200            *(_currentPtr++) = *(ptr++);
201            *(_currentPtr++) = *(ptr);
[4473]202        }
203
204        inline void read8(char* ptr)
205        {
206            char* endPtr = _currentPtr+8;
207            if (endPtr>=_endPtr) return;
208
209            if (_swapBytes)
210            {
[13890]211                *(ptr+7) = *(_currentPtr++);
212                *(ptr+6) = *(_currentPtr++);
213                *(ptr+5) = *(_currentPtr++);
214                *(ptr+4) = *(_currentPtr++);
[4473]215
[13890]216                *(ptr+3) = *(_currentPtr++);
217                *(ptr+2) = *(_currentPtr++);
218                *(ptr+1) = *(_currentPtr++);
219                *(ptr) = *(_currentPtr++);
[4473]220            }
221            else
222            {
[13890]223                *(ptr++) = *(_currentPtr++);
224                *(ptr++) = *(_currentPtr++);
225                *(ptr++) = *(_currentPtr++);
226                *(ptr++) = *(_currentPtr++);
[4473]227
[13890]228                *(ptr++) = *(_currentPtr++);
229                *(ptr++) = *(_currentPtr++);
230                *(ptr++) = *(_currentPtr++);
231                *(ptr) = *(_currentPtr++);
[4473]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        {
[4481]255            osg::notify(osg::NOTICE)<<"writeFramestamp = "<<fs.getFrameNumber()<<" "<<fs.getReferenceTime()<<std::endl;
256
[4473]257            writeUInt(fs.getFrameNumber());
[4736]258            writeDouble(fs.getReferenceTime());
[6051]259            writeDouble(fs.getSimulationTime());
[4473]260        }
261
262        void read(osg::FrameStamp& fs)
263        {
264            fs.setFrameNumber(readUInt());
265            fs.setReferenceTime(readDouble());
[6051]266            fs.setSimulationTime(readDouble());
[4481]267
268            osg::notify(osg::NOTICE)<<"readFramestamp = "<<fs.getFrameNumber()<<" "<<fs.getReferenceTime()<<std::endl;
[4473]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));
[4481]292
293            osg::notify(osg::NOTICE)<<"writeMatrix = "<<matrix<<std::endl;
294
[4473]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();
[4481]318
319            osg::notify(osg::NOTICE)<<"readMatrix = "<<matrix<<std::endl;
320
[4473]321        }
322
[5032]323        void write(const osgGA::GUIEventAdapter& event)
[4473]324        {
[5032]325            writeUInt(event.getEventType());
326            writeUInt(event.getKey());
327            writeUInt(event.getButton());
[5592]328            writeInt(event.getWindowX());
329            writeInt(event.getWindowY());
330            writeUInt(event.getWindowWidth());
331            writeUInt(event.getWindowHeight());
[5032]332            writeFloat(event.getXmin());
[5592]333            writeFloat(event.getYmin());
[5032]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());
[4473]341        }
342
[5032]343        void read(osgGA::GUIEventAdapter& event)
[4473]344        {
[5032]345            event.setEventType((osgGA::GUIEventAdapter::EventType)readUInt());
346            event.setKey(readUInt());
347            event.setButton(readUInt());
[5592]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);
[5032]358            event.setX(readFloat());
359            event.setY(readFloat());
360            event.setButtonMask(readUInt());
361            event.setModKeyMask(readUInt());
362            event.setTime(readDouble());
[4473]363        }
[13890]364
[4473]365        void write(CameraPacket& cameraPacket)
366        {
367            writeUInt(cameraPacket._byte_order);
[13890]368
[4473]369            writeUInt(cameraPacket._masterKilled);
[13890]370
[4473]371            write(cameraPacket._matrix);
372            write(cameraPacket._frameStamp);
[13890]373
[4473]374            writeUInt(cameraPacket._events.size());
[5032]375            for(osgGA::EventQueue::Events::iterator itr = cameraPacket._events.begin();
376                itr != cameraPacket._events.end();
377                ++itr)
[4473]378            {
[13890]379                osgGA::GUIEventAdapter* event = (*itr)->asGUIEventAdapter();
380                if (event) write(*event);
[4473]381            }
382        }
383
384        void read(CameraPacket& cameraPacket)
385        {
386            cameraPacket._byte_order = readUInt();
[4474]387            if (cameraPacket._byte_order != SWAP_BYTES_COMPARE)
388            {
389                _swapBytes = !_swapBytes;
390            }
[13890]391
[9637]392            cameraPacket._masterKilled = readUInt()!=0;
[13890]393
[4473]394            read(cameraPacket._matrix);
395            read(cameraPacket._frameStamp);
[13890]396
[4473]397            cameraPacket._events.clear();
398            unsigned int numEvents = readUInt();
399            for(unsigned int i=0;i<numEvents;++i)
400            {
[5032]401                osgGA::GUIEventAdapter* event = new osgGA::GUIEventAdapter;
[4473]402                read(*(event));
403                cameraPacket._events.push_back(event);
404            }
405        }
406};
407
[5920]408void CameraPacket::readEventQueue(osgViewer::Viewer& viewer)
[4470]409{
[4474]410    _events.clear();
411
[11623]412    osgViewer::ViewerBase::Contexts contexts;
[13890]413    viewer.getContexts(contexts);
[11623]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    }
[13890]427
[5920]428    viewer.getEventQueue()->copyEvents(_events);
[4470]429
[4473]430    osg::notify(osg::INFO)<<"written events = "<<_events.size()<<std::endl;
[4470]431}
432
[5920]433void CameraPacket::writeEventQueue(osgViewer::Viewer& viewer)
[4470]434{
[9692]435    osg::notify(osg::INFO)<<"received events = "<<_events.size()<<std::endl;
[4470]436
[5920]437    viewer.getEventQueue()->appendEvents(_events);
[4470]438}
439
440
441
[1704]442enum ViewerMode
443{
444    STAND_ALONE,
445    SLAVE,
446    MASTER
[1697]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);
[13890]453
[1697]454    // set up the usage document, in case we need to print out how to use this program.
[5962]455    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to approach implementation of clustering.");
[1815]456    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
[1697]457    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
[1704]458    arguments.getApplicationUsage()->addCommandLineOption("-m","Set viewer to MASTER mode, sending view via packets.");
[9692]459    arguments.getApplicationUsage()->addCommandLineOption("-s","Set viewer to SLAVE mode, receiving view via packets.");
[1704]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");
[13890]463
[1697]464    // construct the viewer.
[5920]465    osgViewer::Viewer viewer;
[1697]466
467
[1704]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;
[13890]472
[4470]473    int socketNumber=8100;
[1704]474    while (arguments.read("-n",socketNumber)) ;
475
[3511]476    float camera_fov=-1.0f;
[13890]477    while (arguments.read("-f",camera_fov))
[2371]478    {
479    }
[1704]480
481    float camera_offset=45.0f;
482    while (arguments.read("-o",camera_offset)) ;
483
484
[1697]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    }
[13890]501
[1815]502    if (arguments.argc()<=1)
503    {
504        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
505        return 1;
506    }
[5920]507
[1704]508    // load model.
509    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);
[1697]510
511    // set the scene to render
[1704]512    viewer.setSceneData(rootnode.get());
[1697]513
[3511]514    if (camera_fov>0.0f)
515    {
[5920]516        double fovy, aspectRatio, zNear, zFar;
517        viewer.getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio,zNear, zFar);
[13890]518
[5920]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;
[13890]521
[5920]522        fovy = atan(tan(osg::DegreesToRadians(camera_fov)*0.5)/aspectRatio)*2.0;
523        viewer.getCamera()->setProjectionMatrixAsPerspective(fovy, aspectRatio,zNear, zFar);
[13890]524
[5920]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;
[3511]528    }
529
[5921]530    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
[3511]531
[11622]532    // add the stats handler
533    viewer.addEventHandler(new osgViewer::StatsHandler);
[5921]534
[11622]535    // add the state manipulator
536    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
537
538
[5920]539    // create the windows and run the threads.
540    viewer.realize();
541
542
[3728]543    CameraPacket *cp = new CameraPacket;
[4473]544
[1706]545    // objects for managing the broadcasting and recieving of camera packets.
[1704]546    Broadcaster     bc;
547    Receiver        rc;
548
[1960]549    bc.setPort(static_cast<short int>(socketNumber));
[4472]550    rc.setPort(static_cast<short int>(socketNumber));
[1960]551
552    bool masterKilled = false;
[13890]553
[4473]554    DataConverter scratchPad(1024);
[1960]555
556    while( !viewer.done() && !masterKilled )
[1697]557    {
[4470]558        osg::Timer_t startTick = osg::Timer::instance()->tick();
[13890]559
[5920]560        viewer.advance();
561
[1704]562        // special handling for working as a cluster.
563        switch (viewerMode)
564        {
565        case(MASTER):
566            {
[13890]567
[1704]568                // take camera zero as the guide.
[5920]569                osg::Matrix modelview(viewer.getCamera()->getViewMatrix());
[13890]570
[3728]571                cp->setPacket(modelview,viewer.getFrameStamp());
[13890]572
[4470]573                cp->readEventQueue(viewer);
[1704]574
[4474]575                scratchPad.reset();
[4473]576                scratchPad.write(*cp);
577
[4475]578                scratchPad.reset();
579                scratchPad.read(*cp);
580
[4473]581                bc.setBuffer(scratchPad._startPtr, scratchPad._numBytes);
[13890]582
[4473]583                std::cout << "bc.sync()"<<scratchPad._numBytes<<std::endl;
[4471]584
[3067]585                bc.sync();
[13890]586
[1704]587            }
588            break;
589        case(SLAVE):
590            {
591
[4473]592                rc.setBuffer(scratchPad._startPtr, scratchPad._numBytes);
[1704]593
[1960]594                rc.sync();
[13890]595
[4474]596                scratchPad.reset();
[4473]597                scratchPad.read(*cp);
[13890]598
[4472]599                cp->writeEventQueue(viewer);
[1704]600
[13890]601                if (cp->getMasterKilled())
[1704]602                {
[4472]603                    std::cout << "Received master killed."<<std::endl;
[1706]604                    // break out of while (!done) loop since we've now want to shut down.
[1960]605                    masterKilled = true;
[1704]606                }
607            }
608            break;
609        default:
610            // no need to anything here, just a normal interactive viewer.
611            break;
612        }
[13890]613
[4470]614        osg::Timer_t endTick = osg::Timer::instance()->tick();
[13890]615
[4472]616        osg::notify(osg::INFO)<<"Time to do cluster sync "<<osg::Timer::instance()->delta_m(startTick,endTick)<<std::endl;
[4470]617
618        // update the scene by traversing it with the the update visitor which will
619        // call all node update callbacks and animations.
[5920]620        viewer.eventTraversal();
621        viewer.updateTraversal();
[4470]622
623        if (viewerMode==SLAVE)
624        {
625            osg::Matrix modelview;
626            cp->getModelView(modelview,camera_offset);
[13890]627
[5920]628            viewer.getCamera()->setViewMatrix(modelview);
[4470]629        }
630
[1697]631        // fire off the cull and draw traversals of the scene.
[1960]632        if(!masterKilled)
[5920]633            viewer.renderingTraversals();
[13890]634
[1697]635    }
[1960]636
[1704]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.
[3728]641        cp->setPacket(osg::Matrix::identity(),viewer.getFrameStamp());
[13890]642        cp->setMasterKilled(true);
[1704]643
[11624]644        scratchPad.reset();
645        scratchPad.write(*cp);
646
647        bc.setBuffer(scratchPad._startPtr, scratchPad._numBytes);
[1960]648        bc.sync();
[1704]649
[4472]650        std::cout << "Broadcasting death."<<std::endl;
[1704]651
652    }
653
[1697]654    return 0;
655}
Note: See TracBrowser for help on using the browser.