source: Swollen/swollen/main.cpp @ 132

Last change on this file since 132 was 132, checked in by darran, 19 years ago

Last release version changes

File size: 12.4 KB
Line 
1/*
2  SWWViewer
3
4  An OpenSceneGraph viewer for pyVolution SWW files.
5  copyright (C) 2004-2005 Geoscience Australia
6*/
7
8#include <iostream>
9#include <fstream>
10
11#include <osg/Group>
12#include <osg/Material>
13#include <osg/MatrixTransform>
14#include <osg/Notify>
15#include <osg/PositionAttitudeTransform>
16#include <osg/StateAttribute>
17#include <osgDB/FileNameUtils>
18
19#include <animation.h>
20#include <project.h>
21#include <SWWReader.h>
22#include <bedslope.h>
23#include <hud.h>
24#include <keyboardeventhandler.h>
25#include <directionallight.h>
26#include <state.h>
27#include <watersurface.h>
28#include <customviewer.h>
29#include <customargumentparser.h>
30
31// prototypes
32osg::Transform* createSky(float radius, const std::string filename);
33extern const char* version();
34
35
36int main( int argc, char **argv )
37{
38
39   // use an ArgumentParser object to manage the program arguments.
40   // this custom version detects if the last argument is a macro file
41   // and modifies the argument list accordingly so the following code works ...
42   CustomArgumentParser arguments( &argc, argv );
43
44
45   // set up the usage document
46   std::string appname = arguments.getApplicationName();
47   arguments.getApplicationUsage()->setDescription( appname );
48   arguments.getApplicationUsage()->setCommandLineUsage("swollen [options] swwfile ...");
49   arguments.getApplicationUsage()->addCommandLineOption("-help", "Display this information");
50   arguments.getApplicationUsage()->addCommandLineOption("-scale <float>", "Vertical scale factor");
51   arguments.getApplicationUsage()->addCommandLineOption("-tps <rate>", "Timesteps per second");
52   arguments.getApplicationUsage()->addCommandLineOption("-hmin <float>", "Height below which transparency is set to zero");
53   arguments.getApplicationUsage()->addCommandLineOption("-hmax <float>", "Height above which transparency is set to alphamax");
54   arguments.getApplicationUsage()->addCommandLineOption("-alphamin <float 0-1>", "Transparency value at hmin");
55   arguments.getApplicationUsage()->addCommandLineOption("-alphamax <float 0-1>", "Maximum transparency clamp value");
56   arguments.getApplicationUsage()->addCommandLineOption("-lightpos <float>,<float>,<float>", "x,y,z of bedslope directional light (z is up, default is overhead)");
57   arguments.getApplicationUsage()->addCommandLineOption("-movie <dirname>", "Save numbered images to named directory and quit");
58   arguments.getApplicationUsage()->addCommandLineOption("-loop", "Repeated (looped) playback of .swm files");
59   arguments.getApplicationUsage()->addCommandLineOption("-nosky", "Omit background sky");
60   arguments.getApplicationUsage()->addCommandLineOption("-cullangle <float angle 0-90>", "Cull triangles steeper than this value");
61   arguments.getApplicationUsage()->addCommandLineOption("-texture <file>", "Image to use for bedslope topography");
62   arguments.getApplicationUsage()->addCommandLineOption("-version", "Revision number and creation (not compile) date");
63
64
65   // construct the viewer.
66   CustomViewer viewer(arguments);
67
68
69   // set up with sensible default event handlers
70   viewer.setUpViewer( osgProducer::Viewer::STANDARD_SETTINGS );
71   viewer.setClearColor( osg::Vec4(DEF_BACKGROUND_COLOUR) );
72   //viewer.getCamera(0)->getRenderSurface()->setWindowRectangle(200,300,400,300);
73   viewer.getCullSettings().setComputeNearFarMode( osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES );
74
75
76   // animation
77   StateList statelist;
78   bool playbackmode;
79   bool recordingmode = false;
80   bool savemovie = false;
81   bool loop = false;
82   unsigned int playback_index = 0;
83   std::string moviedir;
84   Animation animation;
85
86   if( arguments.isSWM() )
87   {
88      playbackmode = true;
89      statelist.read( arguments.getFilename() );
90      if( arguments.read("-movie",moviedir) ) 
91      {
92         savemovie = true;  // flag to store frames and quit ...
93         animation.setDirectory( moviedir );
94         animation.setViewer( viewer );
95      }
96      if( arguments.read("-loop") ) 
97         loop = true;
98   }
99   else
100   {
101      playbackmode = false;
102      savemovie = false;
103      loop = true;  // playback in none macro mode should loop (otherwise you don't get a chance to save)
104   }
105
106
107   // get details on keyboard and mouse bindings used by the viewer
108   viewer.getUsage(*arguments.getApplicationUsage());
109
110   // if user requested help, write it out to cout
111   if( arguments.read("-help") || arguments.read("--help") || arguments.read("-h") )
112   {
113      arguments.getApplicationUsage()->write(std::cout);
114      return 1;
115   }
116
117
118   // same for version info
119   if( arguments.read("-version") )
120   {
121      std::cout << version() << std::endl;
122      return 1;
123   }
124
125
126   // last argument is either an sww file or an swm macro recording
127   int lastarg = arguments.argc()-1;
128   std::string swwfile = arguments.argv()[lastarg];
129   arguments.remove(lastarg);
130   if( osgDB::getLowerCaseFileExtension(swwfile) != std::string("sww") )
131   {
132      std::cout << "Require last argument be an .sww/.swm file ... quitting" << std::endl;
133      return 1; 
134   }
135   SWWReader *sww = new SWWReader(swwfile);
136   if (sww->isValid() == false)
137   {
138      std::cout << "Unable to load " << swwfile << " ... is this really an .sww file?" << std::endl;
139      return 1;
140   }
141
142
143   // relative directory to swollen binary
144   if( osgDB::getFilePath(argv[0]) == "" )
145      sww->setSwollenDir( std::string(".") );
146   else
147      sww->setSwollenDir( osgDB::getFilePath(argv[0]) );
148
149
150   // default arguments and command line parameters
151   float tmpfloat, tps, vscale;
152   if( !arguments.read("-tps", tps) || tps <= 0.0 ) tps = DEF_TPS;
153   if( !arguments.read("-scale", vscale) ) vscale = 1.0;
154   if( arguments.read("-hmin",tmpfloat) ) sww->setHeightMin( tmpfloat ); 
155   if( arguments.read("-hmax",tmpfloat) ) sww->setHeightMax( tmpfloat );     
156   if( arguments.read("-alphamin",tmpfloat) ) sww->setAlphaMin( tmpfloat );   
157   if( arguments.read("-alphamax",tmpfloat) ) sww->setAlphaMax( tmpfloat );
158   if( arguments.read("-cullangle",tmpfloat) ) sww->setCullAngle( tmpfloat );
159
160   std::string bedslopetexture;
161   if( arguments.read("-texture",bedslopetexture) ) sww->setBedslopeTexture( bedslopetexture );
162
163   // root node
164   osg::Group* rootnode = new osg::Group;
165
166   // transform
167   osg::PositionAttitudeTransform* model = new osg::PositionAttitudeTransform;
168   model->setName("position_attitude_transform");
169
170   // enscapsulates OpenGL state
171   osg::StateSet* rootStateSet = new osg::StateSet;
172
173   // Bedslope geometry
174   BedSlope* bedslope = new BedSlope(sww);
175
176   // Water geometry
177   WaterSurface* water = new WaterSurface(sww);
178
179   // Heads Up Display (text overlay)
180   HeadsUpDisplay* hud = new HeadsUpDisplay();
181   hud->setTitle("pyVolution SWW Viewer");
182   if( arguments.isSWM() )
183      hud->setMode("playback");
184
185
186   // Lighting
187   DirectionalLight* light = new DirectionalLight(rootStateSet);
188   light->setPosition( osg::Vec3(1,1,1) );  // z is up
189
190   std::string lightposstr;
191   while (arguments.read("-lightpos",lightposstr))
192   {
193      float x, y, z;
194      int count = sscanf( lightposstr.c_str(), "%f,%f,%f", &x, &y, &z );
195      if( count == 3 ) light->setPosition( osg::Vec3(x,y,z) );  // z is up
196      else osg::notify(osg::WARN) << "Invalid bedslope light position \"" << lightposstr << "\"" << std::endl;
197   }
198
199
200
201   // scenegraph hierarchy
202   rootnode->setStateSet(rootStateSet);
203   rootnode->addChild( hud->get() );
204   rootnode->addChild( light->get() );
205   rootnode->addChild(model);
206   model->addChild( bedslope->get() );
207   model->addChild( water->get() );
208
209
210   // allow vertical scaling from command line parameter
211   model->setScale( osg::Vec3(1.0, 1.0, vscale) );
212
213   // surrounding sky sphere
214   if( !arguments.read("-nosky") )
215      rootnode->addChild( createSky(10.0, sww->getSwollenDir() + std::string("/sky_small.jpg") ));
216
217
218   // add model to viewer.
219   viewer.setSceneData(rootnode);
220 
221   // any option left unread are converted into errors to write out later.
222   arguments.reportRemainingOptionsAsUnrecognized();
223 
224   // report any errors if they have occured when parsing the program aguments.
225   if (arguments.errors())
226   {
227      arguments.writeErrorMessages(std::cout);
228      return 1;
229   }
230
231
232   // register additional event handler
233   KeyboardEventHandler* event_handler = new KeyboardEventHandler(sww->getNumberOfTimesteps(), tps);
234   viewer.getEventHandlerList().push_front(event_handler);
235
236 
237   // create the windows and run the threads.
238   viewer.realize();
239
240
241   // initial camera position
242   CustomTerrainManipulator* terrainmanipulator = viewer.getTerrainManipulator();
243   terrainmanipulator->setNode( model );
244   terrainmanipulator->setAutoComputeHomePosition( false );
245   terrainmanipulator->setHomePosition(
246      osg::Vec3d(0,-3,3),    // camera location
247      osg::Vec3d(0,0,0),     // camera target
248      osg::Vec3d(0,1,1) );   // camera up vector
249   terrainmanipulator->moveToHome();
250   terrainmanipulator->enable();
251
252 
253   unsigned int timestep = 0;
254   bool done = false;
255   while( !done )
256   {
257   
258      // wait for all cull and draw threads to complete.
259      viewer.sync();
260
261      // user hits 'escape' to exit
262      if( viewer.done() )
263         done = true;
264
265
266      if( !playbackmode )
267      {
268
269         // current time
270         double time = viewer.getFrameStamp()->getReferenceTime();
271
272         event_handler->setTime( time );
273         timestep = event_handler->getTimestep();
274         water->setTimeStep(timestep);
275         hud->setTime( sww->getTime(timestep) );
276
277
278         // events
279         if( event_handler->toggleWireframe() )
280            water->toggleWireframe();
281         if( event_handler->toggleCulling() )
282            water->toggleCulling();
283
284         // '1' key starts/stops recording of view/position/setting info
285         if( event_handler->toggleRecording() )
286         {
287            switch( recordingmode )
288            {
289               case false : 
290                  recordingmode = true; 
291                  hud->setMode("recording");
292                  break;
293               case true : 
294                  recordingmode = false; 
295                  hud->setMode("");
296                  break;
297            }
298         }
299
300
301         // '2' key starts playback of recorded frames
302         if( event_handler->togglePlayback() && statelist.size() > 0 )
303         {
304            recordingmode = false;
305            playbackmode = true; 
306            hud->setMode("playback");
307            event_handler->setPaused( true );
308            playback_index = 0;
309         }
310
311         if( recordingmode )
312         {
313            State state = State();
314            state.setTimestep( event_handler->getTimestep() );
315            state.setCulling( sww->getCulling() );
316            state.setWireframe( water->getWireframe() );
317            state.setMatrix( viewer.getViewMatrix() );
318            statelist.push_back( state );
319         }
320      }
321
322      else
323
324      {
325         // might need to save image from previous pass ...
326         if( savemovie )
327            animation.saveImage( playback_index );
328
329         // in playback mode
330         State state = statelist.at( playback_index );
331         water->setTimeStep( state.getTimestep() );
332         water->setWireframe( state.getWireframe() );
333         water->setCulling( state.getCulling() );
334         hud->setTime( sww->getTime(state.getTimestep()) );
335
336         // loop playback
337         playback_index ++;
338         if( playback_index == statelist.size() )
339         {
340            if( loop )
341               playback_index = 0;
342            else
343               done = true;
344         }
345
346         // '2' key stops playback of recorded frames
347         if( event_handler->togglePlayback() )
348         {
349            playbackmode = false; 
350            hud->setMode("");
351            event_handler->setPaused( true );
352         }
353
354         viewer.setView( state.getMatrix() );
355      }
356
357
358      // '3' key causes compiled animation to be saved to disk
359      if( event_handler->toggleSave() )
360      {
361         std::fstream f;
362         f.open( "movie.swm", std::fstream::out );
363         if( f.is_open() )
364         {
365            f << "# SWM 1.0 START" << std::endl;
366            arguments.write( f );
367            statelist.write( f );
368            f << "# SWM END" << std::endl;
369            f.close();
370         }
371         std::cout << "Wrote macro file movie.swm" << std::endl;
372      }
373
374      // scene-graph updates
375      bedslope->update();
376      hud->update();
377      water->update();
378
379      // update the scene by traversing with the update visitor
380      viewer.update();
381
382      // fire off the cull and draw traversals of the scene.
383      viewer.frame();
384   }
385   
386   // wait for all cull and draw threads to complete before exit.
387   viewer.sync();
388
389   return 0;
390}
Note: See TracBrowser for help on using the repository browser.