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

Revision 3511, 8.4 kB (checked in by robert, 9 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.