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

Revision 2371, 8.0 kB (checked in by robert, 11 years ago)

Fixed the setting of the offset so that it convert degrees to radians.

Added setting of FOV, however, it doesn't yet function, will need to look into Producer to work out why.

  • 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)
16#include <winsock.h>
17#endif
18
19#include "receiver.h"
20#include "broadcaster.h"
21
22typedef unsigned char * BytePtr;
23template <class T>
24inline void swapBytes(  T &s )
25{
26    if( sizeof( T ) == 1 ) return;
27
28    T d = s;
29    BytePtr sptr = (BytePtr)&s;
30    BytePtr dptr = &(((BytePtr)&d)[sizeof(T)-1]);
31
32    for( unsigned int i = 0; i < sizeof(T); i++ )
33        *(sptr++) = *(dptr--);
34}
35
36class CameraPacket {
37    public:
38   
39        CameraPacket():_masterKilled(false)
40        {
41            _byte_order = 0x12345678;
42        }
43       
44        void setPacket(const osg::Matrix& matrix,const osg::FrameStamp* frameStamp)
45        {
46            _matrix = matrix;
47            if (frameStamp)
48            {
49                _frameStamp    = *frameStamp;
50            }
51        }
52       
53        void getModelView(osg::Matrix& matrix,float angle_offset=0.0f)
54        {
55       
56            matrix = _matrix * osg::Matrix::rotate(osg::DegreesToRadians(angle_offset),0.0f,1.0f,0.0f);
57        }
58       
59        void checkByteOrder( void )
60        {
61            if( _byte_order == 0x78563412 )  // We're backwards
62            {
63                swapBytes( _byte_order );
64            swapBytes( _masterKilled );
65            for( int i = 0; i < 16; i++ )
66                swapBytes( _matrix.ptr()[i] );
67
68                    // umm.. we should byte swap _frameStamp too...
69            }
70        }
71
72       
73        void setMasterKilled(const bool flag) { _masterKilled = flag; }
74        const bool getMasterKilled() const { return _masterKilled; }
75       
76    unsigned long   _byte_order;
77        bool            _masterKilled;
78        osg::Matrix     _matrix;
79
80        // note don't use a ref_ptr as used elsewhere for FrameStamp
81        // since we don't want to copy the pointer - but the memory.
82        // FrameStamp doesn't have a private destructor to allow
83        // us to do this, even though its a reference counted object.   
84        osg::FrameStamp  _frameStamp;
85       
86};
87
88enum ViewerMode
89{
90    STAND_ALONE,
91    SLAVE,
92    MASTER
93};
94
95int main( int argc, char **argv )
96{
97
98    // use an ArgumentParser object to manage the program arguments.
99    osg::ArgumentParser arguments(&argc,argv);
100   
101    // set up the usage document, in case we need to print out how to use this program.
102    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.");
103    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
104    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
105    arguments.getApplicationUsage()->addCommandLineOption("-m","Set viewer to MASTER mode, sending view via packets.");
106    arguments.getApplicationUsage()->addCommandLineOption("-s","Set viewer to SLAVE mode, reciving view via packets.");
107    arguments.getApplicationUsage()->addCommandLineOption("-n <int>","Socket number to transmit packets");
108    arguments.getApplicationUsage()->addCommandLineOption("-f <float>","Field of view of camera");
109    arguments.getApplicationUsage()->addCommandLineOption("-o <float>","Offset angle of camera");
110   
111    // construct the viewer.
112    osgProducer::Viewer viewer(arguments);
113
114    // set up the value with sensible default event handlers.
115    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);
116
117    // get details on keyboard and mouse bindings used by the viewer.
118    viewer.getUsage(*arguments.getApplicationUsage());
119
120
121    // read up the osgcluster specific arguments.
122    ViewerMode viewerMode = STAND_ALONE;
123    while (arguments.read("-m")) viewerMode = MASTER;
124    while (arguments.read("-s")) viewerMode = SLAVE;
125   
126    float socketNumber=8100.0f;
127    while (arguments.read("-n",socketNumber)) ;
128
129    float camera_fov=45.0f;
130    while (arguments.read("-f",camera_fov))
131    {
132        std::cout << "setting lens perspective : original "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
133        viewer.setLensPerspective(camera_fov,camera_fov*viewer.getLensVerticalFov()/viewer.getLensHorizontalFov(),1.0f,1000.0f);
134        std::cout << "setting lens perspective : new "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
135    }
136
137    float camera_offset=45.0f;
138    while (arguments.read("-o",camera_offset)) ;
139
140
141    // if user request help write it out to cout.
142    if (arguments.read("-h") || arguments.read("--help"))
143    {
144        arguments.getApplicationUsage()->write(std::cout);
145        return 1;
146    }
147
148    // any option left unread are converted into errors to write out later.
149    arguments.reportRemainingOptionsAsUnrecognized();
150
151    // report any errors if they have occured when parsing the program aguments.
152    if (arguments.errors())
153    {
154        arguments.writeErrorMessages(std::cout);
155        return 1;
156    }
157   
158    if (arguments.argc()<=1)
159    {
160        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
161        return 1;
162    }
163   
164   
165    // load model.
166    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);
167
168   
169    // set the scene to render
170    viewer.setSceneData(rootnode.get());
171
172    // create the windows and run the threads.
173    viewer.realize();
174
175    // objects for managing the broadcasting and recieving of camera packets.
176    Broadcaster     bc;
177    Receiver        rc;
178
179    bc.setPort(static_cast<short int>(socketNumber));
180    rc.setPort(static_cast<short int>(socketNumber));
181
182    bool masterKilled = false;
183
184    while( !viewer.done() && !masterKilled )
185    {
186        // wait for all cull and draw threads to complete.
187        viewer.sync();
188
189        // update the scene by traversing it with the the update visitor which will
190        // call all node update callbacks and animations.
191        viewer.update();
192         
193         
194        // special handling for working as a cluster.
195        switch (viewerMode)
196        {
197        case(MASTER):
198            {
199                CameraPacket cp;
200               
201                // take camera zero as the guide.
202                osg::Matrix modelview(viewer.getCameraConfig()->getCamera(0)->getViewMatrix());
203               
204                cp.setPacket(modelview,viewer.getFrameStamp());
205
206                bc.setBuffer(&cp, sizeof( CameraPacket ));
207            bc.sync();
208
209            }
210            break;
211        case(SLAVE):
212            {
213                CameraPacket cp;
214
215                rc.setBuffer(&cp, sizeof( CameraPacket ));
216
217                rc.sync();
218   
219                cp.checkByteOrder();
220
221                osg::Matrix modelview;
222                cp.getModelView(modelview,camera_offset);
223               
224                viewer.setView(modelview);
225
226                if (cp.getMasterKilled())
227                {
228                    std::cout << "received master killed"<<std::endl;
229                    // break out of while (!done) loop since we've now want to shut down.
230                    masterKilled = true;
231                }
232            }
233            break;
234        default:
235            // no need to anything here, just a normal interactive viewer.
236            break;
237        }
238         
239        // fire off the cull and draw traversals of the scene.
240        if(!masterKilled)
241            viewer.frame();
242       
243    }
244
245    // wait for all cull and draw threads to complete before exit.
246    viewer.sync();
247
248    // if we are master clean up by telling all slaves that we're going down.
249    if (viewerMode==MASTER)
250    {
251        // need to broadcast my death.
252        CameraPacket cp;
253        cp.setPacket(osg::Matrix::identity(),viewer.getFrameStamp());
254        cp.setMasterKilled(true);
255
256        bc.setBuffer(&cp, sizeof( CameraPacket ));
257        bc.sync();
258
259        std::cout << "broadcasting death"<<std::endl;
260
261    }
262
263    return 0;
264}
Note: See TracBrowser for help on using the browser.