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

Revision 3511, 8.4 kB (checked in by robert, 10 years ago)

Move the setting of the camera horizontal field of view to after the realize()
to avoid the CameraGroup?'s Lens be set when its NULL.

  • 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
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=-1.0f;
130    while (arguments.read("-f",camera_fov))
131    {
132    }
133
134    float camera_offset=45.0f;
135    while (arguments.read("-o",camera_offset)) ;
136
137
138    // if user request help write it out to cout.
139    if (arguments.read("-h") || arguments.read("--help"))
140    {
141        arguments.getApplicationUsage()->write(std::cout);
142        return 1;
143    }
144
145    // any option left unread are converted into errors to write out later.
146    arguments.reportRemainingOptionsAsUnrecognized();
147
148    // report any errors if they have occured when parsing the program aguments.
149    if (arguments.errors())
150    {
151        arguments.writeErrorMessages(std::cout);
152        return 1;
153    }
154   
155    if (arguments.argc()<=1)
156    {
157        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
158        return 1;
159    }
160   
161   
162    // load model.
163    osg::ref_ptr<osg::Node> rootnode = osgDB::readNodeFiles(arguments);
164
165   
166    // set the scene to render
167    viewer.setSceneData(rootnode.get());
168
169    // create the windows and run the threads.
170    viewer.realize();
171
172
173    // 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.
174    if (camera_fov>0.0f)
175    {
176        float aspectRatio = tan( osg::DegreesToRadians(viewer.getLensVerticalFov()*0.5)) / tan(osg::DegreesToRadians(viewer.getLensHorizontalFov()*0.5));
177        float new_fovy = osg::RadiansToDegrees(atan( aspectRatio * tan( osg::DegreesToRadians(camera_fov*0.5))))*2.0f;
178        std::cout << "setting lens perspective : original "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
179        viewer.setLensPerspective(camera_fov,new_fovy,1.0f,1000.0f);
180        std::cout << "setting lens perspective : new "<<viewer.getLensHorizontalFov()<<"  "<<viewer.getLensVerticalFov()<<std::endl;
181    }
182
183
184    // objects for managing the broadcasting and recieving of camera packets.
185    Broadcaster     bc;
186    Receiver        rc;
187
188    bc.setPort(static_cast<short int>(socketNumber));
189    rc.setPort(static_cast<short int>(socketNumber));
190
191    bool masterKilled = false;
192
193    while( !viewer.done() && !masterKilled )
194    {
195        // wait for all cull and draw threads to complete.
196        viewer.sync();
197
198        // update the scene by traversing it with the the update visitor which will
199        // call all node update callbacks and animations.
200        viewer.update();
201         
202         
203        // special handling for working as a cluster.
204        switch (viewerMode)
205        {
206        case(MASTER):
207            {
208                CameraPacket cp;
209               
210                // take camera zero as the guide.
211                osg::Matrix modelview(viewer.getCameraConfig()->getCamera(0)->getViewMatrix());
212               
213                cp.setPacket(modelview,viewer.getFrameStamp());
214
215                bc.setBuffer(&cp, sizeof( CameraPacket ));
216               
217                bc.sync();
218
219            }
220            break;
221        case(SLAVE):
222            {
223                CameraPacket cp;
224
225                rc.setBuffer(&cp, sizeof( CameraPacket ));
226
227                rc.sync();
228   
229                cp.checkByteOrder();
230
231                osg::Matrix modelview;
232                cp.getModelView(modelview,camera_offset);
233               
234                viewer.setView(modelview);
235
236                if (cp.getMasterKilled())
237                {
238                    std::cout << "received master killed"<<std::endl;
239                    // break out of while (!done) loop since we've now want to shut down.
240                    masterKilled = true;
241                }
242            }
243            break;
244        default:
245            // no need to anything here, just a normal interactive viewer.
246            break;
247        }
248         
249        // fire off the cull and draw traversals of the scene.
250        if(!masterKilled)
251            viewer.frame();
252       
253    }
254
255    // wait for all cull and draw threads to complete before exit.
256    viewer.sync();
257
258    // if we are master clean up by telling all slaves that we're going down.
259    if (viewerMode==MASTER)
260    {
261        // need to broadcast my death.
262        CameraPacket cp;
263        cp.setPacket(osg::Matrix::identity(),viewer.getFrameStamp());
264        cp.setMasterKilled(true);
265
266        bc.setBuffer(&cp, sizeof( CameraPacket ));
267        bc.sync();
268
269        std::cout << "broadcasting death"<<std::endl;
270
271    }
272
273    return 0;
274}
Note: See TracBrowser for help on using the browser.